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

Scrapy如何编写自定义中间件自动从谷歌表格加载start_urls

实现方案

不需要在每个爬虫中单独编写URL读取逻辑,也不需要针对单个爬虫做适配,通过全局Spider中间件配合Scrapy内置的爬虫启动信号,即可实现一次配置、所有爬虫自动从谷歌表格读取链接填充start_urls,具体实现步骤如下:

1. 编写全局Spider中间件

打开项目目录下的middlewares.py文件,新增如下中间件类:

import gspread
from oauth2client.service_account import ServiceAccountCredentials
from scrapy import signals
from scrapy.exceptions import NotConfigured

class GoogleSheetStartUrlsMiddleware:
    def __init__(self, sheet_name, worksheet_index, url_column, creds_path):
        self.sheet_name = sheet_name
        self.worksheet_index = worksheet_index
        self.url_column = url_column
        # 初始化谷歌表格客户端,整个爬虫运行周期仅连接一次,避免重复鉴权
        scope = [
            'https://spreadsheets.google.com/feeds',
            'https://www.googleapis.com/auth/drive'
        ]
        creds = ServiceAccountCredentials.from_json_keyfile_name(creds_path, scope)
        self.client = gspread.authorize(creds)

    @classmethod
    def from_crawler(cls, crawler):
        # 读取全局开关,未开启时不加载该中间件
        if not crawler.settings.getbool('ENABLE_GOOGLE_SHEET_START_URLS'):
            raise NotConfigured
        # 从配置文件读取表格参数,默认值与你现有代码保持一致
        sheet_name = crawler.settings.get('GOOGLE_SHEET_NAME', 'Sheet_1')
        worksheet_index = crawler.settings.getint('GOOGLE_SHEET_WORKSHEET_INDEX', 0)
        url_column = crawler.settings.getint('GOOGLE_SHEET_URL_COLUMN', 2)
        creds_path = crawler.settings.get('GOOGLE_SHEET_CREDS_PATH', 'token.json')
        
        instance = cls(sheet_name, worksheet_index, url_column, creds_path)
        # 绑定爬虫启动信号,爬虫初始化完成后自动执行URL注入
        crawler.signals.connect(instance.inject_start_urls, signal=signals.spider_opened)
        return instance

    def inject_start_urls(self, spider):
        # 支持单个爬虫跳过全局注入:在爬虫类中加属性 use_google_sheet_start_urls = False 即可
        if getattr(spider, 'use_google_sheet_start_urls', True) is False:
            return
        # 读取指定列的所有链接
        sheet = self.client.open(self.sheet_name)
        sheet_instance = sheet.get_worksheet(self.worksheet_index)
        raw_links = sheet_instance.col_values(col=self.url_column)
        # 过滤空值、去除首尾空格、去重,避免无效请求和重复抓取
        valid_links = []
        seen = set()
        for link in raw_links:
            link = link.strip()
            if link and link not in seen:
                valid_links.append(link)
                seen.add(link)
        # 注入链接到start_urls:默认追加到爬虫原有start_urls后做全局去重
        if hasattr(spider, 'start_urls'):
            spider.start_urls.extend(valid_links)
            spider.start_urls = list(set(spider.start_urls))
        else:
            spider.start_urls = valid_links

2. 注册中间件并添加配置

打开项目的settings.py文件,做两处配置:

  1. 将新增的中间件加入SPIDER_MIDDLEWARES列表,优先级数值建议设为50(低于默认中间件优先级),保证在请求生成前完成URL注入:
SPIDER_MIDDLEWARES = {
    # 保留原有已配置的中间件,新增下面这行
    '你的项目名.middlewares.GoogleSheetStartUrlsMiddleware': 50,
}

注意将你的项目名替换为你本地Scrapy项目的实际目录名称

  1. 添加功能开关和表格参数配置,默认值与你现有代码完全匹配,可按需修改:
# 全局开关,设为False即可一键关闭所有爬虫的表格URL自动注入
ENABLE_GOOGLE_SHEET_START_URLS = True
# 谷歌表格配置项
GOOGLE_SHEET_NAME = 'Sheet_1'
GOOGLE_SHEET_WORKSHEET_INDEX = 0
GOOGLE_SHEET_URL_COLUMN = 2
GOOGLE_SHEET_CREDS_PATH = 'token.json'

使用说明

  • 配置完成后,执行scrapy crawl 爬虫名启动任意爬虫时,都会自动读取谷歌表格中的链接填充到start_urls,不需要在单个爬虫文件中编写任何读取逻辑
  • 如果某个特殊爬虫不需要加载表格中的链接,只需要在对应爬虫类中添加一行属性即可跳过全局逻辑:
    class SpecialSpider(scrapy.Spider):
        name = 'special_spider'
        use_google_sheet_start_urls = False # 加这行就不会注入表格链接
        start_urls = ['https://example.com'] # 仅使用爬虫内定义的起始链接
    
  • 如果你希望完全使用表格中的链接、忽略爬虫文件内手动写的start_urls,只需要把inject_start_urls方法中的链接赋值逻辑替换为直接赋值即可:
    # 注释掉原来的if/else判断,直接给start_urls赋值
    spider.start_urls = valid_links
    

不推荐用下载中间件实现该需求:下载中间件的作用是处理发起请求后的请求/响应逻辑,起始URL注入属于爬虫初始化阶段的操作,用Spider中间件配合spider_opened信号实现,整个爬虫运行周期仅读取一次表格,性能最优。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:48:18