Scrapy爬取如何正确关联<ul>与<li>?分类子项匹配异常解决
解决Scrapy爬取中分类与子项不匹配的问题
我看了你的代码和HTML结构,问题出在你把主分类和子项容器分开收集后按索引硬关联,但没考虑它们的层级结构,还误用了全局XPath(//)导致选取范围混乱。
问题根源
原代码的核心错误:
- 用
out_box.xpath('//li[@class="font-size-3 color-yellow main-list-li"]')时,//会从整个页面选取所有符合的li,而非在out_box内部按结构关联的li; - 同理,
out_box.xpath('//ul[@class="list-inline main-list-ul"]')也是全局抓取所有ul,再通过i += 1按顺序绑定主分类。但实际上每个主分类(比如Living room)后面跟着多个ul,这种按索引硬匹配的方式必然导致错位,最终所有子项都绑定到第一个主分类。
修复方案
正确思路是跟着HTML结构的层级走:先定位每个主分类li,再直接抓取它后面属于该分类的所有子ul,这样就能严格保证分类和子项的对应关系。
修改后的parse_item方法代码如下:
def parse_item(self, response): cat = response.meta["cat"] out_box = response.xpath('//div[@class="row margin-b2"]') # 遍历每个主分类标签(比如Living room、Bed room) for main_cat_li in out_box.xpath('.//li[@class="font-size-3 color-yellow main-list-li"]'): sub_cat = main_cat_li.xpath('./text()').extract_first().strip() print(f"当前主分类: {sub_cat}") # 抓取当前主分类后面的所有同级子ul(仅匹配指定class的ul) sub_uls = main_cat_li.xpath('./following-sibling::ul[@class="list-inline main-list-ul"]') # 遍历每个子ul容器 for sub_ul in sub_uls: # 在当前ul内抓取所有子项链接(用.//限定范围,避免全局抓取) for url_box in sub_ul.xpath('.//li[@class="list-inline-item main-list-li-w align-text-top"]//a'): new_url = url_box.xpath('./@href').extract_first() if new_url: yield scrapy.Request( new_url, meta={"url": new_url, "cat": cat, "sub_cat": sub_cat}, callback=self.parse_item_info )
关键改进点
- 用相对XPath(
.//):限定选取范围在当前节点内部,避免全局抓取无关元素; - 层级关联抓取:通过
following-sibling::ul直接绑定当前主分类的子ul,从根源上保证分类与子项的对应; - 用
extract_first()替代extract()[0]:更安全,避免节点不存在时出现索引越界错误。
这样修改后,parse_item_info里的sub_cat就能正确对应每个子项的所属分类,比如Chair、Sofa对应Living room,Bed、Mirror对应Bed room。
内容的提问来源于stack exchange,提问作者jdleung
相关产品推荐
相关产品推荐

