资讯动态

Crawlee BasicCrawler 实战指南:基于 `@crawlee/basic` 构建并行网页爬虫

发布时间:2026/9/11 22:06:40 来源:尧图企业网站定制
Crawlee BasicCrawler 实战指南基于crawlee/basic构建并行网页爬虫【免费下载链接】crawleeCrawlee—A web scraping and browser automation library for Node.js to build reliable crawlers. In JavaScript and TypeScript. Extract data for AI, LLMs, RAG, or GPTs. Download HTML, PDF, JPG, PNG, and other files from websites. Works with Puppeteer, Playwright, Cheerio, JSDOM, and raw HTTP. Both headful and headless mode. With proxy rotation.项目地址: https://gitcode.com/GitHub_Trending/cr/crawlee导读本文围绕 Crawlee 仓库中 packages/basic-crawler/README.md 展开系统讲解crawlee/basic包提供的BasicCrawler它是 Crawlee 家族中最底层、最灵活的爬虫基类——URL 来源可以是静态的RequestList也可以是支持递归爬取的动态RequestQueue而页面下载与数据提取逻辑完全由你自行实现。读完本文你将掌握BasicCrawler的完整配置面请求源、并发控制、重试、超时、会话、代理、robots.txt 等、核心生命周期与调用链并能基于 basic-crawler.ts 的源码级实现写出可上生产环境的自定义爬虫。一、BasicCrawler 是什么Crawlee 的底层发动机从 README 的定义看BasicCrawler为并行爬取网页提供了一个简单框架它不帮你下载页面、也不帮你解析 HTML——requestHandler中的抓取与提取完全由你实现它对每个 Request代表一个待爬 URL调用你提供的requestHandler请求由RequestList静态 URL 列表或RequestQueue动态队列支持递归爬取供给当没有更多待处理 Request 时爬虫自动结束新请求只有在 CPU 与内存足够时才被调度——这一判断由ConcurrencySystem完成。在仓库中BasicCrawler的实现位于 packages/basic-crawler/src/internals/basic-crawler.ts而 CheerioCrawler、PuppeteerCrawler、PlaywrightCrawler 等高层爬虫它们替你完成了下载与解析都以它为基类。也就是说理解了BasicCrawler就理解了 Crawlee 全部爬虫的调度内核。从源码结构看该包由四个文件组成internals/basic-crawler.ts —— 核心类实现约 3100 行internals/crawler-run.ts —— 单次run()的任务循环task loopinternals/request-timeout.ts —— 请求超时机制internals/send-request.ts ——sendRequest上下文助手。包元信息见 packages/basic-crawler/package.jsonv4.0.0要求 Node.js 22ESM 模块。二、第一个爬虫最小可运行示例README 给出了最典型的用法——用sendRequest抓取 HTML 并写入 Datasetimport { BasicCrawler, Dataset } from crawlee; // 创建爬虫实例 const crawler new BasicCrawler({ async requestHandler({ request, sendRequest }) { // request 是 Request 类的实例 // 这里我们简单地抓取页面 HTML 并存入 dataset const { body } await sendRequest({ url: request.url, method: request.method, body: request.payload, headers: request.headers, }); await Dataset.pushData({ url: request.url, html: body, }) }, }); // 入队初始请求并运行爬虫 await crawler.run([ http://www.example.com/page-1, http://www.example.com/page-2, ]);几个关键点requestHandler是核心。它接收 BasicCrawlingContext其中request是当前待爬 URL 的描述sendRequest是帮你发 HTTP 请求的助手。它必须返回 Promise爬虫会 await 它。crawler.run(requests)是入队 运行的快捷方式。requests参数等价于先调用crawler.addRequests()再运行。Dataset.pushData是 Crawlee 的标准结果存储数据默认落在本地./storage/datasets中方便后续导出。sendRequest 的底层实现sendRequest并非简单的fetch封装。查看 internals/send-request.ts它会把当前 Request 转换为 Fetch API 的请求格式合并你传入的覆盖项url/method/headers/body然后交给httpClient.sendRequest()并自动携带当前会话的 cookieJarsession.cookieJar保持请求间的 cookie 一致性可选的timeoutMillis、signal用于取消、ignoreTlsErrors。这意味着即使你手写 HTTP 抓取也能无缝获得 Crawlee 的会话、代理、超时管理能力。三、请求来源RequestList、RequestQueue 与 RequestManagerREADME 明确了两类请求供给方式选项类型用途requestListRequestList静态 URL 列表一次性给定所有 URLrequestQueueRequestQueue动态队列支持在爬取过程中持续入队递归爬取默认行为如果两个选项都不提供爬虫会在以下时机打开默认的RequestQueue调用crawler.addRequests()时或调用crawler.run(requests)并提供初始请求参数时。组合使用README 特别强调若同时提供requestList和requestQueue爬虫会先处理列表中的 URL并在开始处理前把列表中的全部 URL 自动入队到队列中从而保证单个 URL 不会被重复爬取。源码视角RequestManagerTandem从源码basic-crawler.ts可以确认requestList与requestQueue会被合并成一个RequestManagerTandem串联管理器列表作为只读 loader 先被读取队列作为可写目标接收转移过来的请求。当前版本还引入了更统一的requestManager选项一个RequestQueue本身就是 request manager只读源如RequestList、SitemapRequestLoader可通过requestLoader.toTandem()与队列组合。代码注释明确标注requestList/requestQueue为已弃用但仍被支持The legacyrequestListandrequestQueueoptions are deprecated... but new code should userequestManagerdirectly.另外注意一个约束requestManager与requestList/requestQueue互斥同时传入会直接抛错basic-crawler.ts。爬虫何时结束队列为空即结束。run()返回的 Promise 在所有请求处理完后 resolve在keepAlive: true模式下会持续等待新请求入队需要手动crawler.stop()或crawler.teardown()退出。四、并发控制ConcurrencySystem 与三大调节旋钮README 指出新请求只有在 CPU 和内存充足时才会被调度判断者是ConcurrencySystem。并发主要通过三个构造参数调节参数含义默认值minConcurrency最低并行度系统自动计算maxConcurrency最高并行度系统自动计算maxRequestsPerMinute每分钟最大请求数Infinity不限制⚠️警告minConcurrency设置过高而系统内存/CPU 不足时爬虫会极慢或崩溃。不确定时保持默认值让并发自动伸缩即可。更精细的控制注入 concurrencySystem源码中对concurrencySystem的注释给出了关键信息basic-crawler.ts它是是否还有空闲算力再跑一个任务的判定者通常是一个ConcurrencySystem实例所有伸缩配置min/max/desired 并发、伸缩比例、maxTasksPerMinute、快照器调优都挂在实例上把同一个实例注入多个并行爬虫可以共享同一个并发预算对所有爬虫做联合限流——每个爬虫仍拥有自己的AutoscaledPool只共享负载/伸缩记账它与minConcurrency/maxConcurrency/initialConcurrency/maxRequestsPerMinute互斥同时传入会抛错生命周期由你管理需要先start()再run()否则抛错所有借用它的爬虫结束后stop()它。initialConcurrency 与运行期调优initialConcurrency是爬虫启动时的并发度默认取minConcurrency。crawler.concurrencySystem是只读的运行期若要动态调优需要自己构建并注入ConcurrencySystem然后在自己的引用上修改minConcurrency/maxConcurrency/desiredConcurrency。五、重试与错误处理机制maxRequestRetries重试上限maxRequestRetries控制请求失败后的最大重试次数默认 3。重试覆盖的场景包括导航错误、会话/代理错误、以及用户函数requestHandler、preNavigationHooks、postNavigationHooks抛出的错误。这与 README 强调的准则一致为了让重试生效应当让我们的函数主动抛异常而不是捕获它们。异常会通过Request.pushErrorMessage()记录到请求上。三个处理函数的分工回调触发时机errorHandler请求失败但尚未超过maxRequestRetries在每次重试前执行可修改 RequestfailedRequestHandler请求失败超过maxRequestRetries后执行处理最终失败requestHandler正常处理每个请求源码实现位于 basic-crawler.tsrequestHandler抛出的异常会让爬虫稍后重爬直至重试耗尽然后调用failedRequestHandler。状态码与反爬处理blockedStatusCodes默认[401, 403, 429]这些状态码会被判定为会话被封触发会话轮换/废弃retryOnBlocked默认false设为true时爬虫自动尝试绕过检测到的机器人防护当前支持 Cloudflare Bot Management 与 Google Search 限流页ignoreHttpErrorStatusCodes/additionalHttpErrorStatusCodes默认情况下 HTTP 状态码 500 会被视为错误这两个数组分别用于排除错误与额外视为错误。从源码isErrorStatusCode()basic-crawler.ts可精确看到判定逻辑protected isErrorStatusCode(status: number): boolean { const excludeError this.#ignoreHttpErrorStatusCodes.has(status); const includeError this.additionalHttpErrorStatusCodes.has(status); return (status 500 !excludeError) || includeError; }六、超时与限速让爬虫绅士地爬requestHandlerTimeoutSecsrequestHandlerTimeoutSecs规定requestHandler必须在多少秒内完成默认 60 秒。源码中basic-crawler.ts把它换算为毫秒若未提供则取 60_000ms。另有internalTimeoutMillis默认至少 5 分钟取requestHandlerTimeoutMillis * 2与 300s 的较大者作为整个请求的兜底超时。上下文里还提供了extendTimeout(secs)助手用于给当前请求窗口临时续时。sameDomainDelaySecs同域节流sameDomainDelaySecs表示爬取同一域名下两个请求之间等待的秒数默认 0。子域名与主域名一起限速按可注册域名registrableDomain计算。源码显示basic-crawler.ts若底层 request manager 支持节流信号爬虫直接传递minIntervalEverywhere信号否则用ThrottlingRequestManager包装避免同一域名出现两套时钟。maxRequestsPerCrawl 与 maxCrawlDepthmaxRequestsPerCrawl爬虫最多打开的页面数。源码强调它应当总是设置以防配置错误的爬虫陷入死循环由于并行处理实际访问数可能略超此值。达到限制后新请求不再入队进行中的请求被允许完成。maxCrawlDepth最大爬取深度。0只处理初始请求跳过enqueueLinks/addRequests入队的链接1额外处理初始请求中入队的链接。设置后超深度的 URL 会以depth原因被跳过并计入onSkippedRequest。七、会话与代理状态管理与反爬规避的基础sessionPoolsessionPool选项接受内置SessionPool或任何实现ISessionPool接口的对象。从源码basic-crawler.ts可见默认行为爬虫为每个会话创建一个Session并在有proxyConfiguration时自动为会话分配新的代理信息newProxyInfo()。proxyConfigurationproxyConfiguration提供代理 URL 列表并按配置轮换。注意源码中的一个细节basic-crawler.ts同时传入sessionPool和proxyConfiguration时proxyConfiguration会被忽略并打印警告——因为外部提供的会话池中的会话已带有各自的proxyInfo此时应在池上配置代理如addSession({ proxyInfo })或自定义createSessionFunction。会话在管道中的位置从buildBasicContextPipeline()basic-crawler.ts可以看到每个请求经历的四个基础阶段checkRobotsTxt—— robots.txt 检查可选开启createBaseContext—— 构建基础上下文pushData、useState、log、extendTimeout等助手resolveSession—— 从池中解析会话与代理createContextHelpers—— 注入addRequests与sendRequest助手。之后才进入子类管道浏览器启动、导航等和你的requestHandler。若会话解析失败MissingSessionError请求会进入错误流程并尝试重试。八、实用高级特性keepAlive长驻爬虫keepAlive: true让run()在队列清空后不返回持续等待新请求典型场景消息队列驱动的常驻消费者。此时应通过crawler.stop()优雅退出进行中任务完成后结束或crawler.teardown()立即停止。useState跨请求持久状态crawler.useState()基于默认KeyValueStore的getAutoSavedValue实现自动保存/加载。源码特别提示basic-crawler.ts多个爬虫实例共享同一 state 时若未显式指定id会打印警告为每个实例传入稳定且唯一的id如new BasicCrawler({ id: my-crawler-1, ... })可获得相互隔离、且能在脚本重启如 Apify 迁移后持久化的状态。addRequests批量入队crawler.addRequests()是对底层队列addRequestsBatched()的别名默认在首批入队后即 resolve其余批次后台继续可用batchSize、waitBetweenBatchesMillis、waitForAllRequestsToBeAdded控制。它还支持include/excludeglob 或正则过滤、strategy入队策略与enqueueLinks一致AND 语义、baseUrl相对解析、transformRequestFunction转换以及onSkippedRequest回调覆盖 robots.txt 拒绝、过滤不匹配、重定向不符、达到maxRequestsPerCrawl等跳过场景。extendContext扩展上下文extendContext允许你向爬取上下文注入自定义助手它在导航之前运行因此返回值对preNavigationHooks、postNavigationHooks与requestHandler均可见但此时上下文中还没有page、response、$、body等导航产物。README 中的用法示例import { BasicCrawler } from crawlee; const crawler new BasicCrawler({ extendContext(context) ({ async customHelper() { await context.pushData({ url: context.request.url }) } }), async requestHandler(context) { await context.customHelper(); }, });statusMessage 与统计statusMessageLoggingInterval默认 10 秒周期性输出已爬 N 页、失败 M 次、期望并发 X的状态消息statusMessageCallback可覆盖默认消息需显式调用crawler.setStatusMessage()statistics可注入自定义Statistics实例含stateExtension自定义字段run()最终返回FinalStatistics成功数、失败数、重试直方图等。九、生命周期与运行控制BasicCrawler提供完整生命周期管理方法作用run(requests?)运行爬虫可再次调用以继续消费同一 request manager已处理的请求不会重跑addRequests()批量入队stop()优雅停止不再派发新请求允许进行中的任务完成pause()/resume()暂停派发不结束 run之后可恢复teardown()立即停止并清理从 run() 的实现可以看到完整的运行流程启动并发系统 →init()→ 开始采集统计 → 注册SIGINT/MIGRATING/ABORTING监听实现优雅的迁移与中止处理→dispatchRequests()驱动任务循环 → 停止统计、teardown、计算最终统计。期间还会周期性写入状态消息。十、何时该用更高级的爬虫README 明确给出选型建议如果你不想自己实现页面下载与数据提取直接使用现成的高层爬虫CheerioCrawler轻量级 HTTP Cheerio 解析适合纯静态页面PuppeteerCrawler无头 Chrome 自动化适合 JS 渲染页面PlaywrightCrawler跨浏览器自动化功能更现代。它们的共同点是复用BasicCrawler的全部调度内核只通过各自的上下文管道context pipeline补上下载页面 提供解析/浏览器上下文的环节。因此当你的需求属于以下场景时BasicCrawler是正解页面抓取逻辑完全自定义如抓取 PDF、二进制文件、调用内部 API需要最细粒度的调度与错误控制想基于 Crawlee 的并发、会话、代理、存储体系打造自己的专用爬虫框架。参考资源包入口与导出packages/basic-crawler/src/index.ts核心实现packages/basic-crawler/src/internals/basic-crawler.ts请求发送助手packages/basic-crawler/src/internals/send-request.ts运行循环packages/basic-crawler/src/internals/crawler-run.ts超时机制packages/basic-crawler/src/internals/request-timeout.ts测试示例packages/basic-crawler/test/batch-add-requests.test.ts更多入门示例接受输入、爬取单页、递归爬取等docs/examples 与 docs/guides【免费下载链接】crawleeCrawlee—A web scraping and browser automation library for Node.js to build reliable crawlers. In JavaScript and TypeScript. Extract data for AI, LLMs, RAG, or GPTs. Download HTML, PDF, JPG, PNG, and other files from websites. Works with Puppeteer, Playwright, Cheerio, JSDOM, and raw HTTP. Both headful and headless mode. With proxy rotation.项目地址: https://gitcode.com/GitHub_Trending/cr/crawlee创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价