3.6 爬取速度控制与并发


文档摘要

3.6 爬取速度控制与并发 3.6 Scrapy 爬取速度控制与并发 在 Scrapy 中,控制爬取速度和并发是构建高效、稳定爬虫的关键。过快的爬取速度可能导致目标网站崩溃,或被反爬机制封禁;而过低的并发则会大大降低爬虫的效率。Scrapy 提供了多种机制来控制爬取速度和并发,允许开发者根据实际情况进行灵活调整。 3.6.1 理解并发与延迟 在讨论速度控制之前,我们需要理解两个核心概念: 并发 (Concurrency): 指的是同时进行的请求数量。Scrapy 通过并发请求来提高爬取效率。 延迟 (Delay): 指的是在发送请求之间等待的时间。通过设置延迟,可以避免对目标网站造成过大的压力。 3.6.

3.6 爬取速度控制与并发

3.6 Scrapy 爬取速度控制与并发

在 Scrapy 中,控制爬取速度和并发是构建高效、稳定爬虫的关键。过快的爬取速度可能导致目标网站崩溃,或被反爬机制封禁;而过低的并发则会大大降低爬虫的效率。Scrapy 提供了多种机制来控制爬取速度和并发,允许开发者根据实际情况进行灵活调整。

3.6.1 理解并发与延迟

在讨论速度控制之前,我们需要理解两个核心概念:

  • 并发 (Concurrency): 指的是同时进行的请求数量。Scrapy 通过并发请求来提高爬取效率。

  • 延迟 (Delay): 指的是在发送请求之间等待的时间。通过设置延迟,可以避免对目标网站造成过大的压力。

3.6.2 Scrapy 中的并发控制

Scrapy 主要通过以下设置来控制并发:

  • CONCURRENT_REQUESTS: Scrapy downloader 并发请求(concurrent requests)的最大值。默认值是 16。

  • CONCURRENT_REQUESTS_PER_DOMAIN: 对单个域名进行并发请求的最大值。默认值是 8。

  • CONCURRENT_REQUESTS_PER_IP: 对单个IP进行并发请求的最大值。如果非零,CONCURRENT_REQUESTS_PER_DOMAIN 将被忽略, 使用该配置替代。也就是说,并发限制将作用于每个IP,而不是每个域名。

这些设置可以在 settings.py 文件中进行配置。

代码示例:设置并发

# settings.py CONCURRENT_REQUESTS = 32 CONCURRENT_REQUESTS_PER_DOMAIN = 16 CONCURRENT_REQUESTS_PER_IP = 0 # 禁用基于 IP 的并发限制

图示:并发请求

3.6.3 下载延迟 (Download Delay)

Scrapy 提供了 DOWNLOAD_DELAY 设置来控制下载延迟,以避免对目标网站造成过大的压力。

  • DOWNLOAD_DELAY: 下载器在下载同一个网站的连续页面前需要等待的时间,单位为秒。可以设置为浮点数,例如 0.5

代码示例:设置下载延迟

# settings.py DOWNLOAD_DELAY = 0.25 # 等待 0.25 秒

自动节流扩展 (AutoThrottle Extension)

Scrapy 还提供了一个自动节流扩展,可以根据目标网站的响应速度自动调整下载延迟。该扩展通过监控网站的响应时间和错误率来动态调整 DOWNLOAD_DELAY,从而在保证爬取速度的同时,避免对目标网站造成过大的压力。

要启用自动节流扩展,需要在 settings.py 中进行如下配置:

# settings.py AUTOTHROTTLE_ENABLED = True AUTOTHROTTLE_START_DELAY = 5.0 # 初始下载延迟 AUTOTHROTTLE_MAX_DELAY = 60.0 # 最大下载延迟 AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0 # 每个域名的目标并发数 AUTOTHROTTLE_DEBUG = False # 启用调试模式
  • AUTOTHROTTLE_ENABLED: 启用自动节流扩展。

  • AUTOTHROTTLE_START_DELAY: 初始下载延迟,单位为秒。

  • AUTOTHROTTLE_MAX_DELAY: 最大下载延迟,单位为秒。

  • AUTOTHROTTLE_TARGET_CONCURRENCY: 每个域名的目标并发数。

  • AUTOTHROTTLE_DEBUG: 启用调试模式,可以查看自动节流扩展的详细信息。

图示:自动节流

3.6.4 使用自定义下载中间件进行更精细的控制

除了 Scrapy 提供的内置设置外,还可以通过自定义下载中间件来更精细地控制爬取速度和并发。自定义下载中间件可以拦截请求和响应,从而实现更复杂的逻辑,例如:

  • 基于 IP 地址的并发控制。

  • 基于 URL 模式的延迟控制。

  • 使用代理 IP 池。

  • 处理 HTTP 错误。

代码示例:自定义下载中间件

# middlewares.py from scrapy import signals from scrapy.exceptions import IgnoreRequest import time import random class CustomDownloaderMiddleware: def __init__(self, crawler): self.crawler = crawler self.delay = crawler.settings.get('CUSTOM_DOWNLOAD_DELAY', 0) self.user_agents = crawler.settings.get('USER_AGENT_LIST', []) @classmethod def from_crawler(cls, crawler): o = cls(crawler) crawler.signals.connect(o.spider_opened, signal=signals.spider_opened) return o def process_request(self, request, spider): # 延迟处理 if self.delay > 0: time.sleep(self.delay + random.random()) # 增加随机性 # User-Agent 轮换 if self.user_agents: request.headers['User-Agent'] = random.choice(self.user_agents) return None def process_response(self, request, response, spider): # 检查状态码 if response.status >= 400: spider.logger.warning(f"Request failed: {request.url} - Status: {response.status}") # 可以根据状态码进行重试或忽略 # return request # 重试 # raise IgnoreRequest(f"Ignoring request due to status code: {response.status}") # 忽略 return response def process_exception(self, request, exception, spider): spider.logger.error(f"Request exception: {request.url} - {exception}") # 可以根据异常进行重试 # return request # 重试 return None def spider_opened(self, spider): self.delay = getattr(spider, 'download_delay', self.delay) self.user_agents = getattr(spider, 'user_agents', self.user_agents) spider.logger.info(f"CustomDownloaderMiddleware enabled with delay: {self.delay}") # settings.py DOWNLOADER_MIDDLEWARES = { 'myproject.middlewares.CustomDownloaderMiddleware': 543, } CUSTOM_DOWNLOAD_DELAY = 0.5 USER_AGENT_LIST = [ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0', ]

在这个例子中,CustomDownloaderMiddleware 中间件实现了以下功能:

  • 延迟处理: 在 process_request 方法中,根据 CUSTOM_DOWNLOAD_DELAY 设置延迟请求,并增加随机性,避免被识别为爬虫。

  • User-Agent 轮换: 在 process_request 方法中,随机选择一个 User-Agent,模拟不同的浏览器。

  • 状态码检查: 在 process_response 方法中,检查响应的状态码,如果状态码大于等于 400,则记录警告信息,并可以选择重试或忽略请求。

  • 异常处理: 在 process_exception 方法中,处理请求过程中发生的异常,并可以选择重试请求。

  • 动态配置: 中间件从 settings 中读取 CUSTOM_DOWNLOAD_DELAYUSER_AGENT_LIST,并允许spider通过设置spider的属性来覆盖这些值。

要启用该中间件,需要在 settings.py 中将其添加到 DOWNLOADER_MIDDLEWARES 设置中,并设置合适的优先级。

图示:自定义下载中间件

3.6.5 使用代理 IP

使用代理 IP 可以隐藏爬虫的真实 IP 地址,避免被目标网站封禁。Scrapy 提供了多种方式来使用代理 IP:

  • HTTP 代理中间件: 可以使用现成的 HTTP 代理中间件,例如 scrapy-proxies

  • 自定义下载中间件: 可以编写自定义下载中间件,从代理 IP 池中获取代理 IP,并将其添加到请求中。

代码示例:使用自定义下载中间件添加代理

# middlewares.py import random class ProxyMiddleware: def __init__(self, proxy_list): self.proxy_list = proxy_list @classmethod def from_crawler(cls, crawler): return cls( proxy_list=crawler.settings.getlist('PROXY_LIST') ) def process_request(self, request, spider): if self.proxy_list: proxy = random.choice(self.proxy_list) request.meta['proxy'] = proxy spider.logger.debug(f"Using proxy: {proxy} for URL: {request.url}")
# settings.py DOWNLOADER_MIDDLEWARES = { 'myproject.middlewares.ProxyMiddleware': 750, 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': None, # 禁用默认的 HttpProxyMiddleware } PROXY_LIST = [ 'http://10.10.1.10:3128', 'http://127.0.0.1:8000', 'http://10.10.1.11:3128', ]

3.6.6 总结

控制 Scrapy 爬虫的速度和并发是至关重要的。通过合理配置 CONCURRENT_REQUESTSDOWNLOAD_DELAYAUTOTHROTTLE_ENABLED,可以使用Scrapy内置的功能来控制爬取速度。更高级的,可以通过自定义下载中间件来实现更精细的控制,例如基于 IP 地址的并发控制、基于 URL 模式的延迟控制和使用代理 IP 池。选择合适的方法取决于项目的具体需求和目标网站的反爬策略。理解并发、延迟和自动节流的概念,并结合实际情况进行调整,可以构建高效、稳定、友好的 Scrapy 爬虫。


发布者: 作者: 转发
评论区 (0)
U