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

如何让Scrapy按顺序抓取指定列表中的链接?

解决Scrapy爬虫链接抓取顺序问题

Scrapy的异步并发特性会导致请求完成顺序和发送顺序不一致,要保证rankings["Men's Pound-for-Pound"]中的链接按原顺序抓取并输出结果,有两种可行方案:

方案一:限制并发数为1(简单但效率低)

通过强制Scrapy一次只处理一个请求,确保链接按顺序被抓取。可以在爬虫类中添加自定义配置,或者修改项目的settings.py:

修改爬虫类代码

class FighterSpiderSpider(scrapy.Spider):
    name = 'fighter_spider'
    allowed_domains = ['www.ufc.com.br']
    start_urls = ['https://www.ufc.com.br/rankings']
    
    # 添加自定义设置,限制并发
    custom_settings = {
        'CONCURRENT_REQUESTS': 1,
        'CONCURRENT_REQUESTS_PER_DOMAIN': 1
    }

    def parse(self, response):
        all_rankings = response.css('div.view-grouping').getall()
        champions = {Selector(text=x).css('div.view-grouping div.info h4::text').get().strip() : Selector(text=x).css('a::attr(href)').get() for x in all_rankings}
        rankings = {Selector(text=x).css('div.info h4::text').get().strip() : Selector(text=x).css('a::attr(href)').getall() for x in all_rankings}

        if self.ranking == "p4p male":
            for link in rankings["Men's Pound-for-Pound"]:
                yield response.follow(link, callback=self.parse_date)

这种方法适合数据量较小的场景,爬取速度会变慢,但能直接保证顺序。

方案二:携带顺序索引,最终排序输出(高效推荐)

不改变并发效率,给每个请求带上原列表中的索引,在数据处理阶段记录索引,最后通过Pipeline按索引排序输出。

步骤1:修改parse方法,传递索引

def parse(self, response):
    all_rankings = response.css('div.view-grouping').getall()
    champions = {Selector(text=x).css('div.view-grouping div.info h4::text').get().strip() : Selector(text=x).css('a::attr(href)').get() for x in all_rankings}
    rankings = {Selector(text=x).css('div.info h4::text').get().strip() : Selector(text=x).css('a::attr(href)').getall() for x in all_rankings}

    if self.ranking == "p4p male":
        # 用enumerate获取每个链接的索引,存入meta
        for idx, link in enumerate(rankings["Men's Pound-for-Pound"]):
            yield response.follow(link, callback=self.parse_date, meta={'order': idx})

步骤2:在parse_date中记录索引

def parse_date(self, response):
    # 从meta中取出顺序索引
    order = response.meta['order']
    # 提取页面数据(示例,根据实际需求调整)
    fighter_info = {
        'order': order,
        'name': response.css('h1.fighter-name::text').get().strip(),
        # 其他需要抓取的字段...
    }
    yield fighter_info

步骤3:编写Pipeline排序并保存

在项目的pipelines.py中添加排序Pipeline:

import json

class SortByOrderPipeline:
    def __init__(self):
        self.item_list = []

    def process_item(self, item, spider):
        self.item_list.append(dict(item))
        return item

    def close_spider(self, spider):
        # 按order字段从小到大排序
        sorted_items = sorted(self.item_list, key=lambda x: x['order'])
        # 保存到JSON文件(可根据需求改为其他格式)
        with open('sorted_fighters.json', 'w', encoding='utf-8') as f:
            json.dump(sorted_items, f, ensure_ascii=False, indent=2)

步骤4:启用Pipeline

在settings.py中配置:

ITEM_PIPELINES = {
    'your_project_name.pipelines.SortByOrderPipeline': 300,
}

这种方法保留了Scrapy的并发优势,同时能确保最终输出结果按原链接顺序排列,适合大多数场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 20:11:46