快速回答
如何在 Node.js 中将网页转换为 Markdown?
使用 Node.js 18+ 内置的 fetch:在 Authorization header 中带上你的密钥调用 https://webreaderapi.com/api/v1/read?url=…,并从 JSON 响应中读取 markdown。WebReaderAPI 返回页面的正文,以及标题、作者和日期。单个页面消耗 1 积分,使用浏览器则消耗 2 积分,价格自 2026 年 10 月起为 US$0.07/千页。无需 KYC;加密货币支付。
我需要什么?
Node.js 18 或更高版本,以使用全局 fetch,并在 WEBREADER_API_KEY 环境变量中设置 API 密钥。示例为 ES modules:保存时使用 .mjs 扩展名,或在 package.json 中设置 "type": "module",这样顶层的 await 才能正常工作。
JSDoc 注释描述了响应结构,因此 VS Code 等编辑器无需 TypeScript 构建步骤就能提供补全。
/**
* @typedef {Object} Page
* @property {string} url
* @property {string} final_url
* @property {number} status_code
* @property {boolean} rendered
* @property {number} credits_used
* @property {string} [title]
* @property {string} [author]
* @property {string} [published_at]
* @property {string} [language]
* @property {string} [markdown]
* @property {number} word_count
*/
/** @returns {Promise<Page>} */
export async function readPage(url, options = {}) {
const params = new URLSearchParams({ url, ...options });
const res = await fetch(`https://webreaderapi.com/api/v1/read?${params}`, {
headers: { Authorization: `Bearer ${process.env.WEBREADER_API_KEY}` },
signal: AbortSignal.timeout(75_000),
});
const body = await res.json();
if (!res.ok) throw Object.assign(new Error(body.error.message), { code: body.error.code });
return body;
}
const page = await readPage('https://example.com/docs/getting-started', { max_chars: '20000' });
console.log(page.title, page.word_count, 'words,', page.credits_used, 'credit(s)');
如何读取 URL 列表而不触及限制?
运行固定数量的 worker,从共享队列中取出 URL。这比对整个列表使用 Promise.all 更简单,后者会同时发起所有请求并触及 429 concurrency_limit。每个账户都有同时读取页面数的上限;你的控制台会显示该上限,支持团队可将其提高。
下面的并发池会把错误与结果放在一起,因此一个被拒绝的页面不会中断整个运行。诸如 blocked_by_robots 这类拒绝是最终且免费的;记录下来然后继续。
import { readPage } from './read.mjs';
export async function readAll(urls, workers = 8) {
const queue = [...urls];
const results = [];
async function worker() {
while (queue.length) {
const url = queue.shift();
try {
const page = await readPage(url, { max_chars: '50000' });
results.push({ url, page });
} catch (err) {
results.push({ url, error: err.code ?? err.name });
}
}
}
await Promise.all(Array.from({ length: workers }, worker));
return results;
}
const urls = Array.from({ length: 30 }, (_, i) => `https://example.com/blog/post-${i + 1}`);
for (const r of await readAll(urls)) console.log(r.url, '->', r.error ?? r.page.title);
如何在 Node.js 中跟踪 crawl 任务?
用 POST https://webreaderapi.com/api/v1/crawl 启动任务,然后在循环中读取 https://webreaderapi.com/api/v1/jobs/{job_id}。每当 next_cursor 返回时传入 cursor;当没有 cursor 且状态为 done 时,任务已完成。在空轮询之间等待,并将等待时间翻倍直至 30 秒,因为尊重网站 Crawl-delay 的 crawl 可能很慢。
batch 与 crawl 页面 描述了 crawl 如何选择页面,以及 limit 如何限制其读取内容。
const headers = {
Authorization: `Bearer ${process.env.WEBREADER_API_KEY}`,
'Content-Type': 'application/json',
};
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const start = await fetch('https://webreaderapi.com/api/v1/crawl', {
method: 'POST',
headers,
body: JSON.stringify({ url: 'https://docs.example.com/', limit: 300, include_paths: ['/docs/*'] }),
});
const { job_id } = await start.json();
const pages = [];
let cursor = '';
let wait = 2000;
for (;;) {
const url = `https://webreaderapi.com/api/v1/jobs/${job_id}${cursor ? `?cursor=${encodeURIComponent(cursor)}` : ''}`;
const job = await (await fetch(url, { headers })).json();
pages.push(...job.results.filter((r) => !r.error));
if (job.next_cursor) {
cursor = job.next_cursor;
wait = 2000;
continue;
}
if (job.status === 'done') break;
await sleep(wait);
wait = Math.min(wait * 2, 30000);
}
console.log(pages.length, 'pages read, job', job_id);
如何将结果传给模型?
发送 Markdown,而不是整个 JSON。模型应读取的是 markdown 字段;元数据最好留作引用。在其前面加上标题和 final_url,以便模型能标明来源,并将 max_chars 保持在模型上下文能容纳的大小,例如每页 20,000 个字符。
OpenAI function-calling 页面 演示了 Python 中的完整工具循环;上面的同一个 readPage 函数可以作为 Node.js agent 中的工具主体。
Node.js:常见问题
这在 Deno、Bun 或浏览器中能用吗?
Deno 和 Bun 支持相同的 fetch 和 ES modules。不要从浏览器页面调用 API:密钥会暴露给每个访客。请从你的服务器调用。
有 npm 包吗?
没有。本页面的函数就是完整的集成。WebReaderAPI 就是普通的 HTTPS 和 JSON,因此你可以掌控重试、超时和日志记录。
如何处理 429 concurrency_limit?
减少 worker 数量,或短暂等待后重试,且每次将等待时间翻倍。429 不消耗任何费用,错误页面 提供了现成的退避函数。
读取 10,000 个页面需要多少费用?
普通页面约 10,000 积分,若部分页面需要浏览器则更多。10,000 个网页 花费 US$3.75;预付费积分永不过期:未使用的页面数会一直保留在你的账户中,直到你使用。