Scrapy调用Selector.css匹配元素返回空列表问题咨询
问题根因
这个问题10次有9次是浏览器渲染后的DOM结构和Scrapy拿到的原始HTML结构不一致导致的,元凶就是你复制的选择器里包含的tbody标签:
- 绝大多数网站编写HTML时,不会手动给
<table>标签添加<tbody>子节点,直接在table下写<tr>行。但浏览器按照W3C规范渲染页面时,会自动给没有tbody的table补上这个节点,你右键复制选择器的时候,会把这个浏览器自动生成的、源码里根本不存在的节点也抄进选择器里。 - 你在Chrome控制台用
$$()能正常匹配,是因为控制台操作的是浏览器已经渲染完成、补全所有节点、跑完JS后的DOM树;但Scrapy的Selector是直接对请求拿到的原始HTML文本做解析,既不会运行JS,也不会帮你补浏览器才会加的节点,路径里多了不存在的tbody,自然返回空列表。
剩下10%的可能是你用的超长绝对路径里的div:nth-child(1)层级在原始HTML里位置不对——浏览器复制的选择器是从最外层节点开始数的绝对路径,只要中间某一层节点在源码里的顺序、标签名和浏览器渲染后的有差异,整个路径就会失效。
修复方案
- 第一步先删掉选择器里的
> tbody片段,先做测试:
def parse(self, response): sel = scrapy.Selector(response) items_list = sel.css('#main > div.containerbox.boxindex > div.layui-row.layui-col-space15 > div:nth-child(1) > table > tr')
绝大多数情况改完这一步就能正常拿到结果。
2. 如果还是匹配不到,直接放弃浏览器复制的超长绝对选择器,这种选择器容错率极低,页面稍微调整一个div层级就会失效。建议自己写短的、基于特征定位的选择器,比如跳过中间不稳定的div层级,直接靠容器的class定位目标表格再找行:
# 只要目标table在class为containerbox boxindex的div下,就能匹配到,不依赖中间嵌套层级 items_list = sel.css('div.containerbox.boxindex table tr')
- 后续调试选择器时,不要完全信浏览器Elements面板里的DOM结构,一定要先打印
response.text,在原始返回的HTML内容里确认节点的真实嵌套关系——Elements面板展示的是渲染后的最终结果,和爬虫拿到的原始内容经常存在差异。
内容的提问来源于stack exchange,提问作者user15217679
相关产品推荐
相关产品推荐

