一个本地 MCP 服务,用来把公开网页提取成更干净的正文 Markdown,适合给 Codex、其他 MCP 客户端或 LLM 工作流直接调用。
- 支持
extract_url和extract_many - 优先抽取正文,尽量移除导航、侧栏、广告等噪音
- 输出结构化字段:
title、author、publishedAt、markdown、plainText、images、warnings - 默认先走原生
fetch + Readability + selector - 当页面疑似需要浏览器渲染、验证码/反爬拦截、或正文明显不完整时,自动回退到
Playwright - 批量提取支持有限并发,默认
3,避免单站点超时拖慢整批任务 - 对非 HTML 响应和 fallback 失败返回结构化错误信息,便于 MCP 客户端和 LLM 工作流做兜底处理
- 支持可选
debug诊断输出,便于定位 fallback、策略选择和截断行为 - 支持从
application/ld+json中提取文章元数据 - 内置轻量域名级策略,优先照顾高价值内容站点
- HTML 获取:原生
fetch - 正文提取:
Readability+ 选择器兜底 - Markdown 转换:
Turndown - 浏览器 fallback:
playwright-core - 错误结构化:
errorCode、errorStage、retryable - 调试诊断:
debug.fetch、debug.extraction、debug.fallback - 元数据增强:
meta+JSON-LD - 轻量站点策略:GitHub README / 微信公众号 / Medium / Substack 风格页
npm install如果本机没有 Playwright 自带浏览器,也可以直接复用本机 Chrome / Edge / Chromium。
可选环境变量:
PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/path/to/chrome-or-edge优先顺序:
PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATHCHROME_PATHEDGE_PATH- 系统默认常见路径
which/where命令探测
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge
/usr/bin/google-chrome/usr/bin/chromium/usr/bin/chromium-browser/usr/bin/microsoft-edge
C:\Program Files\Google\Chrome\Application\chrome.exeC:\Program Files (x86)\Google\Chrome\Application\chrome.exeC:\Program Files\Microsoft\Edge\Application\msedge.exeC:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
npm start在 config.toml 中加入:
[mcp_servers.web-extract]
command = "node"
args = ["/absolute/path/to/web-extract/server.js"]
startup_timeout_sec = 45输入:
url: 网页地址maxChars: 最大输出字符数,默认30000timeoutMs: 请求超时,默认25000playwrightFallback: 是否允许自动浏览器回退,默认truedebug: 是否返回结构化调试信息,默认false
返回字段:
urlfinalUrlstatustitleauthorpublishedAtsourceStrategymarkdownplainTextexcerptimagescontentLengthwarningsdebug(仅在debug=true时返回)
{
"fetch": {
"source": "fetch",
"status": 200,
"ok": true,
"finalUrl": "...",
"contentType": "text/html; charset=utf-8",
"bodyTextLength": 1234,
"durationMs": 120
},
"extraction": {
"domainProfile": "github-readme",
"readabilityAvailable": true,
"selectorAvailable": true,
"selectedStrategy": "selector:.markdown-body",
"sourceStrategy": "fetch:selector:.markdown-body",
"contentLength": 980,
"markdownLength": 1100,
"truncated": false,
"jsonLdMetaDetected": false,
"durationMs": 18
},
"fallback": {
"triggered": false,
"attempted": false,
"reason": null,
"durationMs": 0
}
}说明:
- 正常路径会返回
fetch:readability、fetch:selector:article之类的sourceStrategy - 如果触发浏览器回退,会返回
playwright:readability、playwright:selector:... - 若你只想使用纯
fetch路径,可在调用时传playwrightFallback=false - 如果响应不是 HTML(例如
application/json/application/pdf),会返回结构化错误而不是继续盲目提取 - 短页面不会因为“字少”就必然触发 fallback;当前会结合整页文本长度和 shell/placeholder 特征综合判断
批量提取多个 URL,逐条返回成功或失败结果。
输入:
urls: URL 列表,最多20maxChars: 最大输出字符数,默认30000timeoutMs: 请求超时,默认25000playwrightFallback: 是否允许自动浏览器回退,默认trueconcurrency: 批量提取并发数,默认3,最大8debug: 是否在成功项中返回调试诊断信息,默认false
成功项结构:
okurlresult
失败项结构:
okurlerrorerrorCodeerrorStageretryable
当前内置的错误码包括:
FETCH_ERRORNON_HTML_RESPONSEEXTRACTION_ERRORPLAYWRIGHT_UNAVAILABLEPLAYWRIGHT_FALLBACK_FAILED
当前内置的高价值站点优化:
- GitHub:优先
.markdown-body - 微信公众号:优先
#js_content/.rich_media_content - Medium 风格页:优先
article - Substack 风格页:优先
article/.available-content
这些策略不会替代通用提取,只是在命中对应站点时优先尝试更合适的正文区域。
npm run smoke
npm testnpm test使用本地 HTML fixture,结果稳定,适合 CInpm run smoke访问真实网页,用于人工冒烟验证- 当前本地 fixture 已覆盖:
- 标准文章页
- JSON-LD 元数据页
- 短但有效的页面
- GitHub README 风格页
- shell / placeholder 页
- 建议 smoke 时至少验证:
- 一个普通 HTML 页面
- 一个需要 fallback 的页面
- 一个非 HTML 页面
已验证通过:
- GitHub HTML 页面:命中
.markdown-body - GitHub API JSON:按
NON_HTML_RESPONSE拒绝 - 微信公众号文章:命中
#js_content - Substack 文章:正文提取 + JSON-LD 元数据有效
- PDF 文件:按
NON_HTML_RESPONSE拒绝
已验证 fallback 链路可用,但内容质量不一定理想:
- X
- Medium(测试 URL 为 404 页面)
- Bloomberg(更偏首页/播放器内容)
失败样本:
- NYTimes 某文章页:当前版本未稳定提取出有效正文
说明:当前 smoke 证明了“核心链路可用”,但不代表所有媒体站点都已做专项适配。后续若要提升命中率和正文质量,应继续扩展域名级策略和等待/过滤规则。
- 登录态页面、强交互页面、复杂验证码页面仍可能失败
playwright-core需要本机可用的 Chromium / Chrome / Edge 可执行文件- 部分站点作者、发布时间等元数据可能缺失,但正文仍优先抽取
- 当前批量提取是“有限并发”而不是站点级调度,不适合高强度大规模采集
- 域名级策略目前是轻量版本,不是完整站点适配器系统
- 增加更强的域名级策略与等待策略
- 增加更多元数据标准支持
- 增加 debug / verbose 日志输出到 CLI / MCP 日志流
- 引入更系统化的站点画像和 fallback 分类
- 发布到 npm 或独立 GitHub 仓库