Crawlee v3 升级指南:从 Apify SDK v2 迁移到 Crawlee 的完整实践手册

发布时间:2026/9/12 4:41:40
Crawlee v3 升级指南:从 Apify SDK v2 迁移到 Crawlee 的完整实践手册 Crawlee v3 升级指南从 Apify SDK v2 迁移到 Crawlee 的完整实践手册【免费下载链接】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本文基于仓库中 docs/upgrading/upgrading_v3.md 整理而成结合packages/下的源码与测试对各个变更点做源码级印证。Crawlee v3 是 Apify SDK v2 的精神继承者本次升级不仅是包名更替更是一次 API 全面重构Monorepo 拆分、TypeScript 全量重写、上下文感知助手、隐式 RequestQueue、批量入队、指纹伪装、内存存储等核心机制全部重做。读完本文你将掌握从 v2 平滑迁移到 v3 的完整改动清单以及每个关键 API 在源码中的真实实现位置与行为细节。:::info 阅读前提 本文面向已经熟悉 Apify SDK v2 的开发者。若你第一次接触 Crawlee建议先阅读 docs/introduction/01-setting-up.mdx 了解基础概念再回来看迁移细节。 :::一、背景为什么 Apify SDK v2 要变成 Crawlee v3直到apify包的 v3 之前Apify SDK 一直把爬虫工具和Apify 平台辅助方法打包在同一个包里。随着两个领域各自的复杂度不断上升v3 版本将整个项目拆分成两个独立部分Crawlee全新的网页抓取库以crawlee包发布到 NPM本仓库即其源码Apify SDKApify 平台辅助工具Actor类、存储、事件等以apify包独立发布。Crawlee 被命名为 v3 正是为了延续 Apify SDK 的版本号作为其精神继承者spiritual successor。这一拆分让两个项目可以各自独立演进版本、独立发布也让只想用爬虫能力的用户不必再引入平台相关的代码。二、Crawlee Monorepo一个元包多个子包crawlee包本身是一个 Monorepo由若干独立发布、统一挂在crawlee命名空间下的小包组成。原文档列出的核心子包如下子包导出内容 / 职责crawlee/core所有 Crawler 实现的基础包含Request、RequestQueue、RequestList、Dataset等类crawlee/cheerio导出CheerioCrawlercrawlee/playwright导出PlaywrightCrawlercrawlee/puppeteer导出PuppeteerCrawlercrawlee/jsdom导出JSDOMCrawlercrawlee/basic导出BasicCrawlercrawlee/http导出HttpCrawlercrawlee/jsdom与crawlee/cheerio的基类crawlee/browser导出BrowserCrawlercrawlee/playwright与crawlee/puppeteer的基类crawlee/memory-storageapify/storage-local的替代品crawlee/browser-pool原browser-pool包crawlee/utils工具方法crawlee/types主要存放关于StorageClient的 TS 接口这些包在仓库中一一对应packages/目录下的同名子目录如 packages/core、packages/cheerio-crawler、packages/browser-pool 等并通过pnpm-workspace.yaml组织为工作区。安装策略按需安装单个子包或直接装元包大部分 Crawlee 包是互相继承并 re-export的所以通常只需要安装你要用的那一个。例如安装crawlee/playwright时它已经包含了crawlee/browser的全部内容而后者又包含crawlee/basic进而包含crawlee/core的全部内容。如果不介意多拉一点代码可以直接使用crawlee元包meta-package它 re-export 了大部分crawlee/*包因此包含所有 Crawler 类npm install crawlee如果只需要 Cheerio 支持只装crawlee/cheerio即可npm install crawlee/cheerio使用playwright或puppeteer时还需要显式安装浏览器库本身——这样用户可以完全控制浏览器库的版本npm install crawlee playwright # 或 npm install crawlee/playwright playwright提示如果偶尔想用crawlee/utils里的工具方法可以额外安装它。这个包包含此前Apify.utils下的一部分工具浏览器相关的工具方法则可以直接从 crawler 包如crawlee/playwright里拿到。三、全量 TypeScript 支持与项目配置Crawlee 和 Apify SDK 都是全量 TypeScript 重写因此包内自带最新类型的声明。官方推荐使用apify/tsconfig包里预置的 TypeScript 配置并且务必把module和target设为ES2022或更高以便使用顶层 awaittop level await{ extends: apify/tsconfig, compilerOptions: { module: ES2022, target: ES2022, outDir: dist, lib: [DOM] }, include: [ ./src/**/* ] }注意apify/tsconfig默认开启了noImplicitAny。如果你在开发初期还有未使用的局部变量它会直接导致构建失败可以先临时关掉它等代码稳定后再打开。Docker 多阶段构建对于Dockerfile原文档推荐多阶段构建multi-stage build避免把 TypeScript 这类 devDependencies 装进最终镜像# 使用多阶段构建因为需要 dev deps 来编译 TS 源码 FROM apify/actor-node:20 AS builder # 拷贝所有文件、安装全部依赖含 dev deps并构建 COPY . ./ RUN npm install --includedev \ npm run build # 创建最终镜像 FROM apify/actor-node:20 # 只拷贝必要文件 COPY --frombuilder /usr/src/app/package*.json ./ COPY --frombuilder /usr/src/app/README.md ./ COPY --frombuilder /usr/src/app/dist ./dist COPY --frombuilder /usr/src/app/apify.json ./apify.json COPY --frombuilder /usr/src/app/INPUT_SCHEMA.json ./INPUT_SCHEMA.json # 只安装生产依赖 RUN npm --quiet set progressfalse \ npm install --onlyprod --no-optional \ echo Installed NPM packages: \ (npm list --onlyprod --no-optional --all || true) \ echo Node.js version: \ node --version \ echo NPM version: \ npm --version # 运行编译后的代码 CMD npm run start:prod第一阶段builder安装全部依赖并执行npm run build产出dist第二阶段只拷贝package*.json、README.md、dist以及平台配置文件然后仅安装生产依赖最大程度缩小镜像体积。四、浏览器指纹从stealth魔法到可配置指纹v2 时代 Puppeteer Crawler 里有一个神奇的stealth选项它开启了一系列模仿真实用户的技巧。它虽然有一定效果但 Crawlee 决定用**生成的浏览器指纹browser fingerprints**来取代它——指纹比固定技巧更接近真实浏览器的多样性。如果不想使用动态指纹可以在browserPoolOptions中通过useFingerprints: false关闭const crawler new PlaywrightCrawler({ browserPoolOptions: { useFingerprints: false, }, });在 packages/browser-pool/src/browser-pool.ts 中可以印证useFingerprints的默认值是truefingerprintOptions默认是空对象。同时源码显示指纹缓存相关配置useFingerprintCache默认true、fingerprintCacheSize默认10000见同文件 L986-L990指纹生成器FingerprintGenerator会在启用时被创建。相关重命名fingerprintsOptions→fingerprintOptionsv3 还顺带把选项名统一为单数fingerprintsOptions改名为fingerprintOptionsfingerprints→fingerprint。更重要的是缓存策略从按代理 URL 缓存改成了按会话缓存useFingerprintPerProxyCache、fingerprintPerProxyCacheSize不再可用取而代之的是useFingerprintCache和fingerprintCacheSize——因为缓存的指纹不再与代理 URL 绑定而是与session绑定。五、Session Cookie 方法重命名此前要读写会话session的 cookie需要调用session.getPuppeteerCookies()或session.setPuppeteerCookies()。但这个方法并不只服务于PuppeteerCrawler任何 Crawler 都可能用到因此重命名为更通用的session.getPuppeteerCookies()→session.getCookies()session.setPuppeteerCookies()→session.setCookies()除此之外的用法完全一致迁移时只需全局替换方法名。六、默认存储改为内存存储Memory Storagev3 默认使用crawlee/memory-storage来存储数据与中间状态例如RequestQueue持有的状态它是对apify/storage-local的替代状态存在内存中而apify/storage-local用的是 SQLite 数据库同时也会把状态转储到文件系统方便观察并且会尊重 KeyValueStore 里已存在的数据例如INPUT.json文件。要在 Apify 平台上运行需要使用Actor.init或Actor.main它们会在检测到 Apify 平台环境时自动把存储客户端切换为ApifyClient本地运行则保持默认的内存存储。如果仍想使用apify/storage-local需要先安装它v2.1.0 才支持 Crawlee再传给Actor.init或Actor.main的选项import { Actor } from apify; import { ApifyStorageLocal } from apify/storage-local; const storage new ApifyStorageLocal(/* 例如 enableWalMode 等选项写在这里 */); await Actor.init({ storage });七、默认存储清理行为反转v2 时代本地多次运行之间状态会保留必须靠apify-cli的--purge参数手动清理。Crawlee 把这一行为反转Actor.init/main调用时默认自动清理存储。想退出这一行为在Actor.init选项中传purge: falseawait Actor.init({ purge: false });从源码可以印证仓库中对应的配置项是purgeOnStart默认true并可用环境变量CRAWLEE_PURGE_ON_START覆盖见 packages/core/src/configuration.ts。同时StorageClient接口新增了可选的purge方法清理逻辑被移动到了存储类本身原先的purgeLocalStorage辅助函数被移除。八、Crawler 选项与接口重命名v3 重命名了一批选项让它们更准确地表达含义。旧的参数名在运行时仍然支持但在 TS 类型层面不再提供旧名称新名称handleRequestFunctionrequestHandlerhandlePageFunctionrequestHandlerhandleRequestTimeoutSecsrequestHandlerTimeoutSecshandlePageTimeoutSecsrequestHandlerTimeoutSecsrequestTimeoutSecsnavigationTimeoutSecshandleFailedRequestFunctionfailedRequestHandler同时爬取上下文crawling context的接口也按同一约定重命名CheerioHandlePageInputs→CheerioCrawlingContextPlaywrightHandlePageFunction→PlaywrightCrawlingContextPuppeteerHandlePageFunction→PuppeteerCrawlingContext九、上下文感知助手Context-aware helpers此前挂在Apify.utils命名空间下的一部分工具现在移动到了**爬取上下文crawling context**中并变得上下文感知context aware部分参数会自动从上下文填充例如当前的Request实例、当前的Page对象或与 Crawler 绑定的RequestQueue。enqueueLinks不再需要手动传参最典型的例子是enqueueLinks。它是上下文感知的不再需要传入requestQueue、page参数Cheerio 场景下也不需要传入$。它还提供3 种入队策略策略枚举值字符串值匹配规则EnqueueStrategy.Allall匹配页面中找到的任何 URLEnqueueStrategy.SameHostnamesame-hostname匹配与基准 URL同子域名的 URL默认策略EnqueueStrategy.SameDomainsame-domain匹配与基准 URL同域名的 URL。例如基准 URL 为https://example.com时https://wow.an.example.com和https://example.com都会被匹配这意味着甚至可以不带任何参数直接调用enqueueLinks()——默认会遍历当前页面所有链接只保留指向同一子域名的那些。从源码看策略枚举定义在 packages/utils/src/internals/url.ts除了上述三种实际还存在第四种SameOriginsame-origin要求主机名与协议都相同。enqueueLinks的实现位于 packages/core/src/enqueue_links/enqueue_links.ts其中strategy默认值为EnqueueStrategy.SameHostnameL126。另外还可以通过 glob 指定 URL 必须匹配的模式const crawler new PlaywrightCrawler({ async requestHandler({ enqueueLinks }) { await enqueueLinks({ globs: [https://crawlee.dev/*/*], // 这里也可以使用 regexps 和 pseudoUrls }); }, });错误日志变得更简洁v2 中request handler 抛出的错误会导致整个错误对象被完整打印。Crawlee 在确认请求会被重试的情况下只把错误消息作为 warning 输出。想恢复 v2 那样详细的日志设置环境变量CRAWLEE_VERBOSE_LOG即可。这一点在 packages/basic-crawler/src/internals/basic-crawler.ts 有源码印证CRAWLEE_VERBOSE_LOG存在时打印完整error.stack否则只输出error.message。sendRequest()处理上下文绑定的请求v3 移除了requestAsBrowser并新增context.sendRequest()助手允许把上下文绑定的Request对象交给 got-scraping 处理const crawler new BasicCrawler({ async requestHandler({ sendRequest, log }) { // 可以用 options 参数覆盖 gotScraping 的选项 const res await sendRequest({ responseType: json }); log.info(received body, res.body); }, });关于sendRequest()的详细用法见仓库中的 Got Scraping 指南。十、隐式RequestQueue与批量入队隐式 RequestQueue 实例所有 Crawler 现在都通过crawler.getRequestQueue()方法自动获得RequestQueue实例——实例不存在时会自动创建。这意味着不再需要手动创建RequestQueue直接使用下面的crawler.addRequests()方法即可。仍然可以显式创建RequestQueue并通过 crawler 选项传入crawler.getRequestQueue()会尊重它并返回你提供的实例。源码实现在 packages/basic-crawler/src/internals/basic-crawler.tsgetRequestQueue()在不存在时自动创建队列。crawler.addRequests()分批添加海量请求新增的addRequests方法会批量添加请求先入队前 1000 个请求并 resolve剩余的在后台继续以 1000 个为一小批添加从而避免触发 API 限流。这意味着爬取几乎立刻开始最多几秒内而这在 v2 中只有组合使用RequestQueue和RequestList才能实现。// 在前 1000 个请求入队后立即 resolverequests 可以是数百万级 const result await crawler.addRequests([/* many requests, can be even millions */]); // 如果想等所有请求都入队await 这个 promise 即可 await result.waitForAllRequestsToBeAdded;在源码中addRequests是对隐式RequestQueue的addRequestsBatched()的别名见 packages/basic-crawler/src/internals/basic-crawler.ts返回的CrawlerAddRequestsResult上挂着waitForAllRequestsToBeAdded。十一、Request.label快捷方式给请求打标签labelingv2 时代需要操作Request.userData对象。v3 提供了Request.label快捷方式它是一对get/set访问器读写的就是userData里的值。该快捷方式同样被加入到了enqueueLinks的选项接口中。在 packages/core/src/request.ts 可以看到实现label的 getter 返回this.userData.labelsetter 写入this.userData.label。构造函数中若传入label也会自动写入userData.label同文件 L244-L246因此它与userData完全等价。async requestHandler({ request, enqueueLinks }) { if (request.label ! DETAIL) { await enqueueLinks({ globs: [...], label: DETAIL, }); } }十二、移除requestAsBrowser全面转向 got-scrapingv1 中requestAsBrowser的底层实现已经是got-scraping一个尽力模仿真实浏览器的got扩展的薄封装。v3 直接移除requestAsBrowser鼓励直接使用got-scraping。为便于迁移v3 新增了上一节提到的context.sendRequest()助手。被移除的选项useInsecureHttpParser已移除现在永久设为true以更好地模仿浏览器行为useHttp2已移除。got-scraping 会自动进行协议协商HTTP/2 能力被设为true——如今 100% 的浏览器都支持 HTTP/2Web 也在大规模使用它。被重命名的选项payload→body/jsonpayload代表要发送的请求体可以是字符串或Buffer。现在没有payload选项了改用body想发 JSON 则用json// Before: await Apify.utils.requestAsBrowser({ …, payload: Hello, world! }); await Apify.utils.requestAsBrowser({ …, payload: Buffer.from(c0ffe, hex) }); await Apify.utils.requestAsBrowser({ …, json: { hello: world } }); // After: await gotScraping({ …, body: Hello, world! }); await gotScraping({ …, body: Buffer.from(c0ffe, hex) }); await gotScraping({ …, json: { hello: world } });ignoreSslErrors→https.rejectUnauthorizedignoreSslErrors被重命名为https.rejectUnauthorized。默认值是false即默认不校验方便使用。注意语义相反所以取值也要取反// Before: await Apify.utils.requestAsBrowser({ …, ignoreSslErrors: false }); // After: await gotScraping({ …, https: { rejectUnauthorized: true } });header-generator选项useMobileVersion、languageCode、countryCode三个选项都不存在了需要直接使用headerGeneratorOptions// Before: await Apify.utils.requestAsBrowser({ …, useMobileVersion: true, languageCode: en, countryCode: US, }); // After: await gotScraping({ …, headerGeneratorOptions: { devices: [mobile], // 或 [desktop] locales: [en-US], }, });timeoutSecs→timeout.request设置超时改用timeout.request并且单位是毫秒// Before: await Apify.utils.requestAsBrowser({ …, timeoutSecs: 30, }); // After: await gotScraping({ …, timeout: { request: 30 * 1000, }, });throwOnHttpErrors→throwHttpErrors该选项决定是否在非成功 HTTP 状态码例如 404时抛出异常。默认值为false。decodeBody→decompress该选项控制是否解压响应体。默认true——除非你很清楚后果否则不要改否则很多网站会解析失败。abortFunction的替代方案这个函数曾经在返回true时让 promise 针对特定响应抛出异常但实用性有限。现在的推荐做法是主动取消请求const promise gotScraping(…); promise.on(request, request { // 注意这里不是 Got 的 Request 实例而是 Node 的 ClientRequest 实例 // https://nodejs.org/api/http.html#class-httpclientrequest if (request.protocol ! https:) { // 非安全请求中止 promise.cancel(); // 如果设置了 isStream: true请改用 stream.destroy() } }); const response await promise;十三、禁止混合浏览器池插件v2 允许创建一个同时混用 Puppeteer 和 Playwright 插件甚至自定义插件的浏览器池。从 v3 起这不再被允许创建此类池会抛出错误——所有将要使用的插件必须是同一类型。:::info 别混淆了 这个变更只是禁止把 Puppeteer 与 Playwright 混在一个池里。你仍然可以创建使用多个 Playwright 插件各自使用不同 launcher的池。 :::这一点与仓库中的测试相印证test/browser-pool/下存在专门的no-hybrid-plugins.test.ts测试来验证混合插件被拒绝的行为。十四、在浏览器之外处理请求一个值得注意的小功能浏览器型 Crawler 也可以在浏览器之外处理请求。做法是组合使用Request.skipNavigation和context.sendRequest()。Request.skipNavigation在 packages/core/src/request.ts 中实现置为true时crawler 会跳过浏览器导航、直接处理请求此时上下文里将没有导航结果response、body、contentType、$、request.loadedUrl等访问这些属性会抛出NavigationSkippedError。完整的示例见 跳过导航示例 以及配套代码 skip-navigation.ts。十五、日志系统与上下文日志Crawlee 把默认的log实例作为命名导出直接暴露。同时爬取上下文中提供了一个带作用域的log实例——它打印的日志会带上前缀 crawler 名称在 request handler 内部做日志时应优先使用它const crawler new CheerioCrawler({ async requestHandler({ log, request }) { log.info(Opened ${request.loadedUrl}); }, });十六、自动保存的爬虫状态useState()每个 Crawler 实例都有useState()方法返回一个状态对象。当persistState事件触发时它会被自动保存。值是被缓存的因此可以多次调用此方法并拿到完全相同的引用——不需要操心保存会自动完成const crawler new CheerioCrawler({ async requestHandler({ crawler }) { const state await crawler.useState({ foo: [] as number[] }); // 直接改值即可无需关心保存 state.foo.push(123); }, });从源码看useState的实现位于 packages/basic-crawler/src/internals/basic-crawler.ts它打开 KeyValueStore 并调用getAutoSavedValue()获取自动保存的值多个 crawler 实例同时使用useState()且未指定显式id时会共享同一个状态对象并收到警告建议为每个实例传入唯一id。十七、Apify SDK平台辅助工具的新家Apify 平台相关的辅助方法现在统一在 Apify SDKapifyNPM 包中它导出Actor类提供以下静态助手ApifyClient快捷方式addWebhook()、call()、callTask()、metamorph()在 Apify 平台运行的助手init()、exit()、fail()、main()、isAtHome()、createProxyConfiguration()存储支持getInput()、getValue()、openDataset()、openKeyValueStore()、openRequestQueue()、pushData()、setValue()事件支持on()、off()其他工具getEnv()、newClient()、reboot()Actor.main只是语法糖Actor.main本质上是Actor.init() 用户函数 Actor.exit()的语法糖外加 try/catch 包裹。所有方法都是 async 的且应被 await——Node 16 及以上可以用顶层 await。以下两种写法等价import { Actor } from apify; await Actor.init(); // your code await Actor.exit(Crawling finished!);import { Actor } from apify; await Actor.main(async () { // your code }, { statusMessage: Crawling finished! });Actor.init()会在 Apify 平台上把 Crawlee 的存储实现条件性地切换为ApifyClient否则保留默认的内存存储实现同时会订阅 websocket 事件本地运行时则模拟它们。Actor.exit()负责清理资源并调用process.exit()确保进程不会因某些原因无限挂起。事件系统从Apify.events到EventManagerApify SDK v2 导出Apify.events它是一个EventEmitter实例。Crawlee 中事件改由EventManager类管理。可以通过Actor.eventManagergetter 访问或者直接使用Actor.on/Actor.off快捷方式-Apify.events.on(...); Actor.on(...);也可以通过Configuration.getEventManager()拿到EventManager实例。在既有事件之外现在还有一个exit事件在调用Actor.exit()时触发Actor.main()结束时也会调用它。这个事件允许你在Actor.exit被调用时优雅地关停任何资源。十八、更小/内部级别的破坏性变更清单原文档还列出了一批较小的破坏性变更迁移时请逐一核对Apify.call()现在是ApifyClient.actor(actorId).call(input, options)的快捷方式同时会考虑环境变量中的 tokenApify.callTask()现在是ApifyClient.task(taskId).call(input, options)的快捷方式同时会考虑环境变量中的 tokenApify.metamorph()现在是ApifyClient.task(taskId).metamorph(input, options)的快捷方式同时会考虑环境变量中的ACTOR_RUN_IDApify.waitForRunToFinish()已移除改用ApifyClient.waitForFinish()Actor.main/init默认清理存储可用purge: false退出移除purgeLocalStorage辅助函数清理逻辑移到存储类本身StorageClient接口新增可选purge方法清理通过Actor.init()自动发生QueueOperationInfo.request不再可用Request.handledAt现在是 ISO 格式的字符串日期源码中可见其定义与校验见 packages/core/src/request.tsRequest.inProgress和Request.reclaimed从 POJO 变成了Setpuppeteer utils 中的injectUnderscore已移除APIFY_MEMORY_MBYTES不再被考虑改用CRAWLEE_AVAILABLE_MEMORY_RATIO默认值0.25见 packages/core/src/configuration.ts部分AutoscaledPool选项不再可用cpuSnapshotIntervalSecs和memorySnapshotIntervalSecs被顶层配置systemInfoIntervalMillis取代默认1000ms见 packages/core/src/configuration.tsmaxUsedCpuRatio被移到顶层配置ProxyConfiguration.newUrlFunction可以是 async 的.newUrl()和.newProxyInfo()现在返回 promiseprepareRequestFunction和postResponseFunction选项被移除改用 navigation hooksgotoFunction和gotoTimeoutSecs被移除移除了对旧/损坏的含 nullRequest属性的请求队列的兼容性修复fingerprintsOptions改名为fingerprintOptionsfingerprints→fingerprintfingerprintOptions现在接受useFingerprintCache和fingerprintCacheSize取代已不再可用的useFingerprintPerProxyCache和fingerprintPerProxyCacheSize因为缓存的指纹不再关联代理 URL而是关联session。十九、迁移检查清单把以上所有变更归纳成一份可直接对照的检查清单依赖按需安装crawlee元包或crawlee/*子包使用 Playwright/Puppeteer 时记得显式安装对应浏览器库TypeScript 配置extends: apify/tsconfigmodule/target设为ES2022以支持顶层 await选项重命名handlePageFunction→requestHandler、handlePageTimeoutSecs→requestHandlerTimeoutSecs、requestTimeoutSecs→navigationTimeoutSecs、handleFailedRequestFunction→failedRequestHandler上下文接口CheerioHandlePageInputs→CheerioCrawlingContext、PlaywrightHandlePageFunction→PlaywrightCrawlingContext、PuppeteerHandlePageFunction→PuppeteerCrawlingContext存储默认使用crawlee/memory-storage在 Apify 平台用Actor.init/main自动切换ApifyClient需要时可用apify/storage-localv2.1.0本地默认自动清理存储purge: false退出Session cookiegetPuppeteerCookies()/setPuppeteerCookies()→getCookies()/setCookies()入队直接用上下文感知的enqueueLinks()默认SameHostname策略大批量请求用crawler.addRequests()并配合waitForAllRequestsToBeAdded标签用Request.label代替手动操作userData.labelHTTP 请求移除requestAsBrowser改用got-scraping或context.sendRequest()并按上文映射表重命名各选项浏览器池禁止混用 Puppeteer 与 Playwright 插件状态用crawler.useState()获取自动保存的状态平台代码Apify.events→Actor.on/off或EventManagerwaitForRunToFinish→ApifyClient.waitForFinish()环境变量APIFY_MEMORY_MBYTES→CRAWLEE_AVAILABLE_MEMORY_RATIO需要详细错误日志时设置CRAWLEE_VERBOSE_LOG。延伸阅读完整的 v2 → v3 官方升级文档本文的原始依据Crawlee 版本迁移总览Got Scraping 指南sendRequest()的详细用法跳过导航示例skipNavigationsendRequest()内存存储实现浏览器池实现指纹、插件等Request 类实现label、skipNavigation、uniqueKey等【免费下载链接】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),仅供参考