WeasyPrint 替代 pdfkit 可显著提速,因其纯 Python 实现、CSS2.1 渲染稳定,移除脚本、压缩 HTML/CSS、禁用动画及跳过 PDF 压缩后,生成耗时可从 8.2s 降至 2.1s。

用 weasyprint 替代 pdfkit(尤其含 CSS 的页面)
pdfkit 底层调用 wkhtmltopdf,对现代 CSS(如 Flexbox、Grid、@media print)支持弱,常触发重排+反复渲染,导致耗时翻倍。而 weasyprint 是纯 Python 实现的 CSS2.1 渲染引擎,对语义化 HTML + 简洁打印样式适配更稳,生成速度通常快 30%–60%。
- 安装:
pip install weasyprint
- 基础用法:
from weasyprint import HTML
HTML(string=html_content).write_pdf("output.pdf") - 关键提速点:提前移除
、onload属性、内联事件绑定;weasyprint不执行 JS,留着只会拖慢解析 - 避免使用
background-image: url(...)指向远程资源——它会同步阻塞渲染,本地路径也建议转为 data URL 或预加载
预处理 HTML:删 DOM、压样式、禁动画
PDF 渲染器不关心交互,但冗余节点和动态样式会显著增加布局计算量。实测一个含 2000 行 DOM、未压缩的管理后台页面,PDF 生成耗时从 8.2s 降到 2.1s。
- 删掉所有
、、、标签 - 把
内联块提取出来,用cssutils或正则剔除@keyframes、transition、animation相关声明 - 将
class名批量缩短(如user-profile-card-wrapper→upcw),可减少 HTML 字节数和选择器匹配开销 - 强制关闭打印时的动画:在 CSS 中加
@media print { * { animation: none !important; transition: none !important; } }
用 --no-pdf-compression 或 compress=False 反直觉提速
多数人以为压缩 PDF 能减小体积,但压缩过程(尤其是 FlateDecode)是 CPU 密集型操作。当页面以文字为主、无高分图时,跳过压缩反而更快。
-
pdfkit:传参options={'--no-pdf-compression': ''} -
weasyprint:调用时加compress=False,例如:HTML(string=html).write_pdf("out.pdf", compress=False) - 注意:若页面含大量 PNG/JPEG,压缩仍有必要;此时应先用
PIL或sharp在 HTML 渲染前降质图片(宽高 ≤ 1200px,质量 75)
并发生成 PDF 时小心 wkhtmltopdf 的 fork 开销
如果用 pdfkit 多进程生成多个 PDF,每个子进程都会 fork 一次 wkhtmltopdf 进程,启动延迟明显(尤其在容器或低配机器上)。这不是代码问题,是工具链限制。
立即学习“前端免费学习笔记(深入)”;
- 改用单进程 + 异步:
weasyprint是线程安全的,可用concurrent.futures.ThreadPoolExecutor并发处理(非 multiprocessing) - 若必须用
wkhtmltopdf,提前起一个长期运行的守护进程(如用subprocess.Popen持有 stdin/stdout),通过管道喂 HTML,避免重复 fork - 检查
/proc/sys/kernel/pid_max和ulimit -u,高并发下可能因 PID 耗尽直接报Resource temporarily unavailable
实际提速效果取决于 HTML 复杂度,但最常被忽略的是「默认开启的 PDF 压缩」和「没清理的 JS 绑定」——这两项不做,其他优化多半白忙。











