Scrapy爬取CoinMarketCap表格第10行后返回None,组合XPath未生效?
核心问题定位
- 你观察到的第10行之后元素class变动是问题的核心诱因:目标网站对表格采用了分块渲染逻辑,前10行是首屏静态渲染的DOM结构,后90行是懒加载的动态渲染结构,两套结构的节点层级完全不同,单一XPath自然无法覆盖全量行。
- 之前尝试的
or写法完全无效的两个具体原因:- 把
or写进XPath路径链:XPath中的or是布尔逻辑运算符,仅用于判断节点是否满足条件,不会跨规则提取对应节点的文本,直接写在路径中会返回逻辑判断值,根本获取不到文本节点。 - 用Python层面的
or拼接两个XPath字符串:两个非空字符串做Python逻辑或运算时,会直接返回第一个字符串,相当于永远只执行第一套XPath规则,完全覆盖不到第二套结构的匹配逻辑。
- 把
修复方案
关键修正点
- 把XPath里用于合并匹配规则的
or换成XPath专用的节点并集运算符|:这个运算符的作用是把两个路径匹配到的所有节点合并成一个集合返回,刚好适配你遇到的“行结构分叉”的场景——每一行只会符合两套结构中的一种,匹配时不会出现冲突。 - 去掉所有依赖元素class的选择规则,只基于标签层级、固定位置的td序号做匹配,从根本上规避class变动导致的匹配失效问题。
- 不强制在XPath中加入
tbody标签选择器,直接通过table//tr的跨层级定位,兼容源码里有没有写tbody、浏览器自动补全tbody的所有场景。
可直接运行的代码
def parse(self, response): # 定位表格内的有效数据行,排除第一行表头 rows = response.xpath('//table//tr[position() > 1]') for row in rows: # 用|合并两套适配不同结构的文本提取规则 currency = row.xpath( './/td[3]/div/a/div/div/p/text() | .//td/a/span[2]/text()' ).get() if currency: yield { 'currency': currency.strip() }
额外排查提醒
如果调整XPath后仍只能拿到10行数据,说明不是XPath的问题:目标网站的表格采用了虚拟滚动机制,初始静态响应里根本没有后90行的DOM结构,需要先确认响应HTML中提取到的tr总数量是否达到100行,再调整请求参数拉取全量页面内容。
内容的提问来源于stack exchange,提问作者Jacob
相关产品推荐
相关产品推荐

