广度爬取

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"

禁用 cookie

除非您确实需要,否则禁用 cookie。进行广度爬取时通常不需要 cookie(搜索引擎爬虫会忽略它们),并且它们通过节省一些 CPU 周期并减少 Scrapy 爬虫的内存占用量来提高性能。

要禁用 cookie,请使用

COOKIES_ENABLED = False

禁用重试

重试失败的 HTTP 请求会显着减慢爬取速度,特别是当网站响应非常慢(或失败)时,从而导致超时错误并被不必要地多次重试,阻止爬虫容量被用于其他域名。

要禁用重试,请使用

RETRY_ENABLED = False

降低下载超时时间

除非您从非常慢的网络连接进行爬取(广度爬取不应如此),否则请降低下载超时时间,以便快速丢弃卡住的请求并释放容量来处理下一个请求。

要降低下载超时时间,请使用

DOWNLOAD_TIMEOUT = 15

禁用重定向

考虑禁用重定向,除非您对跟随它们感兴趣。进行广度爬取时,通常会保存重定向并在稍后再次访问该网站时解析它们。这也有助于保持每次爬取批次中的请求数量恒定,否则重定向循环可能导致爬虫在任何特定域名上占用过多资源。

要禁用重定向,请使用

REDIRECT_ENABLED = False

以 BFO 顺序爬取

Scrapy 默认以 DFO 顺序爬取.

然而,在广度爬取中,页面抓取往往比页面处理快。结果,未处理的早期请求会留在内存中,直到达到最终深度,这会显着增加内存使用量。

请改为以 BFO 顺序爬取以节省内存。

注意内存泄漏

如果您的广度爬取显示内存使用量很高,除了以 BFO 顺序爬取降低并发度之外,您还应该调试您的内存泄漏

安装特定的 Twisted reactor

如果爬取超出了系统的能力范围,您可能想尝试通过 TWISTED_REACTOR 设置安装特定的 Twisted reactor。