Scrapy多请求数据聚合:将单品多色图片URL合并为单条JSON
解决方案
要实现单个商品的所有颜色图片URL聚合到同一条JSON记录,核心是通过Scrapy的meta参数传递商品的状态信息,逐步收集所有颜色的图片,待所有颜色处理完成后再统一输出记录。
修改后的完整代码
import scrapy class USSpider(scrapy.Spider): name = 'US' start_urls = ['https://tr.uspoloassn.com/sadece-online-erkek/?attributes_filterable_product_base_type=T-Shirt'] def parse(self, response): # 获取当前页码和总页数,修正循环范围确保包含最后一页 current_page = int(response.css('.js-product-list-load::attr(page)').extract_first()) total_pages = int(response.css('.js-product-list-load::attr(numpages)').extract_first()) for page_num in range(current_page, total_pages + 1): page_url = f"https://tr.uspoloassn.com/sadece-online-erkek/?attributes_filterable_product_base_type=T-Shirt&page={page_num}" yield scrapy.Request(url=page_url, callback=self.parse2) def parse2(self, response): # 简化商品链接遍历逻辑 for product_href in response.css('a.js-product-images-wrapper::attr(href)'): product_url = response.urljoin(product_href.get()) yield scrapy.Request(url=product_url, callback=self.parse3) def parse3(self, response): base_product_url = response.url # 提取并过滤颜色列表(去重+筛选以v开头的颜色) color_list = list(set(response.xpath('//*[@class="js-variant-area "]//a[@class="js-variant "]/@data-value').extract())) valid_colors = [color for color in color_list if color.lower().startswith('v')] if not valid_colors: # 无有效颜色时直接输出空图片列表的商品记录 yield { 'product_url': base_product_url, 'image_links': [] } return # 发起第一个颜色的请求,传递商品基础信息、剩余颜色和图片收集容器 first_color = valid_colors.pop() color_url = f"{base_product_url}?integration_color={first_color}" yield scrapy.Request( url=color_url, callback=self.parseImage, meta={ 'product_url': base_product_url, 'remaining_colors': valid_colors, 'all_images': [] } ) def parseImage(self, response): # 从meta中取出商品状态数据 product_url = response.meta['product_url'] remaining_colors = response.meta['remaining_colors'] all_images = response.meta['all_images'] # 收集当前颜色的图片链接 current_color_images = response.css("a.js-product-thumbnail::attr(data-image)").extract() all_images.extend(current_color_images) if remaining_colors: # 还有未处理的颜色,继续发起请求并更新状态 next_color = remaining_colors.pop() next_color_url = f"{product_url}?integration_color={next_color}" yield scrapy.Request( url=next_color_url, callback=self.parseImage, meta={ 'product_url': product_url, 'remaining_colors': remaining_colors, 'all_images': all_images } ) else: # 所有颜色处理完成,输出聚合后的商品记录 yield { 'product_url': product_url, 'image_links': all_images }
关键改动说明
- 状态传递:在
parse3中通过meta传递商品的基础URL、剩余未处理的颜色列表,以及用于收集图片的空列表,让每个parseImage请求能跟踪当前商品的处理进度。 - 逐步收集图片:每次处理完一个颜色的图片后,将其添加到总图片列表中,若还有剩余颜色则继续发起请求,直到所有颜色处理完毕。
- 统一输出:当商品的所有颜色都处理完成后,才输出包含该商品所有图片URL的单条JSON记录。
- 代码优化:简化了页码循环、商品链接遍历的逻辑,让代码更易读和维护。
内容的提问来源于stack exchange,提问作者mouhamad
相关产品推荐
相关产品推荐

