
在使用 Scrapy 抓取网页数据时,XPath 表达式返回空数组是一个常见问题。本文将深入探讨 tbody 元素缺失导致 XPath 查询失败的原因,并提供绕过该问题的有效方法,帮助你成功提取目标数据。
在进行网络爬虫开发时,我们经常使用 Scrapy 框架来抓取网页数据。然而,有时我们可能会遇到 XPath 表达式返回空数组的情况,导致无法提取目标数据。一个常见的原因是 tbody 元素在网页的原始 HTML 源代码中不存在,而是由浏览器动态生成的。本文将针对这个问题提供详细的解决方案。
问题分析
许多网站的 HTML 结构中,表格的 tbody 元素并非显式存在于源代码中。浏览器在解析 HTML 时,会自动添加 tbody 元素,以规范表格结构。因此,直接使用包含 tbody 的 XPath 表达式进行查询,可能会导致 Scrapy 无法找到对应的元素,从而返回空数组。
例如,假设我们想要从 https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=hp 页面提取表格中的所有行。如果使用以下 XPath 表达式:
//div[@id='TableWithRules']//tbody/tr
在 Scrapy shell 中可能会发现返回的是一个空数组。这是因为页面的原始 HTML 源代码中并没有 tbody 元素。
解决方案
解决此问题的关键在于绕过 tbody 元素,直接查询 tr 元素。以下是两种可行的解决方案:
1. 直接查询 tr 元素
最简单的方法是直接查询 div[@id='TableWithRules'] 下的所有 tr 元素。
rows = response.xpath("//div[@id='TableWithRules']//tr")这将返回包含表头行的所有行。
2. 过滤表头行
如果需要排除表头行,可以使用 XPath 的谓词 [td] 来筛选包含 td 元素的 tr 元素。
rows = response.xpath("//div[@id='TableWithRules']//tr[td]")这将返回所有包含数据单元格的行,从而排除表头行。
示例代码
以下是一个完整的 Scrapy shell 示例,演示如何使用这两种方法:
scrapy shell https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=hp
# 直接查询所有行
rows = response.xpath("//div[@id='TableWithRules']//tr")
print(len(rows)) # 输出:3366
# 过滤表头行
rows = response.xpath("//div[@id='TableWithRules']//tr[td]")
print(len(rows)) # 输出:3365注意事项
- 在编写 XPath 表达式时,务必先检查网页的原始 HTML 源代码,确认元素的实际结构。
- 可以使用浏览器的开发者工具来检查元素的 XPath 路径。
- 如果网站使用 JavaScript 动态生成内容,可能需要使用 Scrapy 的 JavaScript 渲染中间件,如 Scrapy-Splash 或 Selenium,才能正确抓取数据。
总结
当使用 Scrapy 抓取网页数据时,遇到 XPath 表达式返回空数组的问题,首先要检查 tbody 元素是否存在于网页的原始 HTML 源代码中。如果 tbody 元素不存在,可以尝试绕过它,直接查询 tr 元素,或者使用 XPath 谓词来过滤不需要的行。通过这些方法,可以有效地解决 tbody 元素缺失导致的问题,成功提取目标数据。










