如何处理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
相关产品推荐
相关产品推荐

