Scrapy遍历提取高尔夫球杆信息时重复返回同一值问题求助
问题分析:Scrapy抓取重复高尔夫球杆名称的原因
你用Scrapy抓取golftown.com的高尔夫挖起杆信息时,遇到同一名称重复输出38次的问题,核心原因出在XPath选择器的作用范围和循环内的选择对象上,具体拆解如下:
关键逻辑对比
课程示例代码的正确逻辑
示例中先获取所有书籍节点集合books,遍历每个book子节点时,通过book.css(...)从当前遍历的子节点内部提取数据,属于正确的「局部范围选择」:
import scrapy class Spiderbook0Spider(scrapy.Spider): name = "spiderbook0" allowed_domains = ["books.toscrape.com"] start_urls = ["https://books.toscrape.com"] def parse(self, response): books = response.css('article.product_pod') # 获取所有书籍节点 for book in books: # 遍历单个书籍节点 print(book.css('h3 a::text').get()) # 从当前book节点内提取数据
你的代码的问题点
你在循环里使用的response.xpath(...)是基于整个页面响应对象的全局选择器,//*[@class = 'name-link']/@title这个XPath会匹配页面中第一个符合条件的元素,所以每次循环都会返回同一个结果:
import scrapy class WedgepriceSpider(scrapy.Spider): name = "wedgeprice" allowed_domains = ["golftown.com"] start_urls = ["https://golftown.com/en-CA/clubs/wedges/"] def parse(self, response): wedges = response.css("div.product-tile-top > div.product-image > a.thumb-link ") for wedge in wedges: # 错误:用response.xpath会全局匹配第一个元素,而非当前wedge节点内的元素 print(response.xpath("//*[@class = 'name-link']/@title").get())
修正方案
需要把选择器的作用范围切换到当前遍历的wedge节点上,有两种可行方式:
方式1:调整XPath为局部范围查询
在XPath开头添加.,表示从当前wedge节点下开始查找:
def parse(self, response): wedges = response.css("div.product-tile-top > div.product-image > a.thumb-link ") for wedge in wedges: # 开头加.表示限定在当前wedge节点内查找 print(wedge.xpath(".//*[@class = 'name-link']/@title").get())
方式2:统一使用CSS选择器(更直观)
直接基于当前wedge节点,用CSS选择器提取目标属性:
def parse(self, response): # 可以直接选择包含目标元素的父节点,匹配更精准 wedges = response.css("div.product-tile") for wedge in wedges: print(wedge.css("a.name-link::attr(title)").get())
额外建议
- 可以先打印
len(wedges)确认节点数量是否和页面球杆数一致,验证节点选择是否正确 - 若要抓取价格,可沿用局部选择逻辑,例如
wedge.css("span.price::text").get()
内容的提问来源于stack exchange,提问作者Brian Hamilton
相关产品推荐
相关产品推荐

