如何构建 Web Page to PDF 转换器并保持理智
抱歉,我需要您提供要翻译的具体文本内容(除源码链接外的正文),才能为您进行简体中文翻译。请把文章的其余部分粘贴在这里,我会按照要求保留格式并完成翻译。
将文章保存为 PDF – 仅限纯文本
你是否曾想把文章保存为 PDF 而不带所有额外的杂乱内容——只保留干净、可选中的文本?
或者你只需要页面的特定部分,并希望所有内容在一页长页面上显示,且没有分页?
我也有同样的需求,于是自己实现了一个解决方案,并将其做成了浏览器扩展。
标准的 CTRL + P 有什么问题?
当我把内容保存为 PDF 时,我希望它看起来 完全 与屏幕上一致:
- 可点击的链接
- 整个文档在单个长页面上(没有分页)
CTRL+P 做不到这些。它是为纸质打印设计的,根本不支持上述其他需求。
可用模式在扩展中
1. 完整页面

- 完全保存页面的当前显示效果。
- 文本仍然可选,链接仍然可点击。
- 不是带 OCR 文本的图片——它是真正的 PDF,包含真实文本和真实链接。
2. 导出页面元素

- 在页面上选择特定元素,仅导出该元素。
- 方便保存单篇文章、代码块或其他任何元素。
- 我经常在提交 Google 表单时使用此模式,以便保留填写数据的副本。
3. 文章
最有趣的模式之一。它可以以阅读友好视图保存博客文章——页面上没有其他内容,只有文章本身。
在此模式下,我确保:
- 代码块能够正确换行。
- “ 标签被展开。
因此整篇文章内容都会出现在 PDF 中。
4. 删除元素

- 点击页面上的任意元素并将其删除(例如侧边栏、菜单、广告)。
- 如果不小心删除了重要内容,按 CTRL + Z 撤销。
5. 导出 ChatGPT、DeepSeek 和 Gemini 的聊天记录
由于 AI 公司未提供聊天记录的 PDF 导出功能,我在扩展中加入了此功能。一键即可保存当前打开的对话。
布局选项(所有模式均可用)
- 单页 PDF – 连续滚动,无分页。
- 多页 PDF – 适合打印。
您还可以将页面尺寸调整为匹配屏幕或标准格式,如 A4、A5 等。
如何不让自己抓狂
布局变体太多
保存网站为 PDF 很困难。无法兼顾每一种布局变体——总会有东西出错。
我尝试逐站点修复问题,但很快就变成了对风车的无意义斗争。现在我只为大型平台(例如 Notion)添加特殊修复。
原子化 CSS
大规模采用原子化 CSS 框架(如 Tailwind)让可靠的元素选择变得困难。
- 导出 ChatGPT 对话需要大量工作和复杂的选择器才能抓取对话框元素。
- 使用 Claude Code 时,我因为布局放弃了。
- Gemini 是最容易的——它的类名实际上是可读的。
懒加载
懒加载的图片是另一大痛点。对于包含大量图片的长页面,我使用以下简单方法确保所有图片在生成 PDF 前加载完毕:
for (const img of document.querySelectorAll('img')) {
img.scrollIntoView(); // trigger loading
await new Promise(r => setTimeout(r, 100)); // wait ~100 ms
}
如果你有更优雅的方案,欢迎在评论中分享。
恢复页面样式
导出页面元素模式会隐藏页面上除选定元素之外的所有内容,然后在不重新加载页面的情况下恢复所有样式。
重新加载不是选项——想象一下填写了一个长表单,点击“导出”,页面却刷新了。那种愤怒是真实的。我也经历过。
没有文档
渲染最终 PDF 本身就是一个故事。没有好用的库来完成这项任务。
- Mozilla 的 PDF.js 包含 PDFViewer,听起来很棒——但基本没有文档。
- 只能通过阅读源码和 GitHub issue 来摸索。
- 有大量 issue 请求文档,但 Mozilla 并不打算提供。也算公平——不过还是谢谢这个库。
引擎内部
以下是我主要使用的工具:
- WXT.dev – 用于构建浏览器扩展的框架。在我看来,它是目前最好的选择:快速的 HMR、独立的测试浏览器、极佳的开发速度。
- PDFViewer (PDF.js) – 用于渲染 PDF。
(原文中其余列表被截断。)
PDF 生成选项
从网页生成 PDF 可能会比较棘手。以下是一些最可靠的方法:
- Chrome 调试器 – Chrome DevTools Protocol (Page)
该方法使用 Chrome 调试器将页面转换为 PDF。乍看可能有点奇怪,但它能生成最高质量的 PDF。
接下来是什么?
我正在不断添加与流行网站的集成。
例如,我最近推出了 一键保存 Reddit 帖子。
-
网络服务:
WebToPDF.space – Demo
该网络服务的功能不如扩展程序丰富,但它可以在移动设备上使用。