【python 第三方库】weasyprint

2024-01-25 00:00:00

目录:

weasyprint 模块介绍

WeasyPrint 用于将 HTML 和 CSS 内容渲染成高质量的 PDF 文档。适合生成报告、发票、电子书等文档。

安装 WeasyPrint 主要通过 pip3 进行,但由于其依赖一些图形库(如 Cairo、Pango),在不同操作系统上步骤略有差异。

$ pip3 install weasyprint

HTML 字符串生成 PDF

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 会生效。

URL 生成 PDF

from weasyprint import HTML

# 从 URL 生成
HTML('https://blog.dkvirus.com/').write_pdf('test.pdf')

这里尝试打印我的博客首页,打印出来的 PDF 文件内样式有一点问题。

本地 HTML 文件生成 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')

自定义 CSS 样式

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)])

Html 编写尺寸

目标是 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')

与模板引擎(Jinja2)结合

模版引擎可以动态生成 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 开销。

返回首页

本文总阅读量  次
皖ICP备17026209号-3
总访问量: 
总访客量: