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

如何处理Scrapy因robots.txt阻止爬取的异常并返回提示?

嘿,刚好我在Scrapy 1.5版本里处理过一模一样的需求!给你两个实用的方案,都能完美适配Python 3.5.2:

方案1:爬虫启动前主动检查robots.txt规则

这个思路是在爬虫正式开始爬取前,先去拉取目标网站的robots.txt,手动解析规则判断是否允许我们的爬虫访问。如果被禁止,直接弹出提示并终止爬虫,省得做无用功。

直接上代码示例,你可以直接套到自己的爬虫里:

from scrapy.spiders import Spider
from scrapy.utils.robotparser import RobotFileParser
from scrapy.exceptions import CloseSpider
import scrapy

class YourSpider(Spider):
    name = 'your_spider'
    # 这里替换成用户指定的网站URL
    start_urls = ['https://user-specified-site.com']  

    def start_requests(self):
        # 初始化robots规则解析器
        robot_parser = RobotFileParser()
        # 拼接robots.txt的完整URL(避免手动拼接出错)
        base_domain = '/'.join(self.start_urls[0].split('/')[:3])
        robot_parser.set_url(f"{base_domain}/robots.txt")
        robot_parser.read()

        # 获取当前爬虫使用的User-Agent(优先取settings里配置的)
        user_agent = self.settings.get('USER_AGENT', 'Scrapy/1.5.0 (+https://scrapy.org)')

        # 检查是否允许爬取起始URL
        if not robot_parser.can_fetch(user_agent, self.start_urls[0]):
            # 弹出用户要的提示
            print("您输入的网站因robots.txt禁止爬取")
            # 直接终止爬虫
            raise CloseSpider(reason='Blocked by robots.txt')
        
        # 检查通过,正常发起爬取请求
        for url in self.start_urls:
            yield scrapy.Request(url, callback=self.parse)

    def parse(self, response):
        # 这里写你原本的页面解析逻辑
        pass

注意点:

  • 确保你的settings.py里ROBOTSTXT_OBEY设为True(默认就是True),这样和我们的手动检查逻辑不冲突。
  • 代码里的URL拼接方式能适配大多数网站,避免出现https://site.comrobots.txt这种错误地址。

方案2:通过扩展监听被robots.txt拦截的请求

如果你的爬虫是动态生成URL的(比如从页面里提取新链接),或者想监控所有被robots规则拦截的请求,那这个方案更合适。我们可以写一个Scrapy扩展,监听request_dropped信号——当请求因为robots.txt被丢弃时,自动触发提示。

步骤1:创建扩展文件

在你的Scrapy项目里新建extensions.py,写入以下代码:

from scrapy import signals
from scrapy.exceptions import NotConfigured

class RobotsBlockedAlertExtension:
    def __init__(self, crawler):
        self.crawler = crawler
        # 绑定request_dropped信号,监听被丢弃的请求
        crawler.signals.connect(self.on_request_dropped, signal=signals.request_dropped)

    @classmethod
    def from_crawler(cls, crawler):
        # 只有当ROBOTSTXT_OBEY开启时,才启用这个扩展
        if not crawler.settings.getbool('ROBOTSTXT_OBEY'):
            raise NotConfigured('请先在settings中开启ROBOTSTXT_OBEY')
        return cls(crawler)

    def on_request_dropped(self, request, spider, reason):
        # 判断请求被丢弃的原因是否是robots.txt拦截
        if reason == 'robots.txt':
            print("您输入的网站因robots.txt禁止爬取")
            # 如果你想直接终止爬虫,取消下面这行注释
            # self.crawler.engine.close_spider(spider, reason='Blocked by robots.txt')

步骤2:启用扩展

在settings.py里添加以下配置,注册我们的扩展:

EXTENSIONS = {
    # 替换成你的项目路径,比如'your_project.extensions.RobotsBlockedAlertExtension'
    'your_project.extensions.RobotsBlockedAlertExtension': 500,
}
# 确保这个配置是True(默认就是)
ROBOTSTXT_OBEY = True

这个方案的优势是能覆盖所有被robots规则拦截的请求,不管是起始URL还是后续动态生成的链接,只要被拦截就会触发提示。

选哪个?

  • 如果只需要检查用户指定的起始网站是否被禁止,方案1足够简单直接;
  • 如果爬虫会动态生成大量链接,需要全程监控robots拦截情况,选方案2更靠谱。

两种方案都能完美满足你的需求,根据自己的爬虫逻辑选就行~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:01:07