PDF生成时应优先用DOM解析器(如BeautifulSoup、jsdom)清除标签,而非正则匹配或禁用JS,以避免解析错误、执行报错及排版错乱。

PDF生成时如何跳过 标签内容
HTML 转 PDF 工具(如 wkhtmltopdf、Puppeteer、WeasyPrint)默认会解析并执行 ,但多数场景下你只想要静态渲染——脚本逻辑不仅无用,还可能触发错误、阻塞渲染、甚至注入意外样式或 DOM。真正有效的排除方式不是“删掉脚本”,而是让它们不参与渲染流程。
- 对 Puppeteer:用
page.evaluate()手动移除比在 HTML 里写type="text/plain"更可靠,因为后者仍会被某些 PDF 工具误读为可执行内容 - 对 wkhtmltopdf:加
--javascript-delay 0并配合--no-stop-slow-scripts只是降低影响,不能真正跳过;必须提前清理 HTML - 关键原则:PDF 渲染发生在服务端或 CLI 环境,没有浏览器上下文,
document.write、fetch、setTimeout全部会报错或静默失败
用正则还是 DOM 解析器清理
直接用正则匹配 看似快,但极易漏掉注释内嵌脚本、CDN 地址含 、或自闭合写法(如 )。真实项目中应优先用 DOM 解析器预处理。
from bs4 import BeautifulSoupwith open("input.html") as f: soup = BeautifulSoup(f, "html.parser")
for script in soup.find_all("script"): script.decompose()
with open("cleaned.html", "w") as f: f.write(str(soup))
- BeautifulSoup(Python)和 jsdom(Node.js)能正确处理嵌套、编码、命名空间,避免正则的边界陷阱
- 若用 shell 批量处理,
sed -i '/仅适用于格式严格、无换行、无注释的简单 HTML,生产环境慎用 - 注意:有些脚本通过
data-*属性驱动行为(如data-chart-config),这类需保留,仅删标签本身
Puppeteer 中动态禁用 JS 的实际效果
page.setJavaScriptEnabled(false) 确实能阻止脚本执行,但它不会移除 标签,也不影响内联事件(如 onclick)或 CSS 中的 expression()(IE 旧语法)。更严重的是:部分 PDF 工具(如某些版本的 wkhtmltopdf)根本不支持该选项,调用后无任何效果。
- 推荐组合:先用 DOM 解析器清除所有
和on*属性,再用 Puppeteer 截图,双重保险 - 移除事件属性示例:
soup.find_all(lambda t: t.has_attr("onclick"))→ 对每个结果del t["onclick"] - 不要依赖
page.emulateMedia("screen")来规避 JS —— 它只改媒体查询,不影响脚本加载
为什么 inline script 比 external 更危险
在 PDF 渲染时会抛出 ReferenceError: console is not defined,而 通常只是 404 或超时,反而不易中断流程。但 inline 脚本常含直接 DOM 操作(document.body.innerHTML = ...),一旦执行就会污染结构,导致 PDF 排版错乱。
立即学习“前端免费学习笔记(深入)”;
- 检查 HTML 是否含 inline script:搜索
(单行)和(多行)两个模式 - Webpack/Vite 构建产物中常见
,必须清除,否则 PDF 生成会卡死或返回空白页 - 如果使用模板引擎(如 Jinja2、EJS),把脚本逻辑移到后端预计算,输出纯数据 HTML,从源头避开问题
实际排脚本不是“删代码”,是切断执行链路。最容易被忽略的一点:CSS 中的 @import url("script.js") 或 background: url("xss.svg") 也可能触发 JS 执行(尤其在老旧工具中),这类非 标签的 JS 载入路径,得靠白名单机制或资源拦截来控制。











