目录:
WeasyPrint 用于将 HTML 和 CSS 内容渲染成高质量的 PDF 文档。适合生成报告、发票、电子书等文档。
安装 WeasyPrint 主要通过 pip3 进行,但由于其依赖一些图形库(如 Cairo、Pango),在不同操作系统上步骤略有差异。
$ pip3 install weasyprint
from weasyprint import HTML
html_string = """
<html>
<head><style>body { font-family: Arial; }</style></head>
<body>
<h1>项目报告</h1>
<p>这是一个使用 WeasyPrint 生成的 PDF 文档。</p>
</body>
</html>
"""
HTML(string=html_string).write_pdf('test.pdf')
如果 html 字符串中包含 img 标签,引用本地图片,或者引用了外部 css,都是不会生效的。
从本地 html 文件生成 pdf 时,html 中引用本地图片或外部 css 会生效。
from weasyprint import HTML
# 从 URL 生成
HTML('https://blog.dkvirus.com/').write_pdf('test.pdf')
这里尝试打印我的博客首页,打印出来的 PDF 文件内样式有一点问题。
test.html
<html>
<style>
h1 {
color: red;
}
</style>
<body>
<h1>Hello, WeasyPrint!</h1>
<p>This is a simple example.</p>
</body>
</html>
test.py
from weasyprint import HTML
# 从本地文件生成
HTML('test.html').write_pdf('test.pdf')
from weasyprint import HTML, CSS
html_content = """
<div class="resume">
<h1>我的简历</h1>
<p>姓名:张三</p>
</div>
"""
css_string = """
.resume { font-family: "Microsoft YaHei"; margin: 0 auto; width: 800px; }
h1 { color: #333; }
@page {
size: A4;
margin: 2.5cm;
@top-center { content: "公司机密文件"; }
@bottom-right { content: counter(page); }
}
.page-break { page-break-after: always; }
"""
HTML(string=html_content).write_pdf('resume.pdf', stylesheets=[CSS(string=css_string)])
使用 css 打印属性控制分页,详情参阅 css 打印相关属性介绍
css = CSS(string='''
@page {
size: A4;
margin: 2.5cm;
@top-center { content: "公司机密文件"; }
@bottom-right { content: counter(page); }
}
.page-break { page-break-after: always; }
''')
去 谷歌字体库 下载字体对应的 ttf 文件,并保存到本地。
from weasyprint import HTML, CSS
html_content = """
<div class="resume">
<h1>我的简历</h1>
<p>姓名:张三 123456789</p>
</div>
"""
css_string = '''
@font-face {
font-family: 'NunitoSans';
src: url('./NunitoSans.ttf');
}
body {
font-family: 'NunitoSans', sans-serif;
}
'''
HTML(string=html_content).write_pdf('test.pdf', stylesheets=[CSS(string=css_string)])
目标是 A4 横版, html 宽度设置为 1122px, 高度设置为 793px, 在此基础上写页面,导出 pdf 时刚好占满整个页面。
目标是 A4 竖版, html 宽度设置为 793px, 高度设置为 1122px, 在此基础上写页面,导出 pdf 时刚好占满整个页面。
利用 CSS 的绝对定位和透明度可以轻松添加水印。
from weasyprint import HTML
html_with_watermark = """
<html>
<style>
.watermark {
position: absolute;
opacity: 0.1;
transform: rotate(-45deg);
font-size: 80px;
z-index: -1;
}
</style>
<body>
<div class="watermark">CONFIDENTIAL</div>
<div class="content">正式文档内容...</div>
</body>
</html>
"""
HTML(string=html_with_watermark).write_pdf('test.pdf')
模版引擎可以动态生成 HTML 内容,然后使用 weasyprint 将 HTML 内容生成 PDF 文档。
from jinja2 import Template
from weasyprint import HTML
template = Template("""
<html>
<body>
<h1>{{ title }}</h1>
<p>尊敬的 {{ name }},恭喜您完成课程!</p>
</body>
</html>
""")
html_content = template.render(title="结业证书", name="李四")
HTML(string=html_content).write_pdf("test.pdf")
在调用 write_pdf 方法时,设置图片优化相关参数。
from weasyprint import HTML
HTML(string=your_html_with_images).write_pdf(
'output.pdf',
optimize_images=True, # 启用无损压缩,减少内存和文件体积
jpeg_quality=60, # 控制 JPEG 压缩质量。对于小尺寸预览图,60-80 足够
dpi=72 # 显著降低分辨率。网络图片通常 72-96 DPI,无需高分辨率
)
对于可能会重复出现的图片,使用缓存。
cache = {} # 内存缓存字典
# 或指定一个目录用于磁盘缓存:cache = "/tmp/weasyprint_cache"
for i in range(number_of_reports):
HTML(string=html_content).write_pdf(f'report_{i}.pdf', cache=cache)
缓存确保相同的图片只在第一次被加载和解码,后续直接复用,极大减少了 I/O 和 CPU 开销。
↶ 返回首页 ↶