Scrapy单start_url场景下如何实现每秒20请求的并发爬取
Scrapy实现每秒20请求并发爬取的调整方案
核心问题说明
当前请求串行、速率不达标有两个核心原因:
- Scrapy默认配置中单域名并发数仅为8,默认下载延迟、自动限速规则会限制爬取速率,无法达到每秒20请求的要求
- 现有代码存在逻辑疏漏:初始化方法未调用父类构造函数、列表页解析时未正确提取商品详情页URL,导致调度器无法拿到足量待爬请求,无法触发并发逻辑
第一步:修改settings.py配置参数
直接调整以下配置项即可匹配速率要求:
# 全局最大并发请求数 CONCURRENT_REQUESTS = 20 # 单域名最大并发请求数,默认值为8必须修改 CONCURRENT_REQUESTS_PER_DOMAIN = 20 # 单个请求的下载间隔,设置为0.05秒配合20并发可稳定达到每秒20请求 DOWNLOAD_DELAY = 0.05 # 关闭下载延迟随机化,保证速率稳定 RANDOMIZE_DOWNLOAD_DELAY = False # 关闭自动限速扩展,避免框架自动调整延迟拖慢速率 AUTOTHROTTLE_ENABLED = False # 关闭冗余调试日志,减少不必要的性能损耗 LOG_LEVEL = "INFO"
注意:不要在爬虫代码中添加
time.sleep()类的阻塞等待逻辑,Scrapy基于异步事件循环实现,阻塞代码会卡住整个下载器,反而大幅降低并发效率。
第二步:修正Spider代码逻辑
原有代码存在属性未初始化、详情页URL提取错误的问题,修正后完整代码如下:
import scrapy from scrapy import Request # 提前定义业务内的url映射、默认请求头、cookie等常量 url = {} DEFAULT_HEADERS = {} DEFAULT_COOKIES = {} class WebSpider(scrapy.Spider): name = "web_spider" def __init__(self, country=None, category=None, *args, **kwargs): # 必须调用父类初始化方法,否则基类属性无法正常加载 super().__init__(*args, **kwargs) self.default_headers = DEFAULT_HEADERS self.cookies = DEFAULT_COOKIES self.asin = kwargs.get("asin", "") # 初始化起始URL,避免直接append产生重复值 self.start_urls = [url[country][category]] def start_requests(self): for start_url in self.start_urls: yield Request( url=start_url, headers=self.default_headers, callback=self.parse, cookies=self.cookies, cb_kwargs=dict(link=start_url, asin=self.asin), ) def parse(self, response, **kwargs): # 提取所有商品详情页链接节点 product_nodes = response.xpath('//link') for node in product_nodes: # 从节点中提取真实详情页URL,替换为业务实际的xpath匹配规则 product_url = node.xpath('./@href').get() if not product_url: continue # 将相对路径补全为可直接请求的绝对URL product_url = response.urljoin(product_url) yield Request( url=product_url, headers=self.default_headers, callback=self.product_parse, cookies=self.cookies, cb_kwargs=dict(link=product_url, asin=self.asin), ) def product_parse(self, response, **kwargs): # 编写商品详情解析逻辑,组装item字段 item = {} yield item
效果验证
启动爬虫后观察控制台日志中的Crawled X pages (at Y pages/min)统计项,将Y的数值除以60即为每秒实际请求数,若数值偏差可微调DOWNLOAD_DELAY参数:速率偏高就调大延迟,速率偏低就调小延迟,直到稳定在20 pages/s即可。
内容的提问来源于stack exchange,提问作者Akash Singh
相关产品推荐
相关产品推荐

