广域爬取

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

启用“Ajax 可爬取页面”的爬取

某些页面(根据 2013 年的经验数据,最多 1%)声明自己是 Ajax 可爬取的。这意味着它们提供了通常仅通过 AJAX 可用的内容的纯 HTML 版本。页面可以通过两种方式指示这一点

  1. 在 URL 中使用 #! - 这是默认方式;

  2. 使用特殊的元标记 - 这种方式用于“主要”,“索引”网站页面。

Scrapy 自动处理 (1);要处理 (2),请启用 AjaxCrawlMiddleware

AJAXCRAWL_ENABLED = True

在执行广域爬取时,通常会爬取大量“索引”网页;AjaxCrawlMiddleware 有助于正确地爬取它们。它默认情况下是关闭的,因为它有一些性能开销,并且在聚焦爬取中启用它没有多大意义。

按 BFO 顺序爬取

Scrapy 默认情况下按 DFO 顺序爬取.

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

按 BFO 顺序爬取 以节省内存。

注意内存泄漏

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

安装特定的 Twisted reactor

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