前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用Selenium实现HTML转PDF

使用Selenium实现HTML转PDF

作者头像
州的先生
发布2021-03-19 15:05:00
3.8K0
发布2021-03-19 15:05:00
举报
文章被收录于专栏:州的先生州的先生

前段时间,州的先生为了在觅道文档中实现 markdown 转 pdf 的功能,考察和调研的市面上的一些通行解决方案,详见>>>Python转换HTML为PDF方案合集,你中意哪种?

在那之后,觅道文档选择了Chromium + pyppeteer 的方案作为 HTML 转换 PDF 的技术栈。

但是这个方案并非完美可靠,由于 PyPeeteer 这个第三方库年久失修,很多 Bug 没有修复,导致在觅道文档中调用它经常性地会出现异常。

不得已,州的先生只得另寻它法。由于觅道文档中生成的 PDF 是需要动态渲染一些图形的(比如 Echarts 图表、思维导图、流程图等),所以只能在基于浏览器内核进行渲染的工具中进行选择。因为 whtmltopdf 使用的是老旧的 webkit 作为渲染内核,第一个就将其否决掉。

然后基于对 PyQt5 的熟悉,在 Windows 上使用 PyQt5 的 QWebengine 小部件对 HTML 文件进行 PDF 转换,测试效果还行。结果代码上传到 Linux 服务器上之后,各种系统依赖性的确实和报错。考虑到安装部署的便捷性,只能放弃这个测试了很久的方案。

最后转向了使用 Selenium 调用 Chromium 浏览器的无头模式,将打开的 HTML 打印导出为 PDF,算是比较完美地解决了觅道文档中文集导出 PDF 的问题。下面来看看最核心的实现过程:

依赖库

代码语言:javascript
复制
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import base64

配置 chrome 的启动参数

代码语言:javascript
复制
webdriver_options = Options()
webdriver_prefs = {}

webdriver_options.add_argument('--headless')
webdriver_options.add_argument('--disable-gpu')
webdriver_options.add_argument('--no-sandbox')
webdriver_options.add_argument('--disable-dev-shm-usage')
webdriver_options.experimental_options['prefs'] = webdriver_prefs
webdriver_prefs['profile.default_content_settings'] = {'images': 2}

实例化一个 Chrome

首先在 Selenium 中 实例化一个 Chrome 对象:

代码语言:javascript
复制
driver = webdriver.Chrome(executable_path=settings.CHROMIUM_DRIVER_PATH,options=webdriver_options)

然后请求 HTML 文件,path 为 HTML 文件路径,也可以为 url:

代码语言:javascript
复制
driver.get(path)

加载及处理

首先等待请求加载的完成:

代码语言:javascript
复制
WebDriverWait(driver, timeout).until(staleness_of(driver.find_element_by_tag_name('html')))

然后,配置一个用于打印命令的字典:

代码语言:javascript
复制
calculated_print_options = {
            'landscape': False,
            'displayHeaderFooter': False,
            'printBackground': True,
            'preferCSSPageSize': True,
        }

接着,获取 selenium 当前 session 的相关信息,使用让 Chrome 执行 Page.printToPDF 这一用于打印页面的命令:

代码语言:javascript
复制
resource = "/session/%s/chromium/send_command_and_get_result" % driver.session_id
    url = driver.command_executor._url + resource
    body = json.dumps({'cmd': 'Page.printToPDF', 'params': calculated_print_options })
    response = driver.command_executor._request('POST', url, body)

获取到最后的响应:

代码语言:javascript
复制
result = response.get('value')

最后将响应写入文件之中:

代码语言:javascript
复制
with open('report.pdf', 'wb') as file:
    file.write(result)

这样,就实现了 HTML 到 PDF 文件的转换。

模块调用

实际上,Pypi 中已经存在第三方模块实现了上述的流程,并且添加了 PDF 文件压缩的功能。通过如下命令即可安装使用:

代码语言:javascript
复制
pip install pyhtml2pdf

具体的使用方法详见:https://pypi.org/project/pyhtml2pdf/

上述实现的觅道文档代码位于(点击“阅读原文”快捷访问):https://gitee.com/zmister/MrDoc/blob/master/app_doc/report_html2pdf.py

?分享、点赞、在看,给个三连击呗!?

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 州的先生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 依赖库
  • 配置 chrome 的启动参数
  • 实例化一个 Chrome
  • 加载及处理
  • 模块调用
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档