字
字节笔记本
2026年2月16日
开源项目分享:Reader , 专为 LLM 设计的生产级网页抓取引擎
API中转
¥120
本文介绍 Reader,一个专为 LLM 和 AI Agent 设计的开源生产级网页抓取引擎,支持 Cloudflare 绕过、智能内容提取和批量抓取。
项目简介
Reader 是一款基于 TypeScript 开发的开源网页抓取引擎,由 vakra-dev 团队开发维护。截至目前,该项目在 GitHub 上已获得 320 stars,采用 Apache 2.0 开源协议。
该工具解决了构建需要网络访问的 AI Agent 时的痛点。传统的 Puppeteer + 反检测插件方案在面对 Cloudflare、TLS 指纹检测、代理管理等生产级挑战时往往力不从心。Reader 基于 Ulixee Hero 构建,提供了开箱即用的企业级抓取能力。
核心特性
反检测能力
- Cloudflare 绕过:TLS 指纹模拟、DNS over TLS、WebRTC IP 掩码
- 多信号检测:通过 DOM 元素和文本模式检测挑战
- 动态等待:自动轮询挑战解决状态
内容提取
- 智能清理:自动移除导航、页眉、页脚、弹窗、Cookie 横幅
- 主内容提取:自动识别并提取页面主要内容
- 多格式输出:支持 Markdown、HTML、JSON、Text
企业级功能
- 浏览器池:自动回收、健康监控、队列管理
- 并发抓取:并行 URL 处理与进度跟踪
- 代理支持:数据中心和住宅代理,支持粘性会话和轮询
- 网站爬取:BFS 链接发现,支持深度和页面限制
技术栈
- TypeScript - 主要开发语言
- Ulixee Hero - 高级无头浏览器(反检测核心)
- supermarkdown - Rust 编写的 HTML 转 Markdown 引擎
- Node.js - 运行时环境(>= 18)
安装指南
前置要求
- Node.js >= 18
- Linux 服务器需安装 Chrome 系统依赖(见下文)
安装
bash
npm install @vakra-dev/readerLinux 服务器依赖
在 headless Linux 服务器(VPS、EC2 等)上需要安装 Chrome 的系统依赖:
bash
# Debian/Ubuntu
sudo apt-get install -y libnspr4 libnss3 libatk1.0-0 libatk-bridge2.0-0 \
libcups2 libxcb1 libatspi2.0-0 libx11-6 libxcomposite1 libxdamage1 \
libxext6 libxfixes3 libxrandr2 libgbm1 libcairo2 libpango-1.0-0 libasound2快速开始
基础抓取
typescript
import { ReaderClient } from "@vakra-dev/reader";
const reader = new ReaderClient();
const result = await reader.scrape({
urls: ["https://example.com"],
formats: ["markdown", "html"],
});
console.log(result.data[0].markdown);
await reader.close();批量并发抓取
typescript
const result = await reader.scrape({
urls: ["https://example.com", "https://example.org"],
formats: ["markdown"],
batchConcurrency: 3,
onProgress: (progress) => {
console.log(`${progress.completed}/${progress.total}: ${progress.currentUrl}`);
},
});网站爬取
typescript
const result = await reader.crawl({
url: "https://example.com",
depth: 2,
maxPages: 20,
scrape: true,
});
console.log(`发现 ${result.urls.length} 个页面`);使用代理
typescript
const result = await reader.scrape({
urls: ["https://example.com"],
formats: ["markdown"],
proxy: {
type: "residential",
host: "proxy.example.com",
port: 8080,
username: "username",
password: "password",
country: "us",
},
});CLI 使用
守护进程模式
bash
# 启动守护进程
npx reader start --pool-size 5
# 后续命令自动连接守护进程
npx reader scrape https://example.com
npx reader crawl https://example.com -d 2
# 查看状态
npx reader status
# 停止守护进程
npx reader stop抓取命令
bash
# 抓取单个 URL
npx reader scrape https://example.com
# 多格式输出
npx reader scrape https://example.com -f markdown,html
# 并发抓取多个 URL
npx reader scrape https://example.com https://example.org -c 2
# 保存到文件
npx reader scrape https://example.com -o output.md爬取命令
bash
# 基础爬取
npx reader crawl https://example.com
# 深度爬取并抓取内容
npx reader crawl https://example.com -d 3 -m 50 --scrape
# URL 过滤
npx reader crawl https://example.com --include "blog/*" --exclude "admin/*"高级用法
浏览器池配置
typescript
const reader = new ReaderClient({
browserPool: {
size: 5, // 5 个浏览器实例
retireAfterPages: 50, // 50 页后回收
retireAfterMinutes: 15, // 15 分钟后回收
},
verbose: true,
});代理轮询
typescript
const reader = new ReaderClient({
proxies: [
{ host: "proxy1.example.com", port: 8080, username: "user", password: "pass" },
{ host: "proxy2.example.com", port: 8080, username: "user", password: "pass" },
],
proxyRotation: "round-robin", // 或 "random"
});生产环境部署
typescript
import HeroCore from "@ulixee/hero-core";
import { TransportBridge } from "@ulixee/net";
import { ConnectionToHeroCore } from "@ulixee/hero";
import { scrape } from "@vakra-dev/reader";
// 启动时初始化一次
const heroCore = new HeroCore();
await heroCore.start();
// 每个请求创建连接
function createConnection() {
const bridge = new TransportBridge();
heroCore.addConnection(bridge.transportToClient);
return new ConnectionToHeroCore(bridge.transportToCore);
}
// 在请求中使用
const result = await scrape({
urls: ["https://example.com"],
connectionToCore: createConnection(),
});工作原理
Cloudflare 绕过机制
- TLS 指纹模拟:模拟真实 Chrome 浏览器指纹
- DNS over TLS:使用 Cloudflare DNS (1.1.1.1) 模拟 Chrome 行为
- WebRTC IP 掩码:防止 IP 泄露
- 多信号检测:通过 DOM 元素和文本模式检测挑战
- 动态等待:轮询挑战解决状态,检测 URL 重定向
浏览器池
- 自动回收:100 次请求或 30 分钟后自动回收浏览器
- 健康监控:每 5 分钟后台健康检查
- 请求队列:池满时排队请求(最大 100)
HTML 转 Markdown
Reader 使用 supermarkdown 进行转换,这是一个用 Rust 从头编写的专用引擎:
- Rust 编写:通过 napi-rs 提供 Node.js 绑定,原生性能
- 完整 GFM 支持:表格、任务列表、删除线、自动链接
- LLM 优化:专为 AI 消费设计的干净输出
- 实战测试:处理真实网页的畸形 HTML
- CSS 选择器:转换时可包含/排除元素
API 参考
ReaderClient 配置
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
verbose | boolean | false | 启用详细日志 |
showChrome | boolean | false | 显示浏览器窗口 |
browserPool | BrowserPoolConfig | - | 浏览器池配置 |
proxies | ProxyConfig[] | - | 代理数组 |
proxyRotation | string | "round-robin" | 轮询策略 |
scrape 方法
| 选项 | 类型 | 必需 | 默认值 | 说明 |
|---|---|---|---|---|
urls | string[] | 是 | - | URL 数组 |
formats | Array<"markdown" | "html"> | 否 | ["markdown"] | 输出格式 |
onlyMainContent | boolean | 否 | true | 仅提取主内容 |
batchConcurrency | number | 否 | 1 | 并发数 |
proxy | ProxyConfig | 否 | - | 代理配置 |
注意事项
- 生产环境建议使用共享 Hero Core 避免重复启动 Chrome
- Linux 服务器必须安装 Chrome 系统依赖
- 浏览器池大小根据服务器资源合理配置
- 代理配置支持数据中心和住宅代理
项目链接
- GitHub 仓库:https://github.com/vakra-dev/reader
- 官方文档:https://docs.reader.dev
- NPM 包:https://www.npmjs.com/package/@vakra-dev/reader
- Discord 社区:https://discord.gg/6tjkq7J5WV
- supermarkdown:https://github.com/vakra-dev/supermarkdown
分享: