Scrapy爬虫处理返回404状态码的广告页面问题求助
最近爬某网站的时候遇到个头疼的问题:页面里的广告内容能正常加载,但请求广告链接时总是返回404,导致Scrapy生成不了对应的Item。更奇怪的是,在Scrapy Shell里请求这些广告链接,重试10次后能拿到有效响应,但用scrapy crawl myspider跑爬虫时,广告链接只被请求一次,根本拿不到有效响应。贴一下随机出现的错误日志:
2019-07-30 15:33:51 [scrapy] DEBUG: Retrying <GET https://www.classifiedads.com/homes_for_sale/57c10snzt1wzz> (failed 1 times): 404 Not Found
2019-07-30 15:33:51 [scrapy] DEBUG: Retrying <GET https://www.classifiedads.com/homes_for_sale/49zbgqvx21wzz> (failed 1 times): 404 Not Found
2019-07-30 15:33:51 [scrapy] DEBUG: Retrying <GET https://www.classifiedads.com/homes_for_sale/49482b3hq1wzz> (failed 1 times): 404 Not Found
我的爬虫代码如下:
class MySpider(CrawlSpider): name = 'myspider' start_urls = [ 'https://www.classifiedads.com/search.php?keywords=&cid=468&lid=rx10&lname=India&from=s&page=1', 'https://www.classifiedads.com/search.php?keywords=&cid=18&lid=rx10&lname=India&page=1' ] rules = ( Rule(LinkExtractor(allow=(r'https://www.classifiedads.com/search.php\?keywords=&cid=468&lid=rx10&lname=India&from=s&page=\d+',)), callback='parse_page', follow=True), Rule(LinkExtractor(allow=(r'https://www.classifiedads.com/search.php\?keywords=&cid=18&lid=rx10&lname=India&page=\d+',)), callback='parse_page', follow=True) ) headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36', 'upgrade-insecure-requests': 1, } def parse_page(self, response): items = response.css('div#results div.resultitem div a::attr(href)').getall() if items: for item in items: if item.startswith('//www.classifiedads.com/'): yield scrapy.Request( url='https:{}'.format(item), method='GET', headers=self.headers, callback=self.parse_items ) def parse_items(self, response): # scraping the items的内容
问题分析与解决办法
1. 全局调整重试次数(最直接的解决方式)
Scrapy默认的重试次数是2次(也就是失败1次后重试1次),这和你在Shell里手动重试10次的情况不一样。你可以在settings.py里修改全局配置,把重试次数调到和Shell里一致:
# settings.py RETRY_TIMES = 10 # 设置重试10次,总共会发起11次请求(1次初始+10次重试) RETRY_HTTP_CODES = [404, 500, 502, 503, 504] # 确保404状态码被纳入重试范围(默认已包含,可确认)
2. 针对单个请求单独设置重试参数
如果不想全局修改所有请求的重试次数,只想给广告链接的请求单独配置,可以在生成scrapy.Request时添加meta参数:
yield scrapy.Request( url='https:{}'.format(item), method='GET', headers=self.headers, callback=self.parse_items, meta={'retry_times': 10} # 仅让这个请求重试10次 )
3. 优化请求头与Cookie配置
有时候网站会根据请求头或会话Cookie判断请求合法性,你可以试试:
- 在
settings.py里全局设置User-Agent,替代单个Request里的设置:
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
- 确保Cookie中间件开启,维持会话状态:
COOKIES_ENABLED = True
4. 添加下载延迟避免被限制
频繁请求可能会触发网站的反爬机制,导致404。可以在settings.py里添加下载延迟:
DOWNLOAD_DELAY = 2 # 每次请求间隔2秒
内容的提问来源于stack exchange,提问作者gunesevitan

