spatie / crawler
爬取网站上找到的所有内部链接
Requires
- php: ^8.1
- guzzlehttp/guzzle: ^7.3
- guzzlehttp/psr7: ^2.0
- illuminate/collections: ^10.0|^11.0
- nicmart/tree: ^0.8.0
- spatie/browsershot: ^3.45|^4.0
- spatie/robots-txt: ^2.0
- symfony/dom-crawler: ^6.0|^7.0
Requires (Dev)
- pestphp/pest: ^2.0
- spatie/ray: ^1.37
- dev-main
- 8.2.3
- 8.2.2
- 8.2.1
- 8.2.0
- 8.1.0
- 8.0.4
- 8.0.3
- 8.0.2
- 8.0.1
- 8.0.0
- v7.x-dev
- 7.1.3
- 7.1.2
- 7.1.1
- 7.1.0
- 7.0.5
- 7.0.4
- 7.0.3
- 7.0.2
- 7.0.1
- 7.0.0
- v6.x-dev
- 6.0.2
- 6.0.1
- 6.0.0
- v5.x-dev
- 5.0.2
- 5.0.1
- 5.0.0
- v4.x-dev
- 4.7.6
- 4.7.5
- 4.7.4
- 4.7.3
- 4.7.2
- 4.7.1
- 4.7.0
- 4.6.9
- 4.6.8
- 4.6.7
- 4.6.6
- 4.6.5
- 4.6.4
- 4.6.3
- 4.6.2
- 4.6.1
- 4.6.0
- 4.5.0
- 4.4.3
- 4.4.2
- 4.4.1
- 4.4.0
- 4.3.2
- 4.3.1
- 4.3.0
- 4.2.0
- 4.1.7
- 4.1.6
- 4.1.5
- 4.1.4
- 4.1.3
- 4.1.2
- 4.1.1
- 4.1.0
- 4.0.5
- 4.0.4
- 4.0.3
- 4.0.2
- 4.0.1
- 4.0.0
- 3.2.1
- 3.2.0
- 3.1.3
- 3.1.2
- 3.1.1
- 3.1.0
- 3.0.1
- 3.0.0
- v2.x-dev
- 2.7.1
- 2.7.0
- 2.6.2
- 2.6.1
- 2.6.0
- 2.5.0
- 2.4.0
- 2.3.0
- 2.2.1
- 2.2.0
- 2.1.2
- 2.1.1
- 2.1.0
- 2.0.7
- 2.0.6
- 2.0.5
- 2.0.4
- 2.0.3
- 2.0.2
- 2.0.1
- 2.0.0
- 1.3.1
- 1.3.0
- 1.2.3
- 1.2.2
- 1.2.1
- 1.2.0
- 1.1.1
- 1.1.0
- 1.0.2
- 1.0.1
- 1.0.0
- 0.0.1
This package is auto-updated.
Last update: 2024-08-31 10:57:21 UTC
README
此包提供了一种爬取网站链接的类。底层使用 Guzzle promises 来并发爬取多个 URL。
由于爬虫可以执行 JavaScript,它可以爬取 JavaScript 渲染的网站。底层使用Chrome 和 Puppeteer来实现这一功能。
支持我们
我们投入了大量资源来创建一流的开放源代码包。您可以通过购买我们的付费产品之一来支持我们。
我们非常感谢您从家乡寄给我们明信片,并说明您正在使用我们哪些包。您可以在我们的联系页面上找到我们的地址。我们将所有收到的明信片发布在我们的虚拟明信片墙上。
安装
此包可以通过 Composer 安装
composer require spatie/crawler
用法
爬虫可以这样实例化
use Spatie\Crawler\Crawler; Crawler::create() ->setCrawlObserver(<class that extends \Spatie\Crawler\CrawlObservers\CrawlObserver>) ->startCrawling($url);
传递给 setCrawlObserver
的参数必须是一个扩展 \Spatie\Crawler\CrawlObservers\CrawlObserver
抽象类的对象
namespace Spatie\Crawler\CrawlObservers; use GuzzleHttp\Exception\RequestException; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UriInterface; abstract class CrawlObserver { /* * Called when the crawler will crawl the url. */ public function willCrawl(UriInterface $url, ?string $linkText): void { } /* * Called when the crawler has crawled the given url successfully. */ abstract public function crawled( UriInterface $url, ResponseInterface $response, ?UriInterface $foundOnUrl = null, ?string $linkText, ): void; /* * Called when the crawler had a problem crawling the given url. */ abstract public function crawlFailed( UriInterface $url, RequestException $requestException, ?UriInterface $foundOnUrl = null, ?string $linkText = null, ): void; /** * Called when the crawl has ended. */ public function finishedCrawling(): void { } }
使用多个观察者
您可以使用 setCrawlObservers
设置多个观察者
Crawler::create() ->setCrawlObservers([ <class that extends \Spatie\Crawler\CrawlObservers\CrawlObserver>, <class that extends \Spatie\Crawler\CrawlObservers\CrawlObserver>, ... ]) ->startCrawling($url);
或者您可以使用 addCrawlObserver
逐个设置多个观察者
Crawler::create() ->addCrawlObserver(<class that extends \Spatie\Crawler\CrawlObservers\CrawlObserver>) ->addCrawlObserver(<class that extends \Spatie\Crawler\CrawlObservers\CrawlObserver>) ->addCrawlObserver(<class that extends \Spatie\Crawler\CrawlObservers\CrawlObserver>) ->startCrawling($url);
执行 JavaScript
默认情况下,爬虫不会执行 JavaScript。这是启用 JavaScript 执行的方法
Crawler::create() ->executeJavaScript() ...
为了在 JavaScript 执行后获取 body html,此包依赖于我们的Browsershot包。此包底层使用Puppeteer。以下是如何在您的系统上安装它的指南。
Browsershot 将根据您的系统猜测其依赖项的安装位置。默认情况下,爬虫将实例化一个新的 Browsershot 实例。您可能需要使用 setBrowsershot(Browsershot $browsershot)
方法设置自定义创建的实例。
Crawler::create() ->setBrowsershot($browsershot) ->executeJavaScript() ...
请注意,即使您没有 Browsershot 所需的系统依赖项,爬虫仍然可以工作。这些系统依赖项仅当您调用 executeJavaScript()
时才需要。
过滤某些 URL
您可以通过使用 setCrawlProfile
-函数来告诉爬虫不要访问某些 URL。该函数期望一个扩展 Spatie\Crawler\CrawlProfiles\CrawlProfile
的对象
/* * Determine if the given url should be crawled. */ public function shouldCrawl(UriInterface $url): bool;
此包自带三个 CrawlProfiles
CrawlAllUrls
:此配置将爬取所有页面上所有 URL,包括指向外部网站的 URL。CrawlInternalUrls
:此配置将仅爬取主机页面上的内部 URL。CrawlSubdomains
:此配置文件将仅爬取主机页面上的内部URL及其子域名。
自定义链接提取
您可以通过向爬虫传递自定义的UrlParser
来定制页面中链接的提取方式。
Crawler::create() ->setUrlParserClass(<class that implements \Spatie\Crawler\UrlParsers\UrlParser>::class) ...
默认情况下,使用LinkUrlParser
。该解析器将从a
标签的href
属性中提取所有链接。
还有一个内置的SitemapUrlParser
,可以从网站地图中提取并爬取所有链接。它也支持网站地图索引文件。
Crawler::create() ->setUrlParserClass(SitemapUrlParser::class) ...
忽略robots.txt和robots元数据
默认情况下,爬虫会尊重robots数据。可以通过以下方式禁用这些检查:
Crawler::create() ->ignoreRobots() ...
robots数据可以来自robots.txt
文件、元标签或响应头。有关规范的更多信息,请参阅http://www.robotstxt.org/。
通过我们的包spatie/robots-txt
来解析robots数据。
接受具有rel="nofollow"属性的链接
默认情况下,爬虫会拒绝所有包含属性rel="nofollow"的链接。可以通过以下方式禁用这些检查:
Crawler::create() ->acceptNofollowLinks() ...
使用自定义User Agent
为了尊重自定义User Agent的robots.txt规则,您可以指定自己的自定义User Agent。
Crawler::create() ->setUserAgent('my-agent')
您可以在robots.txt中为'my-agent'添加特定的爬取规则组。以下示例禁止'my-agent'标识的爬虫爬取整个网站。
// Disallow crawling for my-agent User-agent: my-agent Disallow: /
设置并发请求数量
为了提高爬取速度,默认情况下,该包以并发爬取10个URL。如果您想更改该数字,可以使用setConcurrency
方法。
Crawler::create() ->setConcurrency(1) // now all urls will be crawled one by one
定义爬取限制
默认情况下,爬虫会继续爬取直到它爬取了所有能找到的页面。如果您在具有限制的环境(如无服务器环境)中工作,这种行为可能会导致问题。
可以使用以下两个选项来控制爬取行为:
- 总爬取限制(
setTotalCrawlLimit
):此限制定义了要爬取的最大URL数量。 - 当前爬取限制(
setCurrentCrawlLimit
):此限制定义了当前爬取期间处理的URL数量。
让我们通过一些示例来阐明这两种方法之间的区别。
示例1:使用总爬取限制
setTotalCrawlLimit
方法允许您限制要爬取的总URL数量,无论您调用爬虫的频率如何。
$queue = <your selection/implementation of a queue>; // Crawls 5 URLs and ends. Crawler::create() ->setCrawlQueue($queue) ->setTotalCrawlLimit(5) ->startCrawling($url); // Doesn't crawl further as the total limit is reached. Crawler::create() ->setCrawlQueue($queue) ->setTotalCrawlLimit(5) ->startCrawling($url);
示例2:使用当前爬取限制
setCurrentCrawlLimit
将为每次执行设置的URL数量设置限制。此段代码将每次执行处理5个页面,没有页面爬取的总限制。
$queue = <your selection/implementation of a queue>; // Crawls 5 URLs and ends. Crawler::create() ->setCrawlQueue($queue) ->setCurrentCrawlLimit(5) ->startCrawling($url); // Crawls the next 5 URLs and ends. Crawler::create() ->setCrawlQueue($queue) ->setCurrentCrawlLimit(5) ->startCrawling($url);
示例3:组合总限制和爬取限制
这两个限制可以组合起来控制爬虫。
$queue = <your selection/implementation of a queue>; // Crawls 5 URLs and ends. Crawler::create() ->setCrawlQueue($queue) ->setTotalCrawlLimit(10) ->setCurrentCrawlLimit(5) ->startCrawling($url); // Crawls the next 5 URLs and ends. Crawler::create() ->setCrawlQueue($queue) ->setTotalCrawlLimit(10) ->setCurrentCrawlLimit(5) ->startCrawling($url); // Doesn't crawl further as the total limit is reached. Crawler::create() ->setCrawlQueue($queue) ->setTotalCrawlLimit(10) ->setCurrentCrawlLimit(5) ->startCrawling($url);
示例4:跨请求爬取
您可以使用setCurrentCrawlLimit
来分解长时间运行的爬取。以下示例演示了一种(简化的)方法。它由一个初始请求和任何数量的后续请求组成,这些请求继续爬取。
初始请求
要开始跨不同请求爬取,您需要创建所选队列驱动程序的新队列。首先,将队列实例传递给爬虫。爬虫将在处理页面和发现新URL时开始填充队列。在爬虫完成后(使用当前爬取限制)序列化和存储队列引用。
// Create a queue using your queue-driver. $queue = <your selection/implementation of a queue>; // Crawl the first set of URLs Crawler::create() ->setCrawlQueue($queue) ->setCurrentCrawlLimit(10) ->startCrawling($url); // Serialize and store your queue $serializedQueue = serialize($queue);
后续请求
对于任何后续请求,您需要反序列化原始队列并将其传递给爬虫。
// Unserialize queue $queue = unserialize($serializedQueue); // Crawls the next set of URLs Crawler::create() ->setCrawlQueue($queue) ->setCurrentCrawlLimit(10) ->startCrawling($url); // Serialize and store your queue $serialized_queue = serialize($queue);
行为基于队列中的信息。只有当传入相同的队列实例时,行为才会按描述的方式工作。当传入一个全新的队列时,即使是相同的网站,之前爬取的限制也不会适用。
更详细的示例可以在这里找到。
设置最大爬取深度
默认情况下,爬虫会继续爬取直到爬取完提供的URL的每一页。如果您想限制爬虫的深度,可以使用setMaximumDepth
方法。
Crawler::create() ->setMaximumDepth(2)
设置最大响应大小
大多数HTML页面都很小。但爬虫可能会意外地选择大型文件,如PDF和MP3。为了在这种情况下降低内存使用,爬虫只会使用小于2MB的响应。如果在流式传输响应时,它变得大于2MB,爬虫将停止流式传输响应。将假设响应正文为空。
您可以更改最大响应大小。
// let's use a 3 MB maximum. Crawler::create() ->setMaximumResponseSize(1024 * 1024 * 3)
在请求之间添加延迟
在某些情况下,如果您爬取过于积极,可能会受到速率限制。为了解决这个问题,您可以使用setDelayBetweenRequests()
方法在每次请求之间添加一个暂停。这个值以毫秒为单位。
Crawler::create() ->setDelayBetweenRequests(150) // After every page crawled, the crawler will wait for 150ms
限制要解析的内容类型
默认情况下,每个找到的页面都会被下载(大小不超过setMaximumResponseSize()
),并解析以找到额外的链接。您可以通过设置setParseableMimeTypes
来限制哪些内容类型应该被下载和解析,该函数接受一个允许类型的数组。
Crawler::create() ->setParseableMimeTypes(['text/html', 'text/plain'])
这将防止下载具有不同MIME类型的页面的正文,如二进制文件、音频/视频等,这些文件不太可能嵌入链接。此功能主要节省带宽。
使用自定义爬取队列
当爬取一个网站时,爬虫会将要爬取的URL放入队列中。默认情况下,此队列使用内置的ArrayCrawlQueue
存储在内存中。
当网站非常大时,您可能希望将队列存储在其他地方,例如数据库。在这种情况下,您可以编写自己的爬取队列。
有效的爬取队列是任何实现Spatie\Crawler\CrawlQueues\CrawlQueue
-接口的类。您可以通过爬虫上的setCrawlQueue
方法传入您的自定义爬取队列。
Crawler::create() ->setCrawlQueue(<implementation of \Spatie\Crawler\CrawlQueues\CrawlQueue>)
这里
- ArrayCrawlQueue
- RedisCrawlQueue(第三方包)
- CacheCrawlQueue for Laravel(第三方包)
- Laravel Model as Queue(第三方示例应用)
更改默认的基础URL方案
默认情况下,如果未指定,爬虫会将基础URL方案设置为http
。您可以使用setDefaultScheme
来更改它。
Crawler::create() ->setDefaultScheme('https')
变更日志
有关最近更改的更多信息,请参阅变更日志。
贡献
有关详细信息,请参阅贡献。
测试
首先,安装Puppeteer依赖项,否则您的测试将失败。
npm install puppeteer
要运行测试,您必须在单独的终端窗口中首先启动包含的基于node的服务器。
cd tests/server
npm install
node server.js
服务器运行后,您就可以开始测试了。
composer test
安全
如果您发现了关于安全性的bug,请通过[email protected]发送邮件,而不是使用问题跟踪器。
明信片软件
您可以使用这个包,但如果它进入您的生产环境,我们非常希望您能从您家乡给我们寄一张明信片,并说明您正在使用我们的哪个包。
我们的地址是:Spatie,Kruikstraat 22,2018 安特卫普,比利时。
我们将发布收到的所有明信片在我们的公司网站上。
致谢
许可
MIT许可(MIT)。有关更多信息,请参阅许可文件。