查看: 110|回复: 2

Python使用Spire.PDF实现PDF转HTML的三种方式及工具类封装

[复制链接]
发表于 4 小时前 | 显示全部楼层 |阅读模式
在数字化内容管理和网页发布中,将PDF转换为HTML是一项实用技能。HTML具有更好的可访问性、搜索引擎友好性和响应式布局,可以将静态PDF转化为可在线查看、搜索和分享的网页内容。本文基于Spire.PDF for Python库,介绍三种转换方式(基本转换、配置选项转换、流式输出),并提供完整的工具类封装及参数调优建议。

环境准备

使用pip安装Spire.PDF库:
  1. pip install Spire.PDF
复制代码

安装后即可在项目中操作PDF并执行HTML转换。

基本PDF转HTML转换

最简单的转换是直接将PDF保存为HTML,保留文本、图片和基本布局。
  1. from spire.pdf.common import *
  2. from spire.pdf import *
  3. def ConvertPDFToHTML():
  4.     inputFile = "/项目进度.pdf"
  5.     outputFile = "ToHTML.html"
  6.     doc = PdfDocument()
  7.     doc.LoadFromFile(inputFile)
  8.     doc.SaveToFile(outputFile, FileFormat.HTML)
  9.     doc.Close()
  10.     print(f"HTML文件已保存至: {outputFile}")
  11. if __name__ == "__main__":
  12.     ConvertPDFToHTML()
复制代码

核心只有三步:加载PDF、保存为HTML、关闭文档。生成的HTML可直接在浏览器打开。

配置转换选项:控制图片嵌入与布局

当需要更精细的控制(如是否嵌入图片、图片质量、布局方式)时,使用
  1. SetPdfToHtmlOptions()
复制代码
方法。
  1. from spire.pdf.common import *
  2. from spire.pdf import *
  3. def ConvertPDFToHTMLWithOptions():
  4.     inputFile = "/示范文本.pdf"
  5.     outputFile = "Configured.html"
  6.     doc = PdfDocument()
  7.     doc.LoadFromFile(inputFile)
  8.     # 参数:useCssLayout(False=绝对定位), embedImages(True=Base64嵌入), imageQuality(1-100)
  9.     doc.ConvertOptions.SetPdfToHtmlOptions(False, True, 1)
  10.     doc.SaveToFile(outputFile, FileFormat.HTML)
  11.     doc.Close()
  12.     print(f"带嵌入图片的HTML: {outputFile}")
  13. if __name__ == "__main__":
  14.     ConvertPDFToHTMLWithOptions()
复制代码
  1. SetPdfToHtmlOptions
复制代码
的三个参数:
- useCssLayout:False使用绝对定位(保持原布局),True使用流式布局(适合响应式设计)。
- embedImages:True将图片编码为Base64嵌入HTML(自包含文件),False则图片单独保存到文件夹。
- imageQuality:1-100,数值越大质量越高但文件越大。

此方式生成的HTML是自包含的,适合独立分发。注意:原文此处命名为“按页面分割输出”,但实际并未分割页面,而是设置转换选项。如果需要按页面分割,需要额外逻辑(如遍历页面逐一保存),本文暂不展开。

流式输出转换结果

如果希望将HTML内容输出到内存或网络流而不是文件,使用
  1. SaveToStream()
复制代码
方法。
  1. from spire.pdf.common import *
  2. from spire.pdf import *
  3. def ConvertPDFToHTMLStream():
  4.     inputFile = "./Demos/Data/Sample.pdf"
  5.     outputFile = "HTMLStream_Output.html"
  6.     doc = PdfDocument()
  7.     doc.LoadFromFile(inputFile)
  8.     fileStream = Stream(outputFile)
  9.     doc.SaveToStream(fileStream, FileFormat.HTML)
  10.     fileStream.Close()
  11.     doc.Close()
  12.     print(f"流输出已保存至: {outputFile}")
  13. if __name__ == "__main__":
  14.     ConvertPDFToHTMLStream()
复制代码

流式输出适合将HTML内容直接存入数据库、发送给上游服务或进行后续内容修改。也可使用
  1. io.BytesIO
复制代码
获取字节数组。

封装PDF转HTML工具类

实际项目中可封装一个工具类,包含基本转换、资源分离、内存流输出和批量转换等功能。
  1. from spire.pdf.common import *
  2. from spire.pdf import *
  3. import os
  4. import io
  5. class PDFToHTMLConverter:
  6.     def __init__(self):
  7.         pass
  8.     def convert_to_html(self, input_file, output_file,
  9.                         embed_images=True, image_quality=80,
  10.                         use_css_layout=False):
  11.         if not os.path.exists(input_file):
  12.             print(f"文件不存在: {input_file}")
  13.             return False
  14.         try:
  15.             doc = PdfDocument()
  16.             doc.LoadFromFile(input_file)
  17.             doc.ConvertOptions.SetPdfToHtmlOptions(
  18.                 use_css_layout, embed_images, image_quality)
  19.             doc.SaveToFile(output_file, FileFormat.HTML)
  20.             doc.Close()
  21.             print(f"✓ 转换成功: {os.path.basename(input_file)} -> {os.path.basename(output_file)}")
  22.             return True
  23.         except Exception as e:
  24.             print(f"✗ 转换失败: {os.path.basename(input_file)} - {str(e)}")
  25.             return False
  26.     def convert_to_html_with_assets(self, input_file, output_folder):
  27.         if not os.path.exists(input_file):
  28.             print(f"文件不存在: {input_file}")
  29.             return False
  30.         try:
  31.             if not os.path.exists(output_folder):
  32.                 os.makedirs(output_folder)
  33.             doc = PdfDocument()
  34.             doc.LoadFromFile(input_file)
  35.             doc.ConvertOptions.SetPdfToHtmlOptions(False, False, 80)
  36.             base_name = os.path.splitext(os.path.basename(input_file))[0]
  37.             html_file = os.path.join(output_folder, f"{base_name}.html")
  38.             doc.SaveToFile(html_file, FileFormat.HTML)
  39.             doc.Close()
  40.             print(f"✓ 转换成功: {os.path.basename(input_file)} -> {html_file}")
  41.             print(f"  图片资源保存在: {output_folder}")
  42.             return True
  43.         except Exception as e:
  44.             print(f"✗ 转换失败: {os.path.basename(input_file)} - {str(e)}")
  45.             return False
  46.     def convert_to_memory_stream(self, input_file, embed_images=True,
  47.                                  image_quality=80, use_css_layout=False):
  48.         if not os.path.exists(input_file):
  49.             print(f"文件不存在: {input_file}")
  50.             return None
  51.         try:
  52.             doc = PdfDocument()
  53.             doc.LoadFromFile(input_file)
  54.             doc.ConvertOptions.SetPdfToHtmlOptions(
  55.                 use_css_layout, embed_images, image_quality)
  56.             memory_stream = io.BytesIO()
  57.             stream = Stream(memory_stream)
  58.             doc.SaveToStream(stream, FileFormat.HTML)
  59.             doc.Close()
  60.             html_content = memory_stream.getvalue()
  61.             memory_stream.close()
  62.             print(f"✓ 转换成功: {os.path.basename(input_file)} -> 内存流")
  63.             return html_content
  64.         except Exception as e:
  65.             print(f"✗ 转换失败: {os.path.basename(input_file)} - {str(e)}")
  66.             return None
  67.     def batch_convert_folder(self, input_folder, output_folder,
  68.                              embed_images=True, image_quality=80):
  69.         if not os.path.exists(input_folder):
  70.             print(f"输入文件夹不存在: {input_folder}")
  71.             return
  72.         if not os.path.exists(output_folder):
  73.             os.makedirs(output_folder)
  74.         pdf_files = [f for f in os.listdir(input_folder) if f.lower().endswith('.pdf')]
  75.         if not pdf_files:
  76.             print(f"在 {input_folder} 中未找到PDF文件")
  77.             return
  78.         print(f"找到 {len(pdf_files)} 个PDF文件,开始转换...")
  79.         success_count = 0
  80.         fail_count = 0
  81.         for pdf_file in pdf_files:
  82.             input_path = os.path.join(input_folder, pdf_file)
  83.             base_name = os.path.splitext(pdf_file)[0]
  84.             output_path = os.path.join(output_folder, f"{base_name}.html")
  85.             if self.convert_to_html(input_path, output_path,
  86.                                     embed_images=embed_images,
  87.                                     image_quality=image_quality):
  88.                 success_count += 1
  89.             else:
  90.                 fail_count += 1
  91.         print(f"\n转换完成! 成功: {success_count}, 失败: {fail_count}")
  92.         print(f"输出目录: {output_folder}")
  93.     def get_html_content_stats(self, html_content):
  94.         if html_content is None:
  95.             return None
  96.         content = html_content if isinstance(html_content, str) else html_content.decode('utf-8')
  97.         stats = {
  98.             'size_bytes': len(content.encode('utf-8')),
  99.             'size_kb': len(content.encode('utf-8')) / 1024,
  100.             'has_images': '<img' in content.lower(),
  101.             'has_tables': '<table' in content.lower(),
  102.             'has_links': '<a ' in content.lower() or '<a href=' in content.lower(),
  103.         }
  104.         return stats
复制代码

使用示例:
  1. def main():
  2.     converter = PDFToHTMLConverter()
  3.     # 基本转换(图片嵌入)
  4.     converter.convert_to_html("./Documents/Report.pdf", "./Output/Report.html",
  5.                               embed_images=True, image_quality=90)
  6.     # 转换并分离图片
  7.     converter.convert_to_html_with_assets("./Documents/Presentation.pdf",
  8.                                          "./Output/Presentation_HTML")
  9.     # 内存流处理
  10.     html_content = converter.convert_to_memory_stream("./Documents/Brief.pdf",
  11.                                                       embed_images=True)
  12.     if html_content:
  13.         stats = converter.get_html_content_stats(html_content)
  14.         print(f"HTML统计: {stats}")
  15.     # 批量转换
  16.     converter.batch_convert_folder("./Documents/PDFs", "./Output/HTMLs",
  17.                                    embed_images=True, image_quality=85)
  18. if __name__ == "__main__":
  19.     main()
复制代码

常见应用场景示例

- 在线文档查看器:将用户上传的PDF转换为HTML(内存流),存储到数据库或缓存实现预览。
- 文档归档系统:批量转换法律文档为HTML,高质量归档(image_quality=95)。
- 内容管理系统集成:将PDF文章转换为HTML(不嵌入图片,由CMS管理),提取内容后发布。

转换质量优化建议

图片处理
- 嵌入 vs 分离:单文件分发用嵌入,网站发布用分离(可利用CDN缓存)。
- 质量平衡:网页浏览70-85,归档90-100。
- 格式优化:可考虑将Base64图片转为WebP(需额外处理)。

布局保持
- 需要响应式设计:启用CSS流式布局(
  1. useCssLayout=True
复制代码
)。
- 需要精确原始布局:使用绝对定位(
  1. useCssLayout=False
复制代码
)。
- 字体处理:确保目标设备有对应字体,或在CSS中引用Web字体。

性能优化
- 批量处理时建议分批进行,避免内存溢出。
- Web应用中用异步任务(如Celery)处理转换请求。
- 对频繁访问的文档缓存HTML结果。

常见问题与解决方案

布局错乱:调整
  1. SetPdfToHtmlOptions
复制代码
参数,使用绝对定位(第一个参数设为False)可更好地保持原始布局。

图片显示异常:检查
  1. embedImages
复制代码
设置。若分离图片,确保图片文件夹与HTML的相对路径正确。

中文乱码:确保HTML头部包含
  1. <meta charset="UTF-8">
复制代码
,否则手动添加。

文件体积过大:降低
  1. imageQuality
复制代码
参数,或分离图片资源并使用压缩格式。

总结

通过Spire.PDF for Python,开发者可以灵活运用基础转换、配置选项和流式处理,实现PDF到HTML的高质量转化。结合工具类封装和参数调优,可轻松集成到在线文档查看器、内容管理系统等场景,提升文档的可访问性和传播效率。
回复

使用道具 举报

发表于 4 小时前 | 显示全部楼层

Re: Python使用Spire.PDF实现PDF转HTML的三种方式及工具类封装

感谢楼主的详细分享!这三种转换方式覆盖了从简单到灵活的场景,工具类封装也很实用,尤其是参数调优的建议对实际项目很有帮助。想请教一下,`useCssLayout=True` 时生成的流式布局在响应式页面中表现如何?另外,工具类里的 `image_quality` 参数默认80,对于高精度图文混排的PDF,是否推荐适当提高数值?期待楼主能补充一下批量转换的完整示例,方便直接复用。再次感谢!
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python使用Spire.PDF实现PDF转HTML的三种方式及工具类封装

感谢分享!这个工具类封装得很实用,尤其是流式输出和配置选项,正好解决了我之前想把PDF转成内嵌图片的HTML用于邮件展示的需求。问一下,对于带有复杂表格或特殊字体的PDF,Spire.PDF转换后的HTML兼容性怎么样?另外,图片质量设成1和100在实际文件大小上差别大吗?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-16 19:27 , Processed in 0.023654 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部