Selenium webdriver ChromeDriver--页面加载后打印为pdf

Selenium webdriver ChromeDriver--页面加载后打印为pdf,selenium-webdriver,selenium-chromedriver,google-chrome-headless,Selenium Webdriver,Selenium Chromedriver,Google Chrome Headless,根据,Chrome可以在无头模式下启动,使用--打印到pdf,以导出网页的pdf。这适用于通过GET请求访问的页面 试图找到一个打印到pdf的解决方案,允许我在Chrome中执行多个导航请求后导出pdf。示例:打开google.com,输入搜索查询,单击第一个结果链接,导出为PDF 在查看[数量非常有限的]文档和样本时,我没能找到一种方法在页面加载后指示Chrome导出PDF。我正在使用Javachrome驱动程序 一个不涉及铬的可能解决方案是使用一种工具,如。在将HTML发送到工具之前,继续此

根据,Chrome可以在无头模式下启动,使用
--打印到pdf
,以导出网页的pdf。这适用于通过
GET
请求访问的页面

试图找到一个打印到pdf的解决方案,允许我在Chrome中执行多个导航请求后导出pdf。示例:打开
google.com
,输入搜索查询,单击第一个结果链接,导出为PDF

在查看[数量非常有限的]文档和样本时,我没能找到一种方法在页面加载后指示Chrome导出PDF。我正在使用Java
chrome驱动程序

一个不涉及铬的可能解决方案是使用一种工具,如。在将HTML发送到工具之前,继续此路径将迫使我执行以下操作:

  • 将HTML保存在本地文件中
  • 遍历DOM并下载所有文件链接(图像、js、css等)
我不喜欢这个路径,因为它需要我进行大量的修补[我假设]才能正确读取下载的文件路径


有没有一种方法可以指示Chrome打印为PDF格式,但只能在页面加载后打印?

由于没有答案,我将解释我的解决方法。我没有试图找到如何从Chrome请求打印当前页面,而是走了另一条路

对于本例,我们将尝试从Google下载查询“示例”的结果页面:

  • 使用
    driver.get(“google.com”)
    导航,输入查询“示例”,单击“谷歌搜索”
  • 等待结果页面加载
  • 使用
    driver.getPageSource()
  • 使用Jsoup等解析源代码,以便将所有相关链接重新映射到为此目的定义的端点(如下所述)-示例到
    localhost:8080
    。链接“./style.css”将变成“localhost:8080/style.css”
  • 将HTML保存到文件中,例如名为“查询示例”
  • 运行
    chrome--print to pdf localhost:8080/search?id=query example
  • 将会发生的是,chrome将从我们的控制器请求HTML,对于我们返回的HTML中定义的资源,它将转到我们的控制器-因为我们重新映射了相对链接-这将反过来将该请求转发到资源的真实位置-google.com。下面是一个Spring控制器示例,请注意该示例不完整,此处仅作为指导

    @RestController
    @请求映射
    公共类InternationalOffloadRestController{
    @RequestMapping(method=RequestMethod.GET,value=“/search/html”)
    公共字符串getHtml(@RequestParam(“id”)字符串id){
    File File=新文件(“HTML文件的位置”,id);
    try(FileInputStream输入=新的FileInputStream(文件)){
    返回IOUtils.toString(输入,HTML_编码);
    }
    }
    @RequestMapping(“/**”)//将所有重新映射的链接转发到google.com
    公共无效转发(HttpServletResponse HttpServletResponse,…){
    URI=新URI(“https”,null,“google.com”,-1,
    request.getRequestURI(),request.getQueryString(),null);
    setHeader(“Location”,uri.toString());
    httpServletResponse.setStatus(httpServletResponse.SC_永久移动);
    }
    }
    

    从命令行执行此操作的一个示例,需要对页面html和
    sed进行一些修改:

    LOGIN='myuserid'
    PASSW='mypasswd'
    AUTH='pin=$LOGIN&accessCode=$PASSW&Submit=Submit'
    TIMESTAMP=`TZ=HST date -d "today" +"%m/%d/%y %I:%M %p HST"`
    wget -q --save-cookies cookies.txt --keep-session-cookies \
        --post-data $AUTH \
        https://csea.ehawaii.gov/iwa/index.html
    sed -i 's#href="/iwa/css#href="./bin#g' index.html
    sed -i 's#src="/iwa/images#src="./bin#g' index.html
    wkhtmltopdf -q --print-media-type \
                --header-left "$d" --header-font-size 10 \
                --header-line --header-spacing 10 \
                --footer-left "Page [page] of [toPage]" --footer-font-size 10 \
                --footer-line --footer-spacing 10 \
                --footer-right "$TIMESTAMP" \
                --margin-bottom 20 --margin-left 15 \
                --margin-top 20 --margin-right 15 \
                index.html index.pdf
    
    假设Cookie有效,登录后可以访问更多页面,如下所示:

    wget -q --load-cookies cookies.txt https://csea.ehawaii.gov/otherpage.html
    wkhtmltopdf <all the options> otherpage.html otherpage.pdf
    
    wget -r -A.jpg -A.gif -A.css -nd -Pbin \
        https://csea.ehawaii.gov/iwa/index.html
    

    这确实可以通过Selenium Chromedriver通过
    ExecuteCromeCommandWithResult
    方法实现。执行命令
    Page.printToPDF
    时,结果字典的“数据”项中返回一个base-64编码的PDF文档

    下面的答案中提供了一个C#示例,它应该很容易翻译成Java:

    下面是另一个C#示例,说明了一些有用的选项:

    publicstaticvoidmain(字符串[]args)
    {
    var driverOptions=新的ChromeOptions();
    //在无头模式下,默认情况下启用PDF写入(使用驱动程序主版本85进行测试)
    驱动程序。添加参数(“无头”);
    使用(var驱动程序=新的色度驱动程序(驱动程序))
    {
    driver.Navigate().gotour(“https://stackoverflow.com/questions");
    新的WebDriverWait(驱动程序,TimeSpan.FromSeconds(10))。直到(d=>d.FindElements(由.CssSelector(“#问题”))。计数==1);
    //以90%的比例输出A4大小的第一页PDF
    var printpoptions=新字典
    {
    {“纸张宽度”,210/25.4},
    {“paperHeight”,297/25.4},
    {“比例”,0.9},
    {“页面范围”,“1”}
    };
    var printOutput=driver.ExecuteChromeCommandWithResult(“Page.printopdf”,printOptions)作为字典;
    var pdf=Convert.FromBase64String(打印输出[“数据”]为字符串);
    文件.writealBytes(“stackoverflow-page-1.pdf”,pdf);
    }
    }
    
    此处记录了
    页面.printToPDF
    调用的可用选项:

    使用JavaSelenium4.x.x版本,可以实现这一点

    String command = "Page.printToPDF";
    Map<String, Object> params = new HashMap<>();
    params.put("landscape", false);
    Map<String, Object> output = driver.executeCdpCommand(command, params);
    try {
        FileOutputStream fileOutputStream = new FileOutputStream("export.pdf");
        byte[] byteArray = Base64.getDecoder().decode((String)output.get("data"));
        fileOutputStream.write(byteArray);
    } catch (IOException e) {
        e.printStackTrace();
    }
    
    String命令=“Page.printToPDF”;
    Map params=新的HashMap();
    参数put(“横向”,假);
    映射输出=driver.executdpcommand(命令,参数);
    试一试{
    FileOutputStream FileOutputStream=新的FileOutputStream(“export.pdf”);
    字节[]byteArray=Base64.getDecoder().decode((字符串)输出.get(“数据”);
    fileOutputStream.write(byteArray);
    }捕获(IOE异常){
    e、 printStackTrace();
    }
    

    来源:

    你能分享你的代码试用版吗?没有什么可以分享的,因为我的尝试毫无进展。但我可以解释我的过程。它基本上包括尝试当时对我有意义的任何东西,以便在执行
    window.print()
    后强制Chrome打印成PDF。也看了一下,但是这些对m没有帮助
    String command = "Page.printToPDF";
    Map<String, Object> params = new HashMap<>();
    params.put("landscape", false);
    Map<String, Object> output = driver.executeCdpCommand(command, params);
    try {
        FileOutputStream fileOutputStream = new FileOutputStream("export.pdf");
        byte[] byteArray = Base64.getDecoder().decode((String)output.get("data"));
        fileOutputStream.write(byteArray);
    } catch (IOException e) {
        e.printStackTrace();
    }