Crawlee 爬虫专家思维指南:12 条可复用的 Web Scraping 实战原则
发布时间:2026/9/12 13:11:27 作者:尧图编辑部 阅读量:1,286

Crawlee 爬虫专家思维指南12 条可复用的 Web Scraping 实战原则【免费下载链接】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 社区博客《12 tips on how to think like a web scraping expert》原始文档整理扩写。原文档由社区成员 Max Bohomolov 投稿讲述的不是某个具体库的用法而是作者在真实爬虫项目中反复验证的思维方法与排查套路。读完本文你将掌握一套可复用的决策框架如何选择数据源、如何借助robots.txt与sitemap快速建链、如何用 DevTools 反向分析页面数据流、如何用最少的请求拿到最多的数据以及这些方法论在 Crawlee 仓库中对应的源码级支撑crawlee/utils、crawlee/core中的RobotsTxtFile、Sitemap、SitemapRequestLoader等模块。写在前面为什么需要思维层面的指南常规教程都在讲可复制的技术细节从哪开始、按什么路径走、最终到达哪里。这适合学习某个具体技术但很难回答一个关键问题——作者当初为什么决定这样做是什么在指导他的开发决策本文要讨论的是作者在从事爬虫项目时引导他拿到好结果的一般性规则与原则。它们不是某个库的 API 手册而是一套可以沉淀为项目启动前 checklist的思维习惯。1. 为项目选择正确的数据源开始一个项目时你通常已经有一个目标站点并需要从其中提取特定数据。第一步不是写代码而是先确认这个站点或应用为数据提取提供了哪些可能性官方 API站点可能提供免费的官方 API能拿到全部所需数据。这是最优选项。例如 Yelp 就提供官方 API适合作为首选数据来源。网站本身这种情况下需要研究网站结构以及前端与后端交互的方式。移动应用有些场景下既没有网站也没有 API或者移动应用能提供更多数据。此时不要忘记中间人man-in-the-middle代理方案——通过代理截获移动应用与后端通信的流量来提取数据。如果一种数据源行不通就尝试另一种。仍以 Yelp 为例官方 API、网站、移动应用三条路径全部可用如果官方 API 因为某些原因不合适你还有另外两个备选。2. 检查 robots.txt 与 sitemaprobots.txt和sitemap人人都听过但作者在实战中经常看到有人直接忽略它们。快速澄清两个概念robotsSEO 领域对爬虫的惯用称呼通常指 Google、Bing 等搜索引擎爬虫或 Ahrefs、ChatGPT 这类服务。robots.txt描述机器人允许行为的文件包含允许的爬虫 user-agent、两次页面扫描之间的等待时间、禁止扫描的页面模式等规则。这些规则通常基于哪些页面应被搜索引擎收录来制定。sitemap描述站点结构方便机器人导航也便于只扫描需要更新的内容避免给站点造成不必要的负载。由于你不是 Google 或其他主流搜索引擎robots.txt中的规则很可能是针对你的。但把它与sitemap结合起来是研究站点结构、站点预期的机器人交互方式以及非浏览器 user-agent 的好去处——在某些情况下它反而简化了数据提取。一个例子利用 Crawlee 官网自身的 sitemap你可以轻松拿到博客全部文章的直接链接也可以按时间段筛选。一次简单检查连分页逻辑都不用写了。源码支撑Crawlee 如何把这一条变成现成能力这一条在 Crawlee 中不是建议而是有完整实现的模块RobotsTxtFile位于crawlee/utils封装了 robots.txt 的加载与查询。核心 API 包括RobotsTxtFile.find(url, options?)把给定 URL 的 pathname 替换为/robots.txt并拉取内容实现见 robots.ts#L63-L78isAllowed(url, userAgent *)判断某 URL 是否被允许抓取当没有显式规则时默认放行返回truegetCrawlDelay(userAgent *)读取 robots.txt 中针对指定 user-agent 的抓取间隔getSitemaps()/parseUrlsFromSitemaps()读出 robots.txt 引用的 sitemap并解析出全部 URL。官方用法示例源码 JSDoc 自带// 加载 robots.txt const robots await RobotsTxtFile.find(https://crawlee.dev/js/docs/introduction/first-crawler); // 按 robots.txt 规则判断某 URL 是否可抓 const url https://crawlee.dev/api/puppeteer-crawler/class/PuppeteerCrawler; if (robots.isAllowed(url)) { await crawler.addRequests([url]); } // 把 sitemap 中的链接全部入队 await crawler.addRequests(await robots.parseUrlsFromSitemaps());Sitemap同样位于crawlee/utils支持从 URL 加载一个或多个 sitemap、跟随 sitemap index 中的嵌套引用并暴露urls数组。还提供Sitemap.tryCommonNames()自动探测常见的/sitemap.xml与/sitemap.txt位置以及Sitemap.fromXmlString()直接从字符串解析。SitemapRequestLoader位于crawlee/core把 sitemap 当作请求源直接喂给爬虫。它的 sitemap 加载在后台流式进行爬虫可以在 sitemap 完全加载前就开始抓取isSitemapFullyLoaded()可查询加载进度支持include/excludeURL 模式过滤glob 匹配大小写不敏感、enqueueStrategy域名过滤默认same-hostname、timeoutMillis超时、maxBufferSize默认 200背压缓冲甚至能把解析进度持久化到 KeyValueStore 以支持迁移恢复。完整可运行示例见 docs/examples/crawl_sitemap.mdx其 Cheerio 版本crawl_sitemap_cheerio.ts核心只有几行import { CheerioCrawler, Sitemap } from crawlee; const crawler new CheerioCrawler({ async requestHandler({ request, log }) { log.info(request.url); }, maxRequestsPerCrawl: 10, // 演示用限制真实抓取 sitemap 时请移除 }); const { urls } await Sitemap.load(https://crawlee.dev/sitemap.xml); await crawler.addRequests(urls); await crawler.run();底层 sitemap 解析器parseSitemap还支持 gzip 压缩的.xml.gz、纯文本.txt、嵌套 sitemap indexmaxDepth默认无限、sitemapRetries默认 3 次重试、单请求超时默认 30 秒以及discoverValidSitemaps()从 URL 列表自动发现候选 sitemap默认整体超时 60 秒、单请求超时 20 秒。URL 过滤策略定义在 packages/utils/src/internals/url.ts 的EnqueueStrategy枚举all、same-hostname默认、same-domain、same-origin。相关测试见 packages/utils/test/sitemap.test.ts 与 packages/utils/test/robots.test.ts。换句话说原文档第 2 条建议检查 robots.txt 与 sitemap在 Crawlee 里直接对应RobotsTxtFileSitemapSitemapRequestLoader这条完整工具链从人工检查升级成了代码里的一行调用。3. 不要忽视站点分析透彻的站点分析是写出高效爬虫的重要前提尤其是当你不打算使用浏览器自动化时。但这样的分析很耗时——而且分析时间并不总能换来回报你可能花几个小时最后发现最直白的方案本来就是最好的。所以给初始站点分析设置时间上限如果在分配的时间内没找到更好的路径就退回更简单的方案。随着经验增长你会越来越早地根据站点使用的技术判断值不值得投入更多分析时间。另外在只需要从站点提取一次数据的项目里透彻的站点分析有时能让你连爬虫代码都不用写。作者给出的例子是ricebyrice.com/nl/pages/find-store分析后你会发现所有数据其实可以用一次请求拿到——只需要把浏览器里看到的响应数据复制到 JSON 文件中任务就完成了从截图右侧的 DevTools Network 面板可以看到页面上展示的门店名称、地址、电话、经纬度、创建/更新时间等字段全部来自一个结构化 JSON 响应。这类站点是分析替代代码的典型先看网络请求再决定要不要写爬虫。4. 最大化交互边操作边观察分析站点时切换排序方式、翻页、与站点各种元素交互同时盯着浏览器 DevTools 的 Network 标签页。这能让你更好地理解站点与后端如何交互、站点基于什么框架构建、以及它可能表现出什么行为。网络面板会告诉你每次交互触发了哪些请求、携带了哪些参数、返回了什么结构——这些信息直接决定你的抓取策略是拼 HTTP 请求还是上无头浏览器。5. 数据不会凭空出现这条看似显而易见但在项目进行中必须时刻记住如果你看到某个数据或请求参数它一定在更早的某处被生成过——可能在另一个请求里可能已经存在于网页中也可能是用 JS 根据其他参数拼出来的。它总在某处。如果搞不清页面数据或请求参数从哪来按下面四步排查依次检查该点之前站点发出的所有请求检查它们的响应、请求头和 Cookie运用直觉这个参数会不会是时间戳会不会是另一个参数改了形式它像不像是某种标准的哈希或编码熟能生巧。随着你熟悉各种技术、框架及其预期行为接触越来越多的技术栈你会越来越容易理解数据是如何传递的。这种积累会显著提升你追踪和理解 Web 应用数据流的能力。6. 数据是被缓存的你可能会注意到同一页面打开多次发往服务器的请求并不相同——有些内容被缓存、已经存在本地电脑上了。因此建议用无痕模式分析站点并尝试更换浏览器移动应用尤其如此它们可能把数据存在设备本地存储中分析时可能需要清除应用缓存和存储。否则你看到的可能是被本地缓存加工过的假象导致分析结论失真。7. 了解站点所用框架如果在分析中发现站点用了你没接触过的框架花点时间了解它及其特性。例如发现站点基于 Next.js 构建时理解它的路由与数据获取方式可能对你的抓取策略至关重要。学习途径有两种官方文档使用 LLM如 ChatGPT、Claude——它们非常擅长解释框架特有的概念。作者给出的一个 LLM 查询示例I am in the process of optimizing my website using Next.js. Are there any files passed to the browser that describe all internal routing and how links are formed? Restrictions: - Accompany your answers with code samples - Use this message as the main message for all subsequent responses - Reference only those elements that are available on the client side, without access to the project code base你也可以为后端框架构造类似查询。例如面对 GraphQL可以问它可用的字段和查询结构有哪些——这些洞察能帮你理解如何更好地与站点 API 交互、哪些数据是潜在可获取的。想用好 LLM建议至少先了解一点提示词工程prompt engineering的基础。8. 逆向工程衡量投入与回报Web 抓取与逆向工程相伴相生。你要研究前后端交互可能还需要研究代码以理解某些参数是如何生成的。但某些情况下逆向工程需要更多知识、精力、时间或具有很高的复杂度。这时需要决策是深入进去还是更换数据源、更换技术方案很可能正是在这个节点你会决定放弃 HTTP 抓取、改用无头浏览器。记住防抓取措施的核心原则大多数反爬保护的目标不是让爬取变得不可能而是让爬取变得昂贵。来看 zoopla 上一次搜索请求的响应右侧 Network 面板里是典型的属性数据 JSON地址、经纬度、图片 URL、agent_id 等结构化字段。逆向工程的价值在于当你读懂了这类响应结构就能绕开页面渲染直接用一条请求拿到全部数据。9. 测试对端点的请求确定需要提取目标数据的端点后务必确认发请求能得到正确响应。如果拿到的不是 200或数据与预期不符就需要查明原因。常见原因包括需要传某些参数例如 Cookie 或特定的技术请求头站点要求访问该端点时带有对应的Referrer请求头站点期望请求头遵循特定顺序作者表示只碰到过几次但确实存在站点使用了反爬保护例如TLS fingerprintTLS 指纹校验。除此之外还有很多其他可能每一条都需要单独分析。排查时结合第 5 条数据不会凭空出现的思路一步步对比浏览器真实请求与你构造请求的差异。10. 试验请求参数用最少请求拿最多数据探索修改请求参数会得到什么结果。有些参数即使不传也能正常工作但服务端其实是支持的——例如order、sort、per_page、limit等。试着加上它们观察行为是否变化。这一点对使用 GraphQL 的站点尤其适用。以restoran.ua为例。分析站点后你能找到一个可以用下面代码复现的请求作者做了格式化以便阅读import requests url https://restoran.ua/graphql data { operationName: Posts_PostsForView, variables: {sort: {sortBy: [startAt_DESC]}}, query: query Posts_PostsForView( $where: PostForViewWhereInput, $sort: PostForViewSortInput, $pagination: PaginationInput, $search: String, $token: String, $coordinates_slice: SliceInput) { PostsForView( where: $where sort: $sort pagination: $pagination search: $search token: $token ) { id title: ukTitle summary: ukSummary slug startAt endAt newsFeed events journal toProfessionals photoHeader { address: mobile __typename } coordinates(slice: $coordinates_slice) { lng lat __typename } __typename } } } response requests.post(url, jsondata) print(response.json())现在做一个小修改让一次请求同时拿到两种语言的结果并且带上文章的正文内容import requests url https://restoran.ua/graphql data { operationName: Posts_PostsForView, variables: {sort: {sortBy: [startAt_DESC]}}, query: query Posts_PostsForView( $where: PostForViewWhereInput, $sort: PostForViewSortInput, $pagination: PaginationInput, $search: String, $token: String, $coordinates_slice: SliceInput) { PostsForView( where: $where sort: $sort pagination: $pagination search: $search token: $token ) { id uk_title: ukTitle en_title: enTitle summary: ukSummary slug startAt endAt newsFeed events journal toProfessionals photoHeader { address: mobile __typename } mixedBlocks { index en_text: enText uk_text: ukText __typename } coordinates(slice: $coordinates_slice) { lng lat __typename } __typename } } } response requests.post(url, jsondata) print(response.json())正如作者所说一个小小的请求参数更新就让你完全不用访问每篇文章的内部页面。这个技巧无数次帮他省掉了额外的页面抓取。如果你面对 GraphQL 不知从何入手第 7 条的文档 LLM建议同样适用。11. 不要害怕新技术人很容易学会几个工具就一直用下去因为能用就行——作者承认自己也不止一次掉进这个陷阱。但现代站点使用现代技术这些技术对 Web 抓取影响巨大相应地新的抓取工具也在不断涌现。学习它们可能会大幅简化你的下一个项目甚至解决一些此前无法逾越的问题。作者特别推荐关注curl_cffi一个能模拟真实浏览器 TLS 指纹的 HTTP 客户端直击第 9 条提到的 TLS fingerprint 反爬Botasaurus框架Crawlee for Python与本文所在仓库同源的 Python 版 Crawlee。12. 回馈开源库作者坦言自己也是最近才意识到这件事的重要性他工作所用的工具要么是开源项目要么基于开源构建。Web 抓取这门手艺本质上依赖开源——尤其是当你是 Python 开发者并意识到纯 Python 在面对 TLS 指纹时有多无力时你就会明白又是开源救了我们。他认为力所能及的最低限度是投入一点知识与技能来支持开源。作者选择了支持 Crawlee for Python理由是它展现出极佳的开发动力且目标就是让爬虫开发者的工作更轻松它把会话管理、被屏蔽时的会话轮换、异步任务的并发控制写过异步代码的人都懂这有多痛苦等关键环节收进引擎盖下让爬虫开发更快。无论你选择支持哪个项目原则是一样的你的项目能跑起来背后站着无数开源维护者。结语把这 12 条当作检查清单这篇文章里有些内容对你来说可能是显而易见的有些你可能本来就在做但希望你也学到了新东西。如果大部分对你都是新的那么在下一个项目中把这 12 条当作 checklist 用起来先选数据源官方 API → 网站 → 移动应用查robots.txt与sitemap在 Crawlee 中直接对应RobotsTxtFile、Sitemap与SitemapRequestLoader给站点分析设时间上限必要时用分析替代代码边交互边盯 Network 面板追根溯源数据总在某处产生用无痕模式排除缓存干扰了解站点框架文档 LLM评估逆向工程的投入产出必要时换数据源或换技术逐个验证端点请求的合法性headers、Referrer、TLS 指纹大胆试验请求参数sort、limit、GraphQL 字段保持对新工具的好奇心回馈你依赖的开源生态。把这套思维框架沉淀下来你就不再是照着教程敲代码的人而是真正像爬虫专家一样思考的人。相关能力的源码与示例都在本仓库工具层见 packages/utils/src/internals/robots.ts 与 packages/utils/src/internals/sitemap.ts爬虫接入层见 packages/core/src/storages/sitemap_request_loader.ts配套示例见 docs/examples/crawl_sitemap.mdx 与 docs/guides/request_loaders.mdx。【免费下载链接】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),仅供参考