大规模爬取

Scrapy 的默认设置针对抓取特定网站进行了优化。这些网站通常由单个 Scrapy 爬虫处理,尽管这不是必需或强制的(例如,存在可以处理任何给定网站的通用爬虫)。

除了这种“聚焦爬取”之外,还有另一种常见的爬取类型,它涵盖了大量(可能无限)的域,并且仅受时间或其他任意限制,而不是在域爬取完成或没有更多请求可执行时停止。这些被称为“大规模爬取”,是搜索引擎常用的爬虫。

大规模爬取通常具有以下常见特性:

  • 它们爬取许多域(通常是无限制的),而不是特定的网站集

  • 它们不一定会将域爬取至完成,因为这样做不切实际(或不可能),而是通过时间或爬取页面数量来限制爬取

  • 它们的逻辑更简单(与具有许多提取规则的复杂爬虫相反),因为数据通常在单独的阶段进行后处理

  • 它们并发爬取许多域,这使得它们能够通过不受任何特定网站限制来提高爬取速度(每个网站都缓慢爬取以尊重礼貌,但许多网站并行爬取)

如上所述,Scrapy 的默认设置针对聚焦爬取进行了优化,而非大规模爬取。然而,由于其异步架构,Scrapy 非常适合执行快速大规模爬取。本页总结了使用 Scrapy 进行大规模爬取时需要记住的一些事项,并提供了调整 Scrapy 设置以实现高效大规模爬取的具体建议。

提高并发量

并发量是并行处理的请求数量。有一个全局限制(CONCURRENT_REQUESTS)以及一个可以按域设置的额外限制(CONCURRENT_REQUESTS_PER_DOMAIN)。

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"

禁用 Cookies

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

要禁用 Cookies,请使用

COOKIES_ENABLED = False

禁用重试

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

要禁用重试,请使用

RETRY_ENABLED = False

缩短下载超时

除非您是从非常慢的连接进行爬取(对于大规模爬取不应该出现这种情况),否则请缩短下载超时,以便快速丢弃卡住的请求,并释放容量来处理下一个请求。

要缩短下载超时,请使用

DOWNLOAD_TIMEOUT = 15

禁用重定向

考虑禁用重定向,除非您有兴趣跟踪它们。在进行大规模爬取时,通常会保存重定向并在稍后的爬取中重新访问网站时解决它们。这也有助于保持每个爬取批次的请求数量恒定,否则重定向循环可能会导致爬虫将过多资源投入到任何特定域上。

要禁用重定向,请使用

REDIRECT_ENABLED = False

以 BFO 顺序爬取

Scrapy 默认以 DFO 顺序爬取.

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

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

注意内存泄漏

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

安装特定的 Twisted reactor

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