You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scrapy多URL爬取时JSON数据顺序混乱问题求助

解决Scrapy多URL爬取时JSON数据顺序混乱的问题

问题说明

单URL爬取时脚本运行正常,JSON结构符合预期;但爬取同站点多个URL时,少量URL结果顺序正常,URL数量增多后,JSON数据顺序偶发混乱(比如第三个URL的title提前出现在第二个URL的相关数据前)。

原因分析

Scrapy是异步并发框架,多个请求会同时处理,不同URL的响应返回时间不确定,导致yield输出的item顺序和start_urls中的顺序不一致。

解决方案

方案一:强制顺序爬取(适合小量URL)

修改Scrapy的settings.py文件,限制并发请求数为1,让爬虫逐个处理URL,保证item顺序和start_urls一致:

# settings.py
CONCURRENT_REQUESTS = 1
DOWNLOAD_DELAY = 0.5  # 可选,添加延迟避免触发站点反爬

优点:实现简单,不需要修改爬虫代码;缺点:牺牲并发效率,URL数量多时爬取速度变慢。

方案二:给Item添加URL标识,后续整理顺序(适合大量URL)

在每个输出的item中添加当前请求的URL字段,导出JSON后再按URL分组、按start_urls顺序重新整理数据,既保留并发效率,又能得到有序结果。

修改后的爬虫代码:

import scrapy


class QuotesSpider(scrapy.Spider):
    name = "attributes"
    start_urls = [
        "https://product.sanyglobal.com/concrete_machinery/truck_mixer/119/161/",
        "https://product.sanyglobal.com/concrete_machinery/truck_mixer/119/162/"
    ]

    def parse(self, response):
        current_url = response.url
        # 输出标题等基础信息
        yield {
            "url": current_url,
            "title": response.css("div.sku-top-title::text").get(),
            "desc": response.css("div.sku-top-desc::text").get(),
            "brochure": 'brochure'
        }
        # 输出折叠面板内容
        for post in response.css(".el-collapse"):
            headers = post.css(".el-collapse-item__header::text")
            desc_list = post.css(".value-el-desc")
            for i in range(len(headers)):
                res = ""
                x = desc_list[i].css(".value-el-desc p::text").extract()
                for y in x:
                    res += y.strip() + "&&"
                try:
                    yield {
                        "url": current_url,
                        "descTitle": headers[i].get().strip(),
                        "desc": res
                    }
                except:
                    continue
        # 输出参数内容
        for post in response.css(".lie-one-canshu"):
            try:
                yield {
                    "url": current_url,
                    "attribute": post.css('.lie-one-canshu::text')[0].get().strip()
                }
            except:
                continue

后续整理顺序的脚本:

导出JSON文件后,用以下脚本按start_urls顺序重新排列数据:

import json

# 读取原始JSON数据
with open('attributes.json', 'r', encoding='utf-8') as f:
    raw_items = json.load(f)

# 按URL分组存储item
url_item_map = {}
for item in raw_items:
    url = item["url"]
    if url not in url_item_map:
        url_item_map[url] = []
    url_item_map[url].append(item)

# 按照start_urls的顺序生成有序结果
target_order = [
    "https://product.sanyglobal.com/concrete_machinery/truck_mixer/119/161/",
    "https://product.sanyglobal.com/concrete_machinery/truck_mixer/119/162/"
]
sorted_items = []
for url in target_order:
    if url in url_item_map:
        sorted_items.extend(url_item_map[url])

# 保存整理后的JSON
with open('sorted_attributes.json', 'w', encoding='utf-8') as f:
    json.dump(sorted_items, f, ensure_ascii=False, indent=2)

方案三:自定义Item Pipeline维护顺序(复杂场景)

如果需要在爬虫内部直接保证输出顺序,可以自定义Pipeline。核心思路是维护一个队列,按照start_urls的顺序缓存每个URL的item,所有请求完成后再按顺序输出。这种方式实现相对复杂,适合对实时输出顺序有严格要求的场景。


内容的提问来源于stack exchange,提问作者Aghilesdza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 06:18:24