@trendtech33566: 【已保存版本】 给想将 URL 或 PDF 转换为干净 Markdown 的人,PullMD,约 400。以下是它能做的・C…
摘要
PullMD 是一个开源、可自托管的服务,可将网页、PDF、Office 文档、EPUB、图片、音频和 YouTube 视频转换为干净的 Markdown,并提供 REST API、MCP 服务器和 PWA 前端。
查看缓存全文
缓存时间: 2026/08/05 12:23
【已保存版本】 对于那些想把 URL 或 PDF 转换为整洁 Markdown 的人,PullMD,约 400。它能做到的事情: ・将网页转换为 Markdown,无广告或装饰 ・支持 PDF/Office/EPUB/图片/音频/YouTube 等 ・包含 REST API / MCP 服务器 / PWA ・可自托管,且易于与 AI 智能体集成 一个能瞬间处理“将信息标准化为 Markdown”的开源项目。它会引起那些构建 RAG 预处理或 AI 工作流的人的共鸣。
AeternaLabsHQ/pullmd
源码:https://github.com/AeternaLabsHQ/pullmd
PullMD 发布(https://github.com/AeternaLabsHQ/pullmd/releases) Docker 拉取(https://hub.docker.com/r/aeternalabshq/pullmd) CI(https://github.com/AeternaLabsHQ/pullmd/actions/workflows/docker.yml) 许可证(https://github.com/AeternaLabsHQ/pullmd/blob/main/LICENSE) MCP(https://github.com/AeternaLabsHQ/pullmd#mcp-server) 自托管的 URL 转 Markdown 服务,面向人类和 AI 智能体。
PullMD 接受任意网页 URL,返回干净、可读的 Markdown——没有导航、没有广告、没有样板内容。它能自动识别 Reddit 和 Hacker News 帖子(包含完整评论树),在可用时使用 Cloudflare 原生 Markdown,对静态 HTML 运行 Mozilla Readability + Trafilatura,最后的手段是通过无头 Chromium(Playwright 辅助容器)渲染 JavaScript 重页面后再提取。
从 v3 开始,PullMD 不再局限于网页:它还能将文档(PDF、Office、EPUB)、图片、音频和 YouTube 视频转换为 Markdown,并默认输出更精简、更省 token 的正文。参见下文 v3 新特性。
它以以下形式提供:
- 一个 PWA 前端,带有原始/渲染视图和实时 frontmatter 视图切换、一键分享输出到其他应用(Web Share API)、一个按服务器建议文件名保存结果为
.md文件的下载按钮、深色/纸张主题、历史记录、归档、分享链接,以及本地 HTML 文件的转换(桌面端拖放、桌面端和移动端文件选择器) - 一个 REST API,位于
GET /api?url=... - 一个 MCP 服务器,位于
POST /mcp(Streamable-HTTP 传输,无状态) - 一个 Claude Code 技能,可下载 zip 包
每次转换都会获得一个 8 位十六进制 分享 ID,它可以作为一个稳定的实时端点:GET /s/:id 返回缓存的 markdown,并在超过一小时未更新时从源站重新获取。将分享 ID 用作固定 URL,始终返回新鲜内容——对 subreddit 订阅源等场景很有用。
v3 新特性
PullMD v3 从一个网页阅读器成长为一个通用的 任何内容转 Markdown 服务,面向智能体,并采用更精简的默认输出。超出纯网页提取的一切都是 可选启用并且优雅降级 的——未配置时,v3 对网页的处理与 v2 完全一致,只是在默认情况下正文更干净。
- 默认使用干净正文 - Markdown 正文现在只有
# 标题+ 内容。来源 URL、抓取日期和所有元数据都移入 YAML frontmatter,因此不会重复,也为你节省 token。Reddit 帖子的规则相同:subreddit、作者、点赞数和发布日期位于 frontmatter(subreddit,author,upvotes,published)中,而非正文。这是唯一一个破坏性变更:设置PULLMD_SOURCE_HEADER=true可恢复旧的内联头部,并使用PULLMD_FRONTMATTER_FIELDS来裁剪输出的字段。参见MIGRATION.md。 - 文档 → Markdown - 支持 PDF、Word、PowerPoint、Excel、EPUB 等,通过 URL 或上传(
POST /api/file,PWA 中可拖放)。 - 高质量 PDF 表格(OCR) - 一个可选的、与供应商无关的 OCR 层(
?pdf=ocr),用于表格级 PDF 转换,自动回退到免费路径。 - 图片和音频 → Markdown - 通过任何兼容 OpenAI 的或本地模型,可选启用字幕生成与转写;在 pullmd 内部运行,无需额外容器。
- YouTube 转录 - 标题、描述和转录,带可点击时间码,无需 API 密钥。
- 更丰富的 frontmatter - 提取来源、质量,以及(对于媒体/OCR)模型 + token/页数使用量,用于成本追踪,另加一个可配置的字段白名单。
从 v2.x 升级的自托管用户:干净正文变更是唯一的破坏性变更 -
MIGRATION.md提供了一行关闭配置。其他一切都是新增功能。
自 3.x 版本以来新增的内容:
- Hacker News 管道(3.1)- 通过专门构建的转换器处理条目、评论永久链接和列表,并在 PWA 中提供 Web Share 和即时 frontmatter 切换。
X-Transcript-Status(3.2)- 区分瞬时 YouTube 速率限制与真正的转录缺失。- SSRF 防护(3.3)- 默认拒绝私有、回环、链路本地、CGNAT 和云元数据目标,覆盖每个抓取路径和每个重定向跳转。
- 查询范围提取(3.4)-
?query=仅返回与问题相关的章节,并带有max_tokens预算。 - 开放站点配方(3.5/3.6)- JSON-LD 转换为 frontmatter、贡献者指南,以及
select.content,让配方可以直接指定文章正文。 - 覆盖率保护(3.7)- 当提取仅保留正文的一小部分时恢复页面;参见
PULLMD_COVERAGE_GUARD。 - 账户控制(3.8)- 非管理员可以从自己的历史记录中清除条目,可以通过
PULLMD_ALLOW_SIGNUP关闭自助注册,scripts/admin.js create-user可从 shell 创建账户。 - 下载按钮(3.9)- PWA 将结果保存为
.md文件,文件名由服务器通过X-Suggested-Filename指定,并可选择添加日期前缀。
快速开始
预构建的多架构镜像(linux/amd64, linux/arm64)位于 Docker Hub 上。将 compose 文件放到某个位置并运行:
``bash mkdir pullmd && cd pullmd curl -O https://raw.githubusercontent.com/AeternaLabsHQ/pullmd/main/docker-compose.yml docker compose up -d
→ http://localhost:3000
``
就这么简单。不需要 .env:每个变量都有合理的默认值,PullMD 在 3000 端口监听。在 compose 文件旁边添加 .env 可覆盖任何设置(参见 配置)。
docker-compose.yml(零配置,节选)
``yaml services: pullmd: image: aeternalabshq/pullmd:latest container_name: pullmd restart: unless-stopped ports: - “{PORT:-3000}:3000" environment: - PUBLIC_URL={PUBLIC_URL:-http://localhost:${PORT:-3000}} - TRAFILATURA_URL=http://trafilatura:8001/extract - PLAYWRIGHT_URL=http://playwright:8002/render - MARKITDOWN_URL=http://markitdown:8003/convert - CACHE_DB=/data/cache.db volumes: - ./data:/data networks: - pullmd-internal depends_on: - trafilatura - playwright - markitdown
trafilatura: image: aeternalabshq/pullmd-trafilatura:latest container_name: pullmd-trafilatura restart: unless-stopped networks: - pullmd-internal
playwright: image: aeternalabshq/pullmd-playwright:latest container_name: pullmd-playwright restart: unless-stopped networks: - pullmd-internal
markitdown: image: aeternalabshq/pullmd-markitdown:latest container_name: pullmd-markitdown restart: unless-stopped mem_limit: ${MARKITDOWN_MEM_LIMIT:-1g} networks: - pullmd-internal
networks: pullmd-internal: driver: bridge ``
为可读性而节选 — 仓库中的
docker-compose.yml会将每个可选的.env变量透传给容器(Reddit 凭据、认证、媒体/OCR 密钥、YouTube 选项、输出整形)。请使用上面的curl -O命令,而不是复制此代码块,否则超出基础项的.env覆盖不会到达容器。
注意: Playwright 辅助容器会给你的镜像缓存增加 约 3.7 GB(Chromium + Firefox + WebKit 二进制文件来自官方 Playwright 基础镜像)。它是可选的——不设置
PLAYWRIGHT_URL并移除playwright服务块,PullMD 会静默降级为静态提取,并在元数据中添加一条降级说明。
注意: MarkItDown 辅助容器是可选的。不设置
MARKITDOWN_URL并移除markitdown服务块即可禁用文档转换。网页 URL 始终可以在没有它的情况下工作。
GHCR 镜像:
ghcr.io/aeternalabshq/{pullmd,pullmd-trafilatura,pullmd-playwright,pullmd-markitdown}。如果你更喜欢 GitHub 的镜像仓库,可以替换image:行。
在 Traefik 后面
对于使用 TLS 的 Traefik 部署,请改用 docker-compose.traefik.yml。镜像相同,但带有 Traefik 标签和 proxy 外部网络。在 .env 中设置 HOST_DOMAIN:
bash curl -O https://raw.githubusercontent.com/AeternaLabsHQ/pullmd/main/docker-compose.traefik.yml echo "HOST_DOMAIN=pullmd.example.com" > .env docker compose -f docker-compose.traefik.yml up -d
本地开发(无需 Docker)
``bash git clone https://github.com/AeternaLabsHQ/pullmd.git cd pullmd npm install npm start
http://localhost:3000
npm test
node –test
``
配置
所有变量都放在 .env 中(从 .env.example 复制):
v3.0.0 输出格式变更: markdown 正文默认是干净的——只有
# 标题后跟内容。来源 URL、抓取日期和所有提取元数据仍保留在 YAML frontmatter 中,与之前一样——正文不再重复它们。设置PULLMD_SOURCE_HEADER=true可恢复旧的内联头部。使用PULLMD_FRONTMATTER_FIELDS来选择输出哪些 frontmatter 字段(在智能体管道中节省 token 非常方便)。
| 变量 | 是否必须 | 用途 |
|---|---|---|
HOST_DOMAIN | 仅 Traefik 变体 | 不带协议的公网主机名。供 Traefik 路由使用,并作为 PUBLIC_URL 的回退值。默认 compose 不使用。 |
PUBLIC_URL | 否 | 嵌入 /help 和技能 zip 中的完整公网源地址。默认为 https://${HOST_DOMAIN}。 |
TRAFILATURA_URL | 否 | Trafilatura 辅助容器 /extract 端点的 URL。未设置 → 跳过 Trafilatura,仅使用 Readability。 |
PLAYWRIGHT_URL | 否 | Playwright 辅助容器 /render 端点的 URL。未设置 → 跳过对 JS 页面的 Playwright 回退。 |
MARKITDOWN_URL | 否 | MarkItDown 辅助容器 /convert 端点的 URL。未设置 → 禁用文档转换路径;POST /api/file 返回 502。 |
PULLMD_VISION_API_KEY / ..._BASE_URL / ..._MODEL | 否 | 通过兼容 OpenAI 的视觉端点进行图像字幕生成。设置密钥即启用。_MODEL 默认为 gpt-4o-mini。 |
PULLMD_STT_API_KEY / ..._BASE_URL / ..._MODEL | 否 | 通过兼容 OpenAI 的 /audio/transcriptions 端点进行音频转写。设置密钥即启用。_MODEL 默认为 whisper-1。 |
PULLMD_LLM_API_KEY / ..._BASE_URL | 否 | 当各模态变量未设置时,作为视觉 + 语音转写共享的回退凭据。只有密钥和基础 URL——没有 PULLMD_LLM_MODEL,设置了也会被忽略(服务器启动时会给出警告)。 |
PULLMD_PDF_OCR_API_KEY / ..._BASE_URL / ..._MODEL | 否 | 通过保留表格的 OCR 提供商实现可选的高质量 PDF→Markdown(参考:Mistral OCR mistral-ocr-latest)。通过请求参数 ?pdf=ocr 或配方 fetch.pdf: ocr 触发。默认 PDF 处理仍使用免费的 markitdown 路径。_MODEL 默认为 mistral-ocr-latest。 |
MARKITDOWN_YOUTUBE | 否 | 设置为 true 可将 YouTube URL 路由到 markitdown 辅助容器(返回标题 + 描述 + 转录)。无需 API 密钥。默认关闭。 |
MARKITDOWN_YT_TIMECODES | 否(辅助容器) | 转录中的默认时间码格式:links(YouTube 时间戳链接,默认)、plain(纯 [MM:SS] 标签)、none(仅转录文本)。可通过请求参数 ?yt_timecodes= 覆盖。 |
MARKITDOWN_YT_CHUNK | 否(辅助容器) | 转录块大小,以秒为单位(默认 30)。0 保持原始逐片段粒度。可通过请求参数 ?yt_chunk= 覆盖。 |
MARKITDOWN_YT_LANGS | 否(辅助容器) | 逗号分隔的首选转录语言(例如 de,en)。如果首选语言不存在,则回退到第一个可用语言。 |
MARKITDOWN_YT_PROXY | 否(辅助容器) | YouTube 请求的 HTTP(S) 代理 URL。数据中心 IP 地址经常被 YouTube 的转录 API 限流;住宅或 ISP 代理可能有所帮助。 |
REDDIT_CLIENT_ID | 否 | Reddit 的 OAuth 凭据。没有它们,PullMD 使用公共 JSON API(速率限制较低)。 |
REDDIT_CLIENT_SECRET | 否 | |
REDDIT_USER_AGENT | 否 | Reddit 要求唯一的 UA。默认:PullMD/1.0 (URL-to-Markdown service)。 |
DISABLE_PUBLIC_HISTORY | 否 | 当为 true 时,隐藏全局最近转换列表和归档(/api/history + /api/archive 返回 403,前端隐藏该部分)。/s/:id 分享链接继续工作。默认:false。 |
PULLMD_USER_AGENT | 否 | 为每次 Web 抓取固定一个出站 User-Agent。禁用轮换。适用于 CI 或已知特定 UA 可用的情况。 |
PULLMD_UA_FEED_URL | 否 | 当前真实世界 UA 的 JSON 订阅源 URL。默认:WinFuture23/real-world-user-agents(https://github.com/WinFuture23/real-world-user-agents)。设置为空字符串可禁用实时刷新,并依赖内置的初始种子池。 |
PULLMD_AUTH_MODE | 否 | disabled(默认)/ single-admin / multi-user。参见下方的“认证”。 |
PULLMD_ALLOW_SIGNUP | 否 | multi-user 模式下的自助注册。默认开启。false / 0 / no / off 会关闭 /signup(返回 404)并从登录页移除“创建账户”链接。仍可通过 node scripts/admin.js create-user 创建账户。 |
PULLMD_ADMIN_EMAIL | 当 AUTH_MODE != disabled 时,首次启动时需要 | 第一个管理员的引导邮箱。 |
PULLMD_ADMIN_PASSWORD | 当 AUTH_MODE != disabled 时,首次启动时需要 | 引导密码(最少 8 个字符)。 |
PULLMD_AUTH_TOKEN | 否 | 旧的 bearer token 兼容(仅 single-admin 模式,已弃用)。 |
PULLMD_SOURCE_HEADER | 否 | 设置为 true 可在正文中恢复旧的内联来源头部(# 标题 + **域名** · 日期 + url;对于 Reddit 是 **r/sub** · u/user · N ↑ 行)。默认(未设置):干净正文 - 仅 H1 标题;来源/日期/帖子元数据位于 frontmatter 中。 |
PULLMD_FRONTMATTER_FIELDS | 否 | 逗号分隔的 frontmatter 字段白名单(例如 title,url,source,llm_tokens)。未设置 = 全部字段。可裁剪 token。未知名称会被忽略,并在启动时给出警告。 |
PULLMD_ALLOWED_HOSTS | 否 | 逗号分隔的 CIDR 和/或精确主机名,即使它们解析到被阻止的范围内也允许抓取。默认空 = 每个内部目标都被阻止。参见 SSRF 防护。 |
PULLMD_SITE_RECIPES | 否 | 额外站点配方的 JSON 文件路径,会合并到内置配方之上。替代 data/site-recipes.json。 |
PULLMD_FILENAME_DATE_PREFIX | 否 | 建议下载文件名(X-Suggested-Filename)的前缀模板。未设置 = 无前缀。令牌 YYYY MM DD HH mm ss 按本地时间替换,所有其他字符直接传递;A-Za-z0-9._- 之外的任何字符最终会成为连字符。示例:YYYY-MM-DD-HH-mm-ss- 会得到 2026-08-01-13-33-42-YT-some-talk-dQw4w9WgXcQ.md。 |
PULLMD_COVERAGE_GUARD | 否 | 设置为 off 可禁用覆盖率保护。默认(未设置):开启。该保护会在提取仅保留页面的一小部分时注意到问题——这是页面构建器单页应用的失败模式,其章节存在于扁平的兄弟容器中,而 Readability 的单一候选评分会丢弃这些容器——并重新转换包含正文的容器。它只会增加结果,记录 source: coverage-guard,并在 metadata.extractorReason 中解释原因。 |
PUBLIC_URL 对自托管很重要:帮助页面和可下载技能将其作为规范端点嵌入。正确设置它,你的用户将获得一个指向你的实例的复制粘贴设置。PullMD 会轮换其出站 Use
相似文章
@tom_doerr: Converts web URLs, PDFs, and media files into clean Markdown, automatically stripping ads and navigation while supporti…
PullMD is a self-hosted URL-to-Markdown service for humans and AI agents, converting web pages, PDFs, and media files into clean Markdown, with support for an MCP server and Claude Code skill.
@GitHub_Daily: 想把网页内容喂给 AI,结果抓回来一堆导航栏、广告和乱码,上下文窗口浪费大半,AI 还读不明白。 于是找到 PullMD 这个开源项目,可以把任意网页内容提取转成干净的 Markdown 文件。 只需提供网页链接,自动识别页面类型,层层提…
PullMD 是一个开源的 URL 转 Markdown 服务,可以自动提取网页正文内容,去除导航、广告等杂物,支持无头浏览器和多种接口(网页、REST API、MCP),便于 AI 工具和用户获取干净的网页文本。
@DanKornas: 将网页内容复制到大语言模型时,不应拖拽整个浏览器。.MD this page 是一个浏览器扩展,……
.MD this page 是一个开源浏览器扩展,利用 Mozilla 的 Readability 将网页转换为干净、可直接用于大语言模型的 Markdown,具备一键捕获、预览和导出等功能。
@HowToPrompt__: 有人开源了一个工具,每秒可将PDF转换为Markdown,速度达122页。→ PDF、DOCX、PPTX、XLSX、EPUB、图像…
一个开源工具可将PDF、DOCX、PPTX、XLSX、EPUB及图像转换为Markdown,速度达122页/秒,支持表格、公式和表单,可在GPU、CPU或Mac上运行。
tweet.md
tweet.md 是一款将 X(Twitter)帖子转换为简洁 Markdown 格式的工具,可简化内容复用。