Python中Scrapy框架使用XPath时匹配不到数据怎么办?
<table class="tabledataformat" cellspacing="0" >
<tr>
<td style="vertical-align:top;">Copper, Cu </td>
<td class="dataCell" style="vertical-align:top;"><= 0.03 %<span class="dataCondition"></span></td>
<td class="dataCell" style="vertical-align:top;"><= 0.03 %<span class="dataCondition"></span></td>
<td class="dataComment" style="vertical-align:top;"></td>
</tr>
</table>
response.xpath('//table[@class="tabledataformat"]/tr').extract() 只能获取到
<tr>
<td style="vertical-align:top;">Copper, Cu </td>
<td class="dataCell" style="vertical-align:top;"></td>
<td class="dataCell" style="vertical-align:top;"></td>
<td class="dataComment" style="vertical-align:top;"></td>
</tr>
<= 0.03 % 和 消失不见,为什么呢?
Python中Scrapy框架使用XPath时匹配不到数据怎么办?
遇到Scrapy用XPath匹配不到数据,先别急着怀疑人生,多半是这几个地方出了问题。我一般会按这个顺序排查:
1. 先确认网页结构 直接用浏览器开发者工具看源码不靠谱,因为JavaScript可能改变了DOM。在Scrapy的parse方法里加一行:
def parse(self, response):
print(response.text) # 或者保存到文件
with open('debug.html', 'w', encoding='utf-8') as f:
f.write(response.text)
看看你拿到的HTML是不是真的包含你要的数据。
2. 检查XPath语法 新手常犯的错:
- 路径不对:
//div[@class="content"]和//div[@class="content "](有空格)是两码事 - 用text()取文本时:
//h1/text()只取直接文本,子元素文本要用//h1//text()或//h1/string() - 属性值包含部分内容:用
contains(),比如//div[contains(@class, "item")]
3. 处理动态加载 如果数据是JS动态加载的,XPath肯定抓不到。这时候要么:
- 找隐藏的API接口(Network面板看XHR请求)
- 用Selenium或Playwright渲染页面
- 用Splash(如果项目在用)
4. 试试CSS选择器 有时候XPath写起来复杂,CSS反而简单:
# XPath
response.xpath('//div[@id="main"]/ul/li/a/@href').getall()
# CSS等价写法
response.css('#main ul li a::attr(href)').getall()
5. 用scrapy shell调试 这是最实用的调试方式:
scrapy shell "http://example.com"
# 然后直接在里面试XPath
>>> response.xpath('//title/text()').get()
实际案例:
昨天我刚遇到一个,页面显示有数据,但XPath就是匹配不到。后来发现响应里有个<iframe>,数据在iframe里。解决方案:
# 先获取iframe的src
iframe_url = response.xpath('//iframe/@src').get()
yield scrapy.Request(iframe_url, callback=self.parse_iframe)
总结建议:从响应源码、XPath语法、动态加载三方面排查。
这部分数据可能是 javascript 异步请求显示的,也就是 ajax 内容, scrapy 是看不到的。
‘’’
<tr> <td style=“vertical-align:top;”>Copper, Cu </td> <td class=“dataCell” style=“vertical-align:top;”><= 0.03 %<span class=“dataCondition”></span></td> <td class=“dataCell” style=“vertical-align:top;”><= 0.03 %<span class=“dataCondition”></span></td> <td class=“dataComment” style=“vertical-align:top;”></td> </tr>
’’'
测试 lxml 能输出, scrapy 应该也没问题,查看 html 源码吧
scrapy 爬下来用 beautifulsoup 处理,我觉得方便些


