如何使用 Selenium 在网页上单击打印按钮

Posted

技术标签:

【中文标题】如何使用 Selenium 在网页上单击打印按钮【英文标题】:How to click on the print button on a web page using Selenium 【发布时间】:2014-12-18 19:19:37 【问题描述】:

我想点击这个页面的打印按钮:

https://www.google.com/maps/dir/40.4515849,-3.6903752/41.380896,2.1228198/@40.4515849,-3.6903752/am=t/?hl=en

然后保存 PDF...

这是点击按钮的代码:

String url = "https://www.google.com/maps/dir/40.4515849,-3.6903752/41.380896,2.1228198/@40.4515849,-3.6903752/am=t/?hl=en";

WebDriver driver = new htmlUnitDriver();
driver.get(url);

System.out.println(driver.getTitle());
System.out.println(driver.getCurrentUrl());

WebElement element = driver.findElement(By.xpath("//*[@id=\"text-mode-options-header\"]/div/div/div[2]/div[2]/div/button[1]"));
element.click();

System.out.println("Page title is: " + driver.getTitle());
driver.quit();

但我收到以下错误:

    Exception in thread "main" org.openqa.selenium.NoSuchElementException: Unable to locate a node using //*[@id="text-mode-options-header"]/div/div/div[2]/div[2]/div/button[1]
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Build info: version: '2.43.1', revision: '5163bce', time: '2014-09-10 16:27:58'
Driver info: driver.version: HtmlUnitDriver
    at org.openqa.selenium.htmlunit.HtmlUnitDriver.findElementByXPath(HtmlUnitDriver.java:1057)
    at org.openqa.selenium.By$ByXPath.findElement(By.java:357)
    at org.openqa.selenium.htmlunit.HtmlUnitDriver$5.call(HtmlUnitDriver.java:1575)
    at org.openqa.selenium.htmlunit.HtmlUnitDriver$5.call(HtmlUnitDriver.java:1)
    at org.openqa.selenium.htmlunit.HtmlUnitDriver.implicitlyWaitFor(HtmlUnitDriver.java:1251)
    at org.openqa.selenium.htmlunit.HtmlUnitDriver.findElement(HtmlUnitDriver.java:1572)
    at org.openqa.selenium.htmlunit.HtmlUnitDriver.findElement(HtmlUnitDriver.java:532)
    at com.controlstation.start.Main.main(Main.java:24)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

如何使用 Selenium 做到这一点?还有其他方法吗?谢谢。

编辑:

【问题讨论】:

你对的理解是什么[2]/div/按钮[1]?是正确的 ID 和正确的 div 吗? 尝试By.xpath("//*[@id="text-mode-options-header"]//button[text()='Print']") 使用按钮文本而不是使用div 层次结构。 【参考方案1】:

这是我的见解。

首先,您需要等待页面加载才能与Print 按钮进行交互。最好的方法是使用内置机制:selenium waits - 等待Print 按钮可点击

// open print dropdown
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("button.print-button"))).click();

// click print button
WebElement printButton = driver.findElement(By.cssSelector("button.print-popup-button"));
printButton.click();

好的,如果你使用 ChromeDriver 运行它:

package com.company;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;


public class Main 
    public static void main(String[] args) 
        String url = "https://www.google.com/maps/dir/40.4515849,-3.6903752/41.380896,2.1228198/@40.4515849,-3.6903752/am=t/?hl=en";

        WebDriver driver = new ChromeDriver();
        driver.get(url);

        // open print dropdown
        WebDriverWait wait = new WebDriverWait(driver, 10);
        wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("button.print-button"))).click();

        // click print button
        WebElement printButton = driver.findElement(By.cssSelector("button.print-popup-button"));
        printButton.click();

        // now what? 
    

您将看到 Chrome 打印预览 对话框,不幸的是,它超出了 selenium 的范围:

但是,有一个希望,如果你检查可用的Chrome arguments,你会发现有一个相关的:

--disable-print-preview - 禁用打印预览(用于测试和不喜欢我们的用户。:[)

好的,我们试试看:

ChromeOptions options = new ChromeOptions();
options.addArguments("--disable-print-preview");

WebDriver driver = new ChromeDriver(options);
driver.get(url);

现在,会显示一个系统打印对话框:

Selenium 也无法控制它。所以,不,没有希望。哦,等等!


好的,如果我们超出了 selenium 的范围,让我们使用可以帮助我们单击对话框中的 Print 按钮的工具 - Robot 类:

该类用于为 测试自动化、自运行演示和其他目的 需要控制鼠标和键盘的应用程序。

我们将初始化Robot 并在打印对话框出现时发送Enter 键:

package com.company;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.awt.*;
import java.awt.event.KeyEvent;


public class Main 
    public static void main(String[] args) throws AWTException, InterruptedException 
        String url = "https://www.google.com/maps/dir/40.4515849,-3.6903752/41.380896,2.1228198/@40.4515849,-3.6903752/am=t/?hl=en";

        Robot r = new Robot();
        r.delay(1000);

        WebDriver driver = new ChromeDriver();
        driver.get(url);

        // open print dropdown
        WebDriverWait wait = new WebDriverWait(driver, 10);
        wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("button.print-button"))).click();

        // click print button
        WebElement printButton = driver.findElement(By.cssSelector("button.print-popup-button"));
        printButton.click();

        Thread.sleep(2000);

        r.keyPress(KeyEvent.VK_ENTER);
        r.keyRelease(KeyEvent.VK_ENTER);
    

使用其他选项:

sikuli - 您需要打印按钮的图像,以便 sikuli 找到并单击 autoit

另见:

How to handle print dialog in Selenium?

【讨论】:

哇,非常感谢...它有效,但我不想打开浏览器,我想在不打开任何浏览器的情况下保存 PDF(只需保存 PDF 以便我可以发送给我的客户)【参考方案2】:

这样你可以点击Print including maps-选项(对不起,它是在C#中):

Actions builder = new Actions(Driver);
builder.MoveToElement(Driver.FindElement(By.ClassName("print-button"))).Click()
       .MoveToElement(Driver.FindElements(By.ClassName("print-popup-button"))[0]).Click().Build().Perform();            

但是!在您的问题中,您有一张 Chrome 打印预览窗口的图片,我认为您的代码正在使用的 HtmlUnitDriver 无法使用该窗口。您始终可以使用 chromedriver 运行测试,但打印预览似乎超出了 selenium 的范围,即。您无法使用 webdriver 控制它。据我所知,系统打印对话框也是如此,它与 Firefox 一起出现。如果 HtmlUnitDriver 在这种情况下表现不同,那么你会没事的,但我担心你会在这里遇到问题。

【讨论】:

【参考方案3】:

只是添加到@JoriO 发布的内容中,您能否在使用 Selenium 单击 Web 元素之前测试它是否存在?如果不存在,请在 driver.get(url)... 之后添加线程睡眠语句。原因是 Selenium 可能会在驱动程序完成加载页面之前尝试单击。这解决了我使用 Selenium 错误“没有此类元素异常”时遇到的大部分问题

【讨论】:

以上是关于如何使用 Selenium 在网页上单击打印按钮的主要内容,如果未能解决你的问题,请参考以下文章

Selenium 在按钮单击后获取 http 请求 ajax url

单击按钮后使用 Selenium 切换到新窗口

在 Android 按钮上打印 Pdf 文件 单击

如何在单击按钮时打印 HTML 内容,而不是页面? [复制]

我想在网页上单击某个按钮,调用本地的应用程序,如何实现最好?求高人指导!!!

在 Python 中使用 Selenium 在 Firefox 上保存网页