reader
为AI代理打造的生产级网页抓取工具,一行代码将任意URL转为干净Markdown
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
为AI代理打造的生产级网页抓取工具,一行代码将任意URL转为干净Markdown
加载项目详情…
本应用为开源项目,仅供学习研究,请遵守其开源协议。
你有没有遇到过这样的情况:训练了一个看起来很聪明的 AI 代理,兴冲冲地接入网络想让它帮你查资料,结果刚一访问目标网站就被 Cloudflare 拦截,代理直接"装死"。这并不是 AI 不够聪明,而是生产级网页抓取本身就是一个极其复杂的工程问题——它远远不只是"发送请求、拿到 HTML、转成文字"这么简单。
Reader(vakra-dev/reader)正是为解决这个痛点而生的开源项目。它是一个构建在 Ulixee Hero 无头浏览器之上的生产级网页抓取引擎,目标用户是那些需要让 AI 代理真正"上网"工作的开发者。
Reader 由独立开发者 Nihal(GitHub: vakra-dev)开发和维护,项目采用 Apache-2.0 许可证,属于完全开源的项目。从 GitHub 仓库的信息来看,Nihal 同时还维护着 supermarkdown(高性能 HTML 到 Markdown 转换库)和一个键盘驱动的 JSON 浏览器,属于专注于开发者工具的工程师。
这个项目的诞生背景非常清晰:作者在构建需要访问网络的 AI 代理时,亲身体验了拼凑 Puppeteer、配置反爬插件、对抗 Cloudflare、管理代理 IP 的痛苦。他在 README 中直言不讳地写道:"Building agents that need web access is frustrating."——这种真实痛点驱动了 Reader 的诞生。
Reader 的设计哲学是"三层原语"——用三个核心 API 覆盖从简单到复杂的各类网页访问需求:
这是 Reader 最核心的功能。对于大多数 AI 用例,你只需要一个干净的 Markdown 输出:
import { ReaderClient } from "@vakra-dev/reader";
import { chromium } from 'playwright-core';
const reader = new ReaderClient();
const result = await reader.scrape({ urls: ["https://news.ycombinator.com"] });
console.log(result.data[0].markdown); // 干净的 Markdown 内容
这背后的处理流程远比表面看起来复杂:
src/config/domain-profiles.ts),根据目标网站的特征应用不同的抓取策略src/formatters/postprocess.ts):提取内容后进行清洗、去噪、结构化,最终输出 LLM 友好的 Markdown当需要系统性地抓取一个网站的多层页面时,crawl() API 提供了完整的解决方案:
const pages = await reader.crawl({
url: "https://example.com",
depth: 2, // 爬取深度
maxPages: 50, // 最多50页
scrape: true, // 同时抓取内容
delayMs: 1000, // 页面间延迟(礼貌爬取)
});
console.log(`发现 ${pages.urls.length} 个页面`);
爬虫实现了 BFS(广度优先)遍历,内置链接去重、同域名判断、内容链接过滤等机制,配合速率限制避免对目标站点的压力。
当内置的抓取功能不够用时,Reader 还提供了直接启动一个隐身 Chrome 的能力,你可以通过 Playwright 或 Puppeteer 全权控制浏览器:
const session = await reader.browser();
const browser = await chromium.connectOverCDP(session.wsEndpoint);
const page = (await browser.newContext()).newPage();
await page.goto('https://example.com');
// 完全自定义的浏览器操作...
await session.close();
这个功能的关键在于:Reader 启动的 Chrome 是经过 TLS 指纹伪装 和 UA 随机化 的,比原生 Puppeteer 启动的 Chrome 更难被检测。
Reader 的技术选型非常精准:
| 层级 | 技术选型 | 作用 |
|---|---|---|
| 核心引擎 | Ulixee Hero / HeroCore | 无头浏览器,CDP 协议,TLS 指纹 |
| 编程语言 | TypeScript + Node.js(>=18) | 类型安全,npm 生态 |
| 构建工具 | tsup | 快速的 TypeScript 打包 |
| 浏览器 | @ulixee/chrome-139-0(内嵌 Chrome 139) | 开箱即用,无需预装 Chrome |
| 日志 | pino + pino-pretty | 结构化高性能日志 |
| HTML转Markdown | @vakra-dev/supermarkdown | Rust 编写的高性能转换器 |
| DOM 解析 | linkedom | 轻量级 DOM 实现 |
| 并发控制 | p-limit | 批量请求并发管理 |
| HTTP 客户端 | undici | Node.js 内置高性能 HTTP |
src/
├── client.ts # ReaderClient 主入口,管理 HeroCore 生命周期
├── scraper.ts # 抓取核心,含代理升级策略和 Markdown 转换
├── crawler.ts # 爬虫引擎,BFS 遍历 + robots.txt + 速率限制
├── browser-session.ts # 启动独立 Chrome 会话,返回 CDP WebSocket
├── errors.ts # 自定义错误体系(DNSError, RobotsBlockedError 等)
├── formatters/
│ ├── markdown.ts # Supermarkdown HTML 到 Markdown 转换
│ └── postprocess.ts # Markdown 后处理(清洗、去噪)
├── utils/
│ ├── robots-parser.ts # Robots.txt 解析与合规检查
│ ├── content-cleaner.ts # 内容清洗(广告、导航、脚本剔除)
│ ├── metadata-extractor.ts # 元数据提取(标题、描述、OG标签)
│ ├── block-detector.ts # 反爬检测
│ ├── rate-limiter.ts # 速率限制
│ └── url-helpers.ts # URL 解析、规范化、同域名判断
├── config/
│ └── domain-profiles.ts # 域名特殊处理规则
├── browser/
│ ├── tiered-pool.ts # 浏览器进程池,按能力分层
│ └── proxy-bound-browser.ts # 代理绑定浏览器实例
├── proxy/
│ ├── proxy-gate.ts # 代理网关
│ └── health-tracker.ts # 代理健康状态追踪
├── cloudflare/
│ └── bypass.ts # Cloudflare 挑战绕过
└── cli/ # CLI 工具实现
Reader 的代理系统是其技术亮点之一。它实现了分层代理池(Tiered Proxy Pool):
同时,ProxyHealthTracker 持续监控各代理的响应时间和成功率,自动下线不健康代理。整个代理系统通过 ProxyGate 统一封装,对上层代码透明。
在 browser-session.ts 中,每个浏览器会话都是一个独立进程:
localhost:PORT(无认证)close() 即 kill 进程,无残留这种设计比长期维护一个浏览器池更轻量,适合需要动态创建和销毁会话的场景。
npm install -g @vakra-dev/reader
# 或
npx @vakra-dev/reader scrape https://example.com
Reader 内置了完整的命令行界面:
# 抓取单个 URL
reader scrape https://example.com
# 启动守护进程(保持浏览器池热启动)
reader start --port 6003
# 获取浏览器会话
reader browser
对于生产环境,Reader 推荐以 daemon 模式 运行:一次性启动浏览器池,所有后续请求复用这个预热的池,避免每次请求都重新启动 Chrome 的开销。
Reader 的定位介于以下几类产品之间:
| 项目 | 类型 | 特点 |
|---|---|---|
| Firecrawl | 云服务 + 开源 | 专注整站爬取,可托管服务 |
| Jina AI Reader | 纯 API 服务 | 只需一个 URL,无代码接入,但不可自托管 |
| Scrapegraph-ai | 本地库 | 使用 LLM 生成抓取脚本,灵活但不稳定 |
| Reader | 本地库 | 基于真实浏览器,最接近生产环境,有代理轮换 |
Reader 的差异化在于:它基于真实的 Chrome 浏览器实例(不是纯 HTTP 请求),加上 TLS 指纹伪装和代理轮换,使得它能处理大多数反爬机制严格的网站,同时完全可本地部署。
在 AI 时代,数据是模型的命脉。RAG 系统需要高质量的外部知识,AI 代理需要实时获取最新信息,这一切都离不开可靠的网页数据采集能力。Reader 填补了一个关键空白:让 AI 开发者不需要成为反爬专家,也能获取生产级的网页数据。
从开源生态角度看,Reader 与 Ulixee 的深度整合代表了无头浏览器在 AI 应用场景中的成熟化。2024 年 Star History 的月度报告已将其与 Jina AI、Firecrawl 等并列,作为 AI Web Scraping 领域的代表性开源工具。
未来,随着 AI 代理的普及,对可靠、自动化网页访问工具的需求只会增长。Reader 的模块化设计——从简单抓取到完整浏览器控制——使其能够适应从简单脚本到复杂生产系统的各种场景,有望成为 AI 数据采集层的重要基础设施。
项目信息