广泛爬取

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(如OpenDNS或Verizon)的DNS服务器。

降低日志级别

在进行广泛爬取时,通常只对爬取速率和发现的错误感兴趣。这些统计数据在使用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

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

一些页面(根据2013年的经验数据,最多1%)声明自己为可抓取的AJAX页面。这意味着它们提供了通常只能通过AJAX获取的内容的纯HTML版本。页面可以通过两种方式表明这一点:

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

  2. 通过使用一个特殊的meta标签 - 这种方式用于“主页”、“索引”网站页面。

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

AJAXCRAWL_ENABLED = True

在进行广泛爬取时,通常会爬取大量的“索引”网页; AjaxCrawlMiddleware 有助于正确爬取这些网页。 它默认是关闭的,因为它有一定的性能开销, 并且在针对特定目标的爬取中启用它没有太大意义。

按BFO顺序爬取

Scrapy 默认以 DFO 顺序爬取

在广泛的爬取中,页面爬取往往比页面处理更快。因此,未处理的早期请求会一直留在内存中,直到达到最终深度,这可能会显著增加内存使用量。

Crawl in BFO order 改为以节省内存。

注意内存泄漏

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

安装特定的Twisted反应器

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