如何用Python将带格式的HTML内容追加到现有PDF的内容末尾(不另起新页)
如何用Python将带格式的HTML内容追加到现有PDF的内容末尾(不另起新页)
嘿,这个需求确实有点讲究——既要保留HTML的格式(段落、表格、图片都不能丢),又得精准续在原PDF最后一页的内容后面,不能直接开新页。我来给你拆解一下实现步骤,用Python结合几个实用的库就能搞定!
核心思路
要实现这个需求,我们需要分三步走:
- 把带格式的HTML转换成PDF(这样才能保留所有样式);
- 精准计算原PDF最后一页的剩余可用空间;
- 把HTML转成的PDF内容,先尝试塞进原PDF的剩余空间,放不下的部分再生成新页追加。
需要安装的库
首先得装两个关键库:
PyMuPDF(fitz):用来处理PDF页面,精确计算空间和复制内容;WeasyPrint:完美支持HTML转PDF,能保留各种样式、表格和图片。
执行下面的命令安装:
pip install pymupdf weasyprint
具体代码实现
我把代码拆成几个函数,方便你理解和复用:
1. HTML转PDF函数
先把你的HTML内容转换成临时PDF字节流,这样后续好处理:
from weasyprint import HTML import fitz # PyMuPDF import io def html_to_pdf(html_content): # 将HTML字符串转换成PDF字节流 html = HTML(string=html_content) pdf_bytes = html.write_pdf() return io.BytesIO(pdf_bytes)
2. 计算原PDF最后一页剩余空间
这里用PyMuPDF来获取原PDF最后一页的已用内容高度,从而算出剩余空间:
def get_last_page_remaining_space(original_pdf_path): doc = fitz.open(original_pdf_path) last_page = doc[-1] # 获取页面的实际可打印区域高度 mediabox = last_page.mediabox total_page_height = mediabox[3] - mediabox[1] # 找到页面上所有文字内容的最底部位置(如果有图片/表格,后续可以补充判断) all_text_rects = last_page.get_text("words") if not all_text_rects: # 如果页面是空的,剩余空间就是整个页面高度 remaining_height = total_page_height else: # PyMuPDF的y轴是从下往上的,所以取最大的y坐标就是内容最底部 max_content_bottom = max(rect[3] for rect in all_text_rects) remaining_height = total_page_height - max_content_bottom doc.close() return remaining_height, total_page_height, mediabox
3. 核心合并函数
这部分是重点,把HTML内容精准追加到原PDF末尾:
def append_html_to_pdf(original_pdf_path, html_content, output_pdf_path): # 第一步:把HTML转成临时PDF html_pdf_stream = html_to_pdf(html_content) html_doc = fitz.open("pdf", html_pdf_stream) # 第二步:获取原PDF最后一页的剩余空间 remaining_height, total_page_height, mediabox = get_last_page_remaining_space(original_pdf_path) original_doc = fitz.open(original_pdf_path) last_original_page = original_doc[-1] # 处理HTML的第一页内容 html_first_page = html_doc[0] # 计算HTML第一页的实际内容高度(不是页面高度) html_text_rects = html_first_page.get_text("words") if html_text_rects: html_content_top = min(rect[1] for rect in html_text_rects) html_content_bottom = max(rect[3] for rect in html_text_rects) html_content_height = html_content_bottom - html_content_top else: html_content_height = 0 if html_content_height <= remaining_height: # 能放下!把HTML第一页的内容复制到原PDF最后一页 # 计算偏移量:让HTML内容刚好接在原内容的下面 offset_y = total_page_height - remaining_height # 复制HTML内容到原页面,只取实际内容部分,避免空区域 content_rect = fitz.Rect(0, html_content_top, mediabox[2]-mediabox[0], html_content_bottom) last_original_page.show_pdf_page(last_original_page.rect, html_doc, 0, clip=content_rect, shift=fitz.Point(0, offset_y)) # 剩下的HTML页面直接追加到原PDF后面 for page_num in range(1, len(html_doc)): original_doc.insert_pdf(html_doc, from_page=page_num, to_page=page_num) else: # HTML第一页内容太长,剩余空间放不下,就直接把所有HTML页面追加到原PDF后面 print("HTML第一页内容超出剩余空间,直接追加所有页面到原PDF末尾") original_doc.insert_pdf(html_doc) # 保存最终的PDF original_doc.save(output_pdf_path) # 关闭文档释放资源 original_doc.close() html_doc.close()
使用示例
你可以这样调用函数,替换成你自己的HTML内容和PDF路径:
# 替换成你自己的HTML内容 my_html = """ <html> <body> <p>这是追加的段落,带<b>加粗</b>和<i>斜体</i>样式~</p> <table border="1" cellpadding="5"> <tr><th>姓名</th><th>年龄</th></tr> <tr><td>张三</td><td>25</td></tr> <tr><td>李四</td><td>30</td></tr> </table> <img src="https://picsum.photos/200/120" alt="示例图片"> </body> </html> """ # 调用函数生成结果 append_html_to_pdf("你的原PDF路径.pdf", my_html, "最终输出PDF路径.pdf")
注意事项
- 关于非文字元素:上面的代码只通过文字来计算内容高度,如果原PDF里有图片、表格等非文字元素,剩余空间计算可能会有点误差。如果需要更精准,可以结合
last_page.get_drawings()和last_page.get_images()来补充判断内容的边界。 - WeasyPrint依赖:在Linux系统上安装WeasyPrint时,可能需要额外装系统依赖(比如
libpango-1.0-0、libcairo2等),Windows和Mac一般安装时会自动处理。 - 复杂HTML拆分:如果HTML内容特别长,且必须拆分第一页塞进剩余空间,那需要更精细的处理(比如把HTML拆分成多个小块逐个转换插入),上面的代码是基础版本,能满足大部分常规场景。
备注:内容来源于stack exchange,提问作者Jitendra Tank
相关产品推荐
相关产品推荐

