广度爬取
Scrapy 的默认设置针对抓取特定网站进行了优化。这些网站通常由单个 Scrapy 爬虫处理,尽管这不是必需或要求的(例如,有一些通用爬虫可以处理任何给定的网站)。
除了这种“聚焦式爬取”之外,还有另一种常见的爬取类型,它覆盖大量(潜在地无限)域名,并且仅受时间或其他任意限制,而不是在域名被完全抓取完成或没有更多请求可执行时停止。这被称为“广度爬取”,是搜索引擎通常采用的爬虫类型。
广度爬取通常具有以下一些常见属性
它们抓取许多域名(通常是无边界的),而不是一组特定的网站
它们不一定将域名完全抓取完成,因为这样做不切实际(或不可能),而是通过时间或抓取页面数量来限制爬取
它们的逻辑更简单(与具有许多提取规则的非常复杂的爬虫相反),因为数据通常在单独的阶段进行后处理
它们并发抓取许多域名,这使得它们通过不受任何特定网站限制来实现更快的抓取速度(每个网站为了遵守礼仪而被缓慢抓取,但许多网站并行抓取)
如上所述,Scrapy 的默认设置是针对聚焦式爬取进行优化的,而不是广度爬取。然而,由于其异步架构,Scrapy 非常适合执行快速广度爬取。本页总结了在使用 Scrapy 进行广度爬取时需要记住的一些事项,并提供了调整 Scrapy 设置以实现高效广度爬取的具体建议。
使用正确的 SCHEDULER_PRIORITY_QUEUE
Scrapy 的默认调度器优先级队列是 'scrapy.pqueues.ScrapyPriorityQueue'
。它在抓取单个域名时表现最佳。它不适合并行抓取许多不同的域名。
要应用推荐的优先级队列,请使用
SCHEDULER_PRIORITY_QUEUE = "scrapy.pqueues.DownloaderAwarePriorityQueue"
提高并发度
并发度是并行处理的请求数量。有一个全局限制(CONCURRENT_REQUESTS
),以及可以按域名(CONCURRENT_REQUESTS_PER_DOMAIN
)或按 IP(CONCURRENT_REQUESTS_PER_IP
)设置的附加限制。
注意
推荐用于广度爬取的调度器优先级队列不支持 CONCURRENT_REQUESTS_PER_IP
。
Scrapy 中的默认全局并发限制不适合并行抓取许多不同的域名,因此您需要增加它。增加多少取决于您的爬虫可用的 CPU 和内存量。
一个好的起点是 100
CONCURRENT_REQUESTS = 100
但最好的方法是通过进行一些试验,找出您的 Scrapy 进程在何种并发度下达到 CPU 瓶颈。为了获得最佳性能,您应该选择 CPU 使用率在 80-90% 的并发度。
增加并发度也会增加内存使用。如果内存使用是一个问题,您可能需要相应地降低全局并发限制。
增加 Twisted IO 线程池最大大小
目前 Scrapy 使用线程池以阻塞方式进行 DNS 解析。在较高的并发级别下,爬取可能会变慢甚至失败,遇到 DNS 解析器超时。可能的解决方案是增加处理 DNS 查询的线程数量。DNS 队列将处理得更快,从而加快建立连接和整体爬取速度。
要增加最大线程池大小,请使用
REACTOR_THREADPOOL_MAXSIZE = 20
设置您自己的 DNS
如果您有多个爬取进程和单个中央 DNS,它可能会对 DNS 服务器造成类似 DoS 攻击,导致整个网络变慢甚至阻止您的机器。为避免这种情况,请设置您自己的 DNS 服务器,带本地缓存并上游到一些大型 DNS,如 OpenDNS 或 Verizon。
降低日志级别
进行广度爬取时,您通常只关心获得的爬取速度和发现的任何错误。这些统计信息在使用 INFO
日志级别时由 Scrapy 报告。为了节省 CPU(和日志存储空间),在生产环境中进行大型广度爬取时,不应使用 DEBUG
日志级别。然而,在开发您的(广度)爬虫时使用 DEBUG
级别可能没问题。
要设置日志级别,请使用
LOG_LEVEL = "INFO"
禁用重试
重试失败的 HTTP 请求会显着减慢爬取速度,特别是当网站响应非常慢(或失败)时,从而导致超时错误并被不必要地多次重试,阻止爬虫容量被用于其他域名。
要禁用重试,请使用
RETRY_ENABLED = False
降低下载超时时间
除非您从非常慢的网络连接进行爬取(广度爬取不应如此),否则请降低下载超时时间,以便快速丢弃卡住的请求并释放容量来处理下一个请求。
要降低下载超时时间,请使用
DOWNLOAD_TIMEOUT = 15
禁用重定向
考虑禁用重定向,除非您对跟随它们感兴趣。进行广度爬取时,通常会保存重定向并在稍后再次访问该网站时解析它们。这也有助于保持每次爬取批次中的请求数量恒定,否则重定向循环可能导致爬虫在任何特定域名上占用过多资源。
要禁用重定向,请使用
REDIRECT_ENABLED = False
以 BFO 顺序爬取
然而,在广度爬取中,页面抓取往往比页面处理快。结果,未处理的早期请求会留在内存中,直到达到最终深度,这会显着增加内存使用量。
请改为以 BFO 顺序爬取以节省内存。
注意内存泄漏
如果您的广度爬取显示内存使用量很高,除了以 BFO 顺序爬取和降低并发度之外,您还应该调试您的内存泄漏。
安装特定的 Twisted reactor
如果爬取超出了系统的能力范围,您可能想尝试通过 TWISTED_REACTOR
设置安装特定的 Twisted reactor。