zoukankan      html  css  js  c++  java
  • python之批量打印网页为pdf文件

      最近实际工作中,小爬遇到这样一个需求,小爬需要将多个流程申请表单网页另存为PDF文件,我们如何利用python将这个过程自动化呢?

      假定我们通过爬虫已经拿到了这些表单的URL,且这些流程表单需要登陆后才能打开。那像那些将HTML直接转pdf的库,如pdfkit、wkhtmltopdf就不能很好地发挥作用了。

      比较直接的方法是使用selenium库:pip install selenium即可快速安装它。利用它的driver.get(URL)方法请求网站的登录页,利用time.sleep(seconds)方法等待用户输入用户名密码正常进入网站,之后的每个driver.get请求,就自动属于登陆状态了。这里小爬倾向于使用chrome浏览器+chromedriver.exe配合selenium完成页面的自动化打印。

      等网页渲染好后,我们该如何打印呢?

      小爬之前尝试的一种方法是,利用windows10 自带的Microsoft Print To PDF虚拟打印机。借助pywin32库中win32print方法来操作.

    比如自动设置系统当前默认打印机:

    win32print.SetDefaultPrinter(device_name) # 设置默认打印机

      再比如,我们可以获取当前打印机:

    currentPrinter=win32print.GetDefaultPrinterW()

      借助这两个api,我们就可以后台悄无声息地更改默认打印机为Microsoft Print To PDF来打印网页为pdf,用完后再悄悄还原默认打印机为用户一开始设定的常用打印机。

      之后就是在网页加载好之后,调用系统的打印界面,即Ctrl+Shift+P。我们需要借助win32api.keybd_event(vk_code[keyname],0,0,0) 来完成模拟,之后等待系统打印窗口弹出后,再借助win32api的findWindow、sendmessage方法来捕获窗口以及完成窗口元素的点击和编辑。由于之前的博文中已经有提及此方法,再此不再赘述。该方法的主要缺陷在于:

    1. win32api.keybd_event不稳定,当我们的窗口焦点丢失时,我们的模拟热键可能会失败;
    2. findWindow、sendmessage方法有时也会失败。

      为了提高程序的稳定性,我们可能不得不使用try except结合while循环来配合使用,多次调用这些window api,直至成功。也正是因为这些,小爬最终决定使用chrome中原生的打印方法,然后调用chrome的“另存为PDF”功能来完成 html 转PDF。

      那么python+selenium这条线如何来自动调用chrome的这套方法呢?

       上图中标示的这些参数,如何通过selenium传导给浏览器,告诉浏览器我们的打印具体配置参数需求?小爬已经提前帮大家踩坑了,示例代码如下:

    import os,json,time
    from selenium import webdriver
    from selenium.webdriver.common.keys import Keys
    
    chrome_options = webdriver.ChromeOptions()
    
    settings = {
        "recentDestinations": [{
            "id": "Save as PDF",
            "origin": "local",
            "account": ""
        }],
        "selectedDestinationId": "Save as PDF",
        "version": 2,
        "isHeaderFooterEnabled": False,
    
        # "customMargins": {},
        # "marginsType": 2,
        # "scaling": 100,
        # "scalingType": 3,
        # "scalingTypePdf": 3,
        "isLandscapeEnabled":True,#landscape横向,portrait 纵向,若不设置该参数,默认纵向
        "isCssBackgroundEnabled": True,
        "mediaSize": {
            "height_microns": 297000,
            "name": "ISO_A4",
            "width_microns": 210000,
            "custom_display_name": "A4 210 x 297 mm"
        },
    }
    
    chrome_options.add_argument('--enable-print-browser')
    #chrome_options.add_argument('--headless') #headless模式下,浏览器窗口不可见,可提高效率
    
    prefs = {
        'printing.print_preview_sticky_settings.appState': json.dumps(settings),
        'savefile.default_directory': 'your file path' #此处填写你希望文件保存的路径
    }
    chrome_options.add_argument('--kiosk-printing') #静默打印,无需用户点击打印页面的确定按钮
    chrome_options.add_experimental_option('prefs', prefs)
    
    
    driver = webdriver.Chrome("./chromedriver", options=chrome_options)
    driver.get('your URL')
    driver.maximize_window()
    # time.sleep(7)
    driver.execute_script('document.title="my_test_file1.pdf";window.print();') #利用js修改网页的title,该title最终就是PDF文件名,利用js的window.print可以快速调出浏览器打印窗口,避免使用热键ctrl+P
    driver.close()

      代码中的setting部分详细注明了,如何设置打印窗口的缩放、边距、纸张类型、打印机名、页面布局(横向、纵向)等信息,供各位参考。

    该方法有如下优势:

    1. chrome原生的打印网页为pdf功能,支持较好;
    2. 配置参数灵活,个性化打印;
    3. 稳定,几乎不会出错,也不需要加sleep来提升程序的稳定性;
    4. 效率更高。

      有相同需求的你,还不赶快试试?

  • 相关阅读:
    40个极简WordPress主题
    一些上流的CSS3图片样式
    15个最好的 HTML5 视频播放器
    优秀的IOS界面
    25 个超棒的 WordPress 主题(2012)
    Codekit 为Web前端打造的全能型神器(附推荐各种工具)
    10 个精彩的、激发灵感的 HTML5 游戏
    20个非常绚丽的 CSS3 特性应用演示
    25+ 个免费精美的商业风格的 WordPress 主题
    10 款非常棒的CSS代码格式化工具推荐
  • 原文地址:https://www.cnblogs.com/new-june/p/14509601.html
Copyright © 2011-2022 走看看