使用 Scrapy 抓取网页时 tbody 为空的问题及解决方案

使用 Scrapy 抓取网页时 tbody 为空的问题及解决方案

本文旨在解决在使用 scrapy 爬取网页数据时,XPath 表达式中包含 tbody 元素导致返回空数组的问题。通常,tbody 元素是由浏览器动态添加的,并不存在于原始 html 源码中。本文将提供绕过 tbody 元素直接提取所需数据的有效方法,并给出相应的 Scrapy Shell 示例。

在使用 Scrapy 进行网页抓取时,你可能会遇到这样的问题:你通过浏览器开发者工具检查元素时,发现某个元素位于 tbody 标签内,但在 Scrapy 中使用 XPath 表达式尝试提取该元素时,却得到了一个空数组。这通常是因为 tbody 元素是由浏览器在渲染页面时动态添加的,实际上并不存在于服务器返回的原始 HTML 源码中。

问题分析

浏览器为了更好地组织表格数据,会自动在 table 标签内插入 tbody 标签。然而,这个 tbody 标签并非总是存在于服务器返回的原始 HTML 中。当你使用 Scrapy 获取网页内容时,你得到的是原始 HTML,而不是浏览器渲染后的 dom 结构。因此,如果你的 XPath 表达式依赖于 tbody 标签,那么很可能会得到空结果。

解决方案

解决这个问题的方法是绕过 tbody 标签,直接定位到你想要提取的元素。以下提供两种常用的方法:

  1. 直接定位到 tr 元素:

    如果你的目标是提取表格中的所有行 (tr 元素),可以直接从包含表格的 div 元素开始,跳过 tbody 标签,直接定位到 tr 元素。

    例如,假设你的 HTML 结构如下:

    <div id="TableWithRules">   <table>     <thead>       <tr>         <th>Header 1</th>         <th>Header 2</th>       </tr>     </thead>     <tbody>       <tr>         <td>Row 1, Column 1</td>         <td>Row 1, Column 2</td>       </tr>       <tr>         <td>Row 2, Column 1</td>         <td>Row 2, Column 2</td>       </tr>     </tbody>   </table> </div>

    你可以使用以下 XPath 表达式来提取所有行:

    //div[@id='TableWithRules']//tr

    在 Scrapy Shell 中,你可以这样使用:

    scrapy shell https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=hp
    rows = response.xpath("//div[@id='TableWithRules']//tr") print(len(rows)) # 输出行数
  2. 跳过表头行:

    如果你的表格包含表头行 (th 元素),并且你只想提取数据行 (td 元素),可以使用 XPath 的谓词来过滤掉表头行。

    //div[@id='TableWithRules']//tr[td]

    这个 XPath 表达式会选择所有包含 td 元素的 tr 元素,从而排除表头行。

    在 Scrapy Shell 中,你可以这样使用:

    rows = response.xpath("//div[@id='TableWithRules']//tr[td]") print(len(rows)) # 输出数据行数

示例代码

以下是一个完整的 Scrapy 示例,展示了如何使用上述方法提取表格数据:

import scrapy  class MySpider(scrapy.Spider):     name = "mytablecrawler"     start_urls = ['https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=hp']      def parse(self, response):         rows = response.xpath("//div[@id='TableWithRules']//tr[td]")         for row in rows:             # 提取每一行的数据             data = row.xpath("./td/text()").getall()             yield {                 'column1': data[0] if len(data) > 0 else None,                 'column2': data[1] if len(data) > 1 else None,                 # ... 其他列             }

注意事项

  • 在编写 XPath 表达式时,务必仔细检查网页的 HTML 结构,并根据实际情况进行调整。
  • 如果网页的 HTML 结构比较复杂,可能需要使用更复杂的 XPath 表达式才能准确地提取到所需数据。
  • 有些网站可能会使用 JavaScript 动态生成表格数据,这种情况下,可能需要使用 Selenium 等工具来模拟浏览器行为,才能获取到完整的数据。

总结

当在使用 Scrapy 抓取网页数据时,遇到 tbody 为空的问题,不要慌张。首先要理解 tbody 元素可能并不存在于原始 HTML 源码中。然后,尝试绕过 tbody 标签,直接定位到你想要提取的元素。通过灵活运用 XPath 表达式,你就可以轻松地解决这个问题,并成功地抓取到所需的数据。

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享