【问题标题】:Trouble scraping data out of a table from a webpage无法从网页中的表格中抓取数据
【发布时间】:2017-08-01 12:17:48
【问题描述】:

我在 python 中结合 selenium 编写了一个脚本,以从位于网页 (finance.yahoo) 中的某个表中抓取数据。但是,当我执行它时,我得到一个错误。我不知道我是否犯了任何错误。 FYC,我目前写的都贴在下面了。

我正在尝试的脚本:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()

driver.get("https://finance.yahoo.com/")
wait = WebDriverWait(driver, 10)

wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "table.tbl tbody")))
items = driver.find_element_by_css_selector("table.tbl tbody")
list_of_data = [[item.text for item in data.find_elements_by_css_selector('td')]
                    for data in items.find_elements_by_css_selector('tr')]
for tab_data in list_of_data:
    print(tab_data) 

driver.quit()

我的脚本抛出的错误:

line 80, in until
    raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message: 

表格数据所在元素的部分部分:

<table cellspacing="0" cellpadding="0" border="0" width="100%" class="tbl">
                <tbody>
                    <tr><th class="pr">Loan Type</th><th class="rate">Today</th><th class="ch">Change</th><th class="lw">Last&nbsp;Week</th></tr>
                    <tr class="">
                        <td class="pr"><a target="_top" rel="nofollow" href="https://finance.yahoo.com/rates">30 yr fixed</a></td>
                        <td class="rate">3.82%</td>
                        <td class="ch"><div class="arrow-up"></div></td>
                        <td class="lw">3.80%</td>
                    </tr>
                    <tr class="bk ">
                        <td class="pr"><a target="_top" rel="nofollow" href="https://finance.yahoo.com/rates/mortgage/15-year-fixed">15 yr fixed</a></td>
                        <td class="rate">3.01%</td>
                        <td class="ch"><div class="arrow-down"></div></td>
                        <td class="lw">3.05%</td>
                    </tr>
                </tbody>
            </table>

【问题讨论】:

  • 增加超时时间
  • 感谢 Gaurang Shah 的建议。增加了时间并执行但没有运气。仍然有同样的错误。
  • 检查元素是否在任何框架内
  • 我在https://finance.yahoo.com/ 上找不到(By.CSS_SELECTOR, "table.tbl tbody") 的任何元素,谢谢。您的确切手动步骤是什么?谢谢

标签: python python-3.x selenium selenium-webdriver web-scraping


【解决方案1】:

这是您问题的答案:

查看您提供的 HTML,我假设您正在尝试抓取表格 Rates,表格标题为 Loan TypeTodayChangeLast Week。但我仍然不确定您希望以哪种格式报废数据。

Rates 表位于名为 bankrate-overnight-averageiframe 中。所以我们需要先切换到frame,然后再刮table。以下是用于抓取 Rates 表的工作代码块,但您的抓取逻辑未更改:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument("start-maximized")
options.add_argument("disable-infobars")
options.add_argument("--disable-extensions")
driver = webdriver.Chrome(chrome_options=options, executable_path=r'C:\\Utility\\BrowserDrivers\\chromedriver.exe')
driver.get("https://finance.yahoo.com/")
wait = WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.NAME, "bankrate-overnight-average")))
items = driver.find_element_by_css_selector("table.tbl tbody")
list_of_data = [[item.text for item in data.find_elements_by_css_selector('td')]
            for data in items.find_elements_by_css_selector('tr')]
for tab_data in list_of_data:
    print(tab_data)

我的控制台上的输出显示为:

[]
['30 yr fixed', '3.82%', '', '3.80%']
['15 yr fixed', '3.01%', '', '3.05%']
['30 yr fixed refi', '3.80%', '', '3.77%']
['15 yr fixed refi', '2.97%', '', '3.02%']
['30 yr jumbo', '4.04%', '', '4.06%']
['5/1 ARM refi', '3.25%', '', '3.23%']

如果这能回答您的问题,请告诉我。

【讨论】:

  • 天哪!!!你终于做到了。感谢 DebanjanB 的有效回答。我要拿出我的答案。顺便说一句,你能给我一个简单的解释吗——当我试图用“tbl”类解析同一个表但不能解析时,我的脚本出了什么问题。谢谢。一会儿会接受你的回答。
  • @Shahin 很高兴能为您提供帮助 :) with your scrapping logic unchanged
  • 是的,确实如此。顺便说一句,看到你的回答,我发现它也可以使用一个班轮来实现--driver.switch_to_frame("bankrate-overnight-average") 。再次感谢。
  • @Shahin 有一点。访问https://finance.yahoo.com/ 涉及大量JavaScript 和AJAX 调用,因此我们不确定预期的frame 的可用性是否会在实现document.ready 状态=complete 之前或之后发生。因此我选择了行之有效的方法。
【解决方案2】:

我访问了 url 并检查了页面元素,并且没有 className 为 'tbl' 的表元素,这就是驱动程序无法定位元素并超时的原因。只需尝试从以下行中删除 .tbl:

wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "table.tbl tbody")))
items = driver.find_element_by_css_selector("table.tbl tbody")

此外,由于 items 将是一个列表对象,因此 find_elements_by_css_selector() 方法将不适用于它,因此您可能会收到错误。

【讨论】:

  • 感谢 Anoop Sharma 的回答。如果我尝试你所说的,我会从第一个空白表中获取数据,然后在我的脚本中设置表索引,我会得到第二个,依此类推。但是,我想刮掉我上面提到的那个特定的表。仅供参考,如果您查看上面的元素,您会看到有一个名为“tbl”的类。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多