Crawlee JSDOMCrawler 实战指南用 Window API 在 Node.js 中高效爬取静态页面【免费下载链接】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/crawleeJSDOMCrawler 是 Crawleecrawlee/jsdom包提供的一款基于纯 HTTP 请求 jsdom DOM 解析的爬虫框架适合抓取无需 JavaScript 渲染的静态页面并以前端开发者熟悉的window对象来提取数据。读完本文你将掌握 JSDOMCrawler 的工作原理、完整配置项并发、MIME 类型、runScripts等、URL 供给方式以及基于源码级的实现细节能够快速搭建可上线的静态页面采集任务。一、JSDOMCrawler 是什么JSDOMCrawler是 Crawlee 中专门面向「纯 HTTP DOM 解析」场景的爬虫。它的核心工作流在 packages/jsdom-crawler/README.md 中被概括为三步用普通 HTTP 请求下载目标 URL 的 HTML将 HTML 交给 jsdom 解析调用用户提供的requestHandler通过window对象提取页面数据。由于它用原始 HTTP 请求下载页面不启动浏览器因此在数据带宽消耗和速度上都十分高效特别适合目标网站内容直接内联在首屏 HTML 中的场景。何时需要换用浏览器型爬虫如果目标网站依赖 JavaScript 才能渲染内容例如 SPA、动态列表则应改用PuppeteerCrawler或PlaywrightCrawler——它们通过完整的无头 Chrome 加载页面。这一点在原文档中已有明确说明也是选型时的第一判断标准。二、工作原理从 HTTP 响应到 window 对象2.1 整体架构位置JSDOMCrawler的继承链是JSDOMCrawler→DOMCrawler→HttpCrawler→BasicCrawler。其中HttpCrawler 负责发起 HTTP 请求、处理响应编码与 MIME 类型DOMCrawler 负责将响应体交给可插拔的DOMParser解析成 DOM并注入extractLinks、enqueueLinks、waitForSelector、parseWithCheerio等辅助方法JSDOMCrawler则把 jsdom 作为默认的DOMParser从而让爬取上下文携带window、document、body等成员。从源码看JSDOMCrawler在构造函数中通过jsdomParser({ runScripts, virtualConsole, log })组装解析器再传给DOMCrawler见 jsdom-crawler.ts。DOMCrawler的buildContextPipeline会把parse → cleanup → addHelpers三个阶段依次组合进请求上下文管道见 dom-crawler.ts。2.2 jsdom 解析器的具体行为jsdomParser的实现位于 jsdom-parser.ts几个值得注意的细节根据响应的Content-Type判断 XML/HTML并分别以text/xml或text/html的 contentType 构造JSDOM实例通过ResourceLoader加载子资源User-Agent 固定为Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36设置了pretendToBeVisual: true并补齐了window.matchMedia与Range.prototype.getBoundingClientRect等 jsdom 缺失的 API stub避免页面脚本在解析阶段直接崩溃返回的解析结果JSDOMParseResult包含window、document以及惰性求值的body即document.documentElement.outerHTML每个请求处理完毕后调用window.close()释放资源见cleanup。2.3 一个最小示例原文档给出如下最小示例JavaScriptconst crawler new JSDOMCrawler({ async requestHandler({ request, window }) { await Dataset.pushData({ url: request.url, title: window.document.title, }); }, }); await crawler.run([ http://crawlee.dev, ]);在 TypeScript 项目中推荐参考官方示例 docs/examples/jsdom_crawler.ts它演示了更完整的用法设置minConcurrency/maxConcurrency、maxRequestRetries、requestHandlerTimeoutSecs、maxRequestsPerCrawl在requestHandler中同时提取标题与所有h1文本并写入数据集还通过failedRequestHandler处理重试后仍失败的请求。三、URL 供给静态列表与动态队列爬取源 URL 由Request对象表示来源有两类RequestList静态列表通过requestList构造选项传入适合 URL 数量固定、已知的场景RequestQueue动态队列通过requestQueue构造选项传入支持在爬取过程中不断入队新 URL从而实现递归爬取整站。3.1 两者同时使用的合并语义原文档特别强调了一个重要行为如果同时提供requestList和requestQueue爬虫会先把 RequestList 中的全部 URL 自动入队到 RequestQueue再开始处理。这保证了同一 URL 不会被重复爬取。3.2 当前版本的 requestManager 抽象值得补充的是从 4.x 源码看requestList/requestQueue两个选项已被标记为deprecated它们会被折叠进统一的requestManagerRequestQueue 本身就是一个 request manager。如果需要「从只读的 RequestList 读取、同时还能入队新请求」可以使用requestManager配合RequestManagerTandem实现见 jsdom-crawler.ts。该注释同样适用于HttpCrawler见 http-crawler.ts。爬虫在没有任何待爬取Request时结束。四、preNavigationHooks请求发出前调整参数原文档提到可以在导航即实际发 HTTP 请求之前通过preNavigationHooks调整请求行为。以文档示例为骨架的写法如下preNavigationHooks: [ (crawlingContext, gotOptions) { // 在这里修改请求选项例如自定义 headers、处理会话等 // ... }, ],从源码看preNavigationHooks是HttpCrawlerOptions的标准选项默认[]整个「导航窗口」由navigationTimeoutSecs默认 30 秒统一预算前置钩子、HTTP 请求、后置钩子共享同一超时窗口慢钩子会消耗导航本身的预算见 http-crawler.ts。此外还有postNavigationHooks可在请求完成后校验响应甚至可以返回新的response覆盖原响应。五、MIME 类型控制additionalMimeTypes默认情况下JSDOMCrawler只处理以下 MIME 内容类型依据 HTTP 响应头Content-Type判定其他类型直接跳过text/htmlapplication/xhtmlxmltext/xmlapplication/xmlapplication/json原 README 只列出了前两种但当前源码 http-crawler.ts 中的HTML_AND_XML_MIME_TYPES与APPLICATION_JSON_MIME_TYPE表明实际支持范围为上面五类——这是新旧文档/实现差异使用时以源码为准。如需处理其他内容类型使用additionalMimeTypes构造选项const crawler new JSDOMCrawler({ additionalMimeTypes: [application/javascript, text/css], async requestHandler({ window }) { // ... }, });需要留意HTML、XML、JSON 等不同类型的解析行为不同例如 JSON 响应会先被解析为json对象具体差异取决于requestHandler的处理方式。另外从源码看HttpCrawler在abortDownloadOfBody中会在下载响应体之前就根据 MIME 类型做拦截不支持的类型会抛错并跳过该资源见 http-crawler.ts所以additionalMimeTypes也在一定程度上避免了无谓的响应体下载。六、并发控制ConcurrencySystem 与相关选项JSDOMCrawler只有在 CPU 与内存余量充足时才会派发新请求这一判断由爬虫内部的ConcurrencySystem完成。调节方式有两层常用层通过JSDOMCrawler构造选项minConcurrency、maxConcurrency和maxRequestsPerMinute调参精细层直接注入一个预配置好的concurrencySystem实例。从源码看HttpCrawler为纯 HTTP 爬虫专门定义了HTTP_OPTIMIZED_CONCURRENCY_SYSTEM_OPTIONS默认目标并发desiredConcurrency: 10并对事件循环负载做了宽松配置快照间隔 2 秒、最大阻塞 100ms、过载阈值 0.7——因为纯 HTTP 爬取几乎不占用事件循环见 http-crawler.ts。JSDOMCrawler会继承这一套默认调优。若你自行提供concurrencySystem默认调优会被整体替换需要手动展开该常量保留import { ConcurrencySystem } from crawlee; const concurrencySystem new ConcurrencySystem({ ...HTTP_OPTIMIZED_CONCURRENCY_SYSTEM_OPTIONS, maxConcurrency: 50, });此外DOMCrawler的waitForSelector辅助方法在解析器不可变mutable: false即未开启runScripts时只检查一次选择器并立即返回或抛错只有当解析器标记为可变runScripts: true时才会以 50ms 间隔轮询直到超时默认 5 秒这一设计见 dom-crawler.ts。七、JSDOMCrawler 专属选项runScripts 与 hideInternalConsole除了继承自HttpCrawler/BasicCrawler的选项外JSDOMCrawlerOptions还定义了两个专属布尔选项见 jsdom-crawler.ts选项默认值作用runScriptsfalse是否下载并执行页面内嵌/外链脚本对应 jsdom 的runScripts: dangerouslyhideInternalConsolefalse是否抑制 jsdom 内部 console 的输出7.1 runScripts在 Node 中运行页面脚本默认JSDOMCrawler不执行任何 JavaScript这正是它比浏览器型爬虫快的原因。但 jsdom 本身也支持执行脚本——开启runScripts: true后页面脚本会在 Node 进程中运行可以触发部分动态内容。需要清醒认识两点jsdom 并未完整实现所有 Web 标准很多现代浏览器 API 缺失网站脚本可能因此报错甚至「跑不起来」原文档与类注释均明确提示了这一限制见 jsdom-crawler.ts开启后解析结果被标记为mutablewaitForSelector会进入轮询模式同时解析器会等待window的load事件并设置了10 秒超时保护见 jsdom-parser.ts。7.2 getVirtualConsole 与 hideInternalConsoleJSDOMCrawler暴露了getVirtualConsole()方法返回当前使用的 jsdomVirtualConsole实例可用来监听 jsdom 内部的 console 消息见 jsdom-crawler.tsconst virtualConsole crawler.getVirtualConsole(); virtualConsole.on(error, (error) { log.error(error); });当hideInternalConsole: true时jsdom 消息默认不再转发到进程 console但你依然可以通过getVirtualConsole()监听无论是否隐藏jsdom 内部的jsdomError都会被记录到 Crawlee 的 debug 日志中。八、Window / Element API前端开发者友好JSDOMCrawler最直观的价值在于爬取上下文里的window对象与浏览器前端开发几乎一致。官方指南 docs/guides/jsdom_crawler.mdx 给出了对照document.title; // 浏览器中 window.document.title; // JSDOMCrawler 中8.1 提取页面全部链接Array.from(document.querySelectorAll(a[href])).map((a) a.href);8.2 使用场景何时选 JSDOMCrawler当CheerioCrawler不够用、但页面又不需要 JavaScript 渲染时JSDOMCrawler是最佳中间选择因为它暴露了完整的 HTML DOM API 集合。优势易于配置上手对前端开发者熟悉友好Window API可以对页面内容进行 DOM 级操作自动规避一部分反爬检测无需执行 JS请求特征更接近普通客户端。劣势比CheerioCrawler慢jsdom 解析开销高于 cheerio不适用于依赖 JavaScript 渲染的网站高并发下容易对目标网站造成压力需要合理设置并发上限。8.3 上下文辅助方法得益于DOMCrawler注入见 dom-crawler.tsrequestHandler上下文还提供extractLinks({ selector?, baseUrl? })从解析后的 DOM 提取 URL默认选择器为abaseUrl 优先取request.loadedUrl不加入请求队列enqueueLinks(options?)提取 URL 并批量加入请求队列默认EnqueueStrategy.SameHostname仅入队同主机链接支持maxCrawlDepth等过滤策略——该行为有测试覆盖见 dom_crawler.test.tswaitForSelector(selector, timeoutMs?)等待选择器匹配到元素默认超时 5 秒仅runScripts开启时轮询parseWithCheerio(selector?, timeoutMs?)把当前页面包成 Cheerio 句柄用与CheerioCrawler相同的方式处理数据。九、基于标签的路由createJSDOMRouter对于多页面类型的站点推荐使用createJSDOMRouter()创建基于 request label 的路由器作为requestHandler使用见 jsdom-crawler.tsimport { JSDOMCrawler, createJSDOMRouter } from crawlee; const router createJSDOMRouter(); router.addHandler(label-a, async (ctx) { ctx.log.info(Handling label-a...); }); router.addDefaultHandler(async (ctx) { ctx.log.info(Handling default...); }); const crawler new JSDOMCrawler({ requestHandler: router, }); await crawler.run();它等价于Router.createJSDOMCrawlingContext()的快捷方式让「同一个爬虫处理不同页面类型」的代码组织更清晰。十、已知限制与使用注意根据类注释jsdom-crawler.tsJSDOMCrawler存在以下限制代理与 Cookie 支持尚不完整jsdom 子资源加载的每次会话从空 cookie store 开始User-Agent 也固定为 Chrome 标识解析器源码中硬编码开启runScripts后 jsdom 的标准实现覆盖不全复杂页面脚本可能失败只有处理完所有Request后爬虫才会结束请确保队列不会被无限增长的 URL 撑爆合理使用maxRequestsPerCrawl或enqueueLinks过滤策略。此外crawlee/jsdom当前版本要求Node.js 22见 package.json依赖 jsdom 26.x官方对 JSDOMCrawler 的完整指南可继续阅读 docs/guides/jsdom_crawler.mdx更多可运行示例见 docs/examples/jsdom_crawler.ts。小结JSDOMCrawler在 Crawlee 的爬虫谱系中占据「比 HTTP 更强、比浏览器更轻」的生态位它以纯 HTTP 请求保证速度与带宽效率以 jsdom 提供完整 Window API 提升提取能力配合RequestQueue递归爬取、ConcurrencySystem自适应并发、preNavigationHooks请求定制与additionalMimeTypes内容类型扩展足以覆盖绝大多数静态站点的数据采集需求。当你遇到「Cheerio 不够用、又不想为渲染买单」的场景时JSDOMCrawler 就是那个恰到好处的选择。【免费下载链接】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),仅供参考