java+selenium+autoIt 實現下載(打印)功能
java+selenium+autoIt 實現下載(打印)功能
selenium是一個開源的自動化測試框架,它可以模擬用戶對瀏覽器的操作,進行自動化的測試。但是,它不僅僅只能用來做測試。
AutoIt 是一個使用類似BASIC腳本語言的免費軟件,它設計用于Windows GUI(圖形用戶界面)中進行自動化操作。它利用模擬鍵盤按鍵,鼠標移動和窗口/控件的組合來實現自動化任務。而這是其它語言不可能做到或無可靠方法實現的(例如VBScript和SendKeys)。在這個項目中AutoIt 主要用于在瀏覽器中點擊下載后,保存文件時,對windos彈框進行操作。
因為業務需求,需要把一個html網頁轉化成PDF,本來準備考慮用iText來對html轉為PDF,但是我們已經擁有html的網頁了,用iText感覺太麻煩,然后又找了一個第三方html->pdf,結果需要收費等一些其它原因,最終決定采用selenium+chrome+java+autol對網頁進行導出PDF。
即使這個是打印成PDF,也可用于下載
環境:springboot v2.1.2 + maven + selenium 3.141.59 + chrome 71.0.3578.98
1 selenium
1.1 關于selenium
selenium是一個自動化測試框架,可以模擬用戶的瀏覽器操作,可以和幾門熱門的語言相結合,例如java,python,接下來我將使用selenuim來操作chrome來模擬用戶將網頁保存為PDF。
1.2 selenium連接chrome
1.2.1 添加selenium的jar包
<!-- Selenium dependency -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-server</artifactId>
<version>3.141.59</version>
</dependency>
1.2.2 下載谷歌瀏覽器驅動
因為我用的是最新的chrome,所以下載的也是暫時最新的驅動,每個驅動對應的谷歌瀏覽器版本也不一樣,你們可以查看相應的文檔,查看自己所對應的驅動
下載完驅動之后,將驅動放置于resource目錄下的driver文件夾內
1.2.3 加載WebDriver
/*獲取瀏覽器的連接*/
public static WebDriver openAccess() {
//在idea運行的谷歌驅動路徑
System.setProperty("webdriver.chrome.driver",
"src/main/resources/driver/chromedriver.exe");
//打jar包后的谷歌驅動路徑
/*String driverPath = System.getProperty("user.dir")+File.separator+"driver"+ File.separator+"chromedriver.exe";*/
HashMap<String, Object> chromePrefs = new HashMap<>();
chromePrefs
.put("profile.default_content_settings.popups", 0);//設置為禁止彈出下載窗口
chromePrefs
.put("download.default_directory", downloadFilepath);//設置為文件下載路徑
ChromeOptions options = new ChromeOptions();
HashMap<String, Object> chromeOptionsMap = new HashMap<>();
options.setExperimentalOption("prefs", chromePrefs);
options.addArguments("--test-type");
options.addArguments("disable-infobars");//取消Chrome正在受到自動測試軟件的控制
/*
用戶瀏覽器地址,用于加載瀏覽器的用戶信息,
這一步將增加瀏覽器的性能消耗,
如果不加這一行,瀏覽器默認已訪客模式進入瀏覽器,
可根據自己的需求來選擇是否使用
*/
options.addArguments("user-data-dir=C:\\Users\\onegene\\AppData\\Local\\Google\\Chrome\\User Data");
DesiredCapabilities cap = DesiredCapabilities.chrome();
cap.setCapability(ChromeOptions.CAPABILITY, chromeOptionsMap);
cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
cap.setCapability(ChromeOptions.CAPABILITY, options);
WebDriver driver = null;
boolean flag = true;
while (flag) {
try {
flag = false;
driver = new ChromeDriver(cap);
//響應時間超過8秒,則重新開啟瀏覽器連接
driver.manage().timeouts().pageLoadTimeout(15, TimeUnit.SECONDS);
driver.manage().window().maximize();
// driver.get(url);
} catch (Exception e) {
flag = true;
if (driver != null) {
driver.quit();
}
log.info("wait for connection browser ");
}
}
return driver;
}
①System.setProperty("webdriver.chrome.driver","src/main/resources/driver/chromedriver.exe");這一步用于在IDEA中運行的是否加載驅動,如果,打成jar包之后,加載驅動的話,應該用下面一行加載驅動,驅動放在與jar包同目錄的dreiver目錄下
String driverPath = System.getProperty("user.dir")+File.separator+"driver"+ File.separator+"chromedriver.exe";
System.setProperty("webdriver.chrome.driver",driverPath);
②options.addArguments("user-data-dir=" + DriverPathUtils.getChromePath());用戶瀏覽器地址,用于加載瀏覽器的用戶信息,這一步將增加瀏覽器的性能消耗,如果不加這一行,瀏覽器默認已訪客模式進入瀏覽器,可根據自己的需求來選擇是否使用
1.3 加載url,進行元素操作
webDriver.get(url);//自己定義
Thread.sleep(1000);
//根絕class尋找元素,并且點擊
WebElement addpBtn = webDriver.findElement(By.className("addp"));
addpBtn.click();
Thread.sleep(1000);
//根據id尋找元素,并且點擊
WebElement genLayoutBtn = webDriver.findElement(By.id("genLayout"));
genLayoutBtn.click();
注:selenium切換tab,并且關閉
String currentWin = webDriver.getWindowHandle();
Set<String> handles = webDriver.getWindowHandles();
for (String handle : handles) {
if (currentWin.equals(handle)) continue;
webDriver = webDriver.switchTo().window(handle);
}
webDriver.close();
1.4調起打印事件
調起如下的谷歌瀏覽器打印事件

調起瀏覽器的打印事件有以下兩種方法:
① 點擊鼠標右鍵,然后點擊打印按鈕
②按住鍵盤的Ctrl+P
顯而易見,第②中方法更實用,所以我們采用第②種
我查看了selenium的鍵盤事件,發現是有鍵盤事件的,調起方法如下:
Actions action = new Actions(driver);
action.keyDown(Keys.CONTROL);// 按下 Ctrl 鍵
action.sednKeys("p")//按下P鍵
action.keyUp(Keys.CONTROL);// 釋放 Ctrl 鍵
action.perform()//發送組合按鍵
本來以為操作鍵盤的方法很簡單,但是不知道為啥chrome一直無法調起鍵盤事件,谷歌了很久,也沒有找到原因,網上也有很多人說無法調起。于是查看jdk文檔,發現java提供了一個操作鍵盤事件的類。如下

所以,我就用以下方法來實現鍵盤事件Ctrl+P
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_P);
robot.keyRelease(KeyEvent.VK_P);
robot.keyRelease(KeyEvent.VK_CONTROL);
本以為事情終于解決了,然后才發現,SpringBoot無法啟動這個鍵盤事件,百度之后,才發現有兩種實現的辦法
①啟動SpringBoot錢,給虛擬機添加參數-ea -Djava.awt.headless=false
②在SpringBoot啟動類中添加代碼,開啟awt
public static void main(String[] args) {
System.setProperty("java.awt.headless", "false");
SpringApplication.run(SeleniumApplication.class, args);
}
1.5 進入保存界面
打印界面進入保存界面只需要按下回車鍵,所以只需按照上一步操作鍵盤點擊回車鍵就好了
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_P);
robot.keyRelease(KeyEvent.VK_P);
robot.keyRelease(KeyEvent.VK_CONTROL);
//睡眠7S,因為谷歌瀏覽器進入打印要先進行渲染,這個需要一段時間
Thread.sleep(7000);
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
2 autolt
AutoIt 目前最新是v3版本,這是一個使用類似BASIC腳本語言的免費軟件,它設計用于Windows GUI(圖形用戶界面)中進行自動化操作。它利用模擬鍵盤按鍵,鼠標移動和窗口/控件的組合來實現自動化任務。而這是其它語言不可能做到或無可靠方法實現的
2.1 autolt基本腳本語法
進入到了另存為得界面,這個時候selenium就基本上無法進行操作了,因為selenium只對谷歌瀏覽器進行操作,不對window窗口進行操作,所以這個時候就需要autolt進行處理了。autolt是一個腳本語言,因為我們只需要保存一個文件,所以并不需要那么深入,所以下面我講下autolt基本使用方法
2.1.1 安裝完軟件之后,各個文件的作用

- 編輯器:用于編寫腳本語言,并且進行調試,按住
F5進行調試 - 運行器:將腳本語言進行運行
- 轉腳本為exe:將編寫的腳本轉換成exe文件,用于java或者python直接運行
- 查看窗口信息:用于獲取將要操作窗口的基本信息,例如將要操作按鈕和編輯框的信息等等
2.1.2 查看窗口信息

查看窗口信息的方法:按住Finder Tool的,然后拖拽到你要操作的位置,這個時候查看Control窗口,就能得到你要操作的元素信息
- Title:當前窗口的標題
- Calss:當前元素的類型,例如當前窗口為編輯框,則這里顯示Edit
- Instance:這個是這個窗口的第一個Edit,所以Instance為1
- ClassnameNN:可以作為當前元素的唯一id,但是沒有AdvancedModel準確
2.2 autolt保存文件
#該腳本的語法是: ;分號代表注釋,為了博客好看,我先把;換成#
##ControlFocus ( "title", "窗口文本", controlID) 設置輸入焦點到指定窗口的某個控件上
#WinWait ( "title題" , "窗口文本" , 超時時間 ) 暫停腳本的執行直至指定窗口存在(出現)為止
#ControlSetText ( "title", "窗口文本", controlID, "新文本" ) 修改指定控件的文本
#Sleep ( 延遲 ) 使腳本暫停指定時間段
#ControlClick ( "title", "窗口文本", 控件ID , 按鈕 , 點擊次數 ) 向指定控件發送鼠標點擊命令
#其中,title即AutoIt Window Info識別出的Title字段,controlID即AutoIt Window Info識別
#出的Class和Instance的拼接,如上圖拼接后的結果應為:Button1
#ControlClick(
#ControlClick("另存為","保存","Button2")
ControlFocus("另存為","text","1001")
WinWait("[CLASS:#32770]","",100)
ControlSetText("另存為","","[CLASS:Edit; INSTANCE:1]","$CmdLine[1]")
Sleep(1500)
ControlClick("另存為","保存","Button2")
2.3 autolt打包成exe
運行轉腳本為exe的文件,將其轉換成exe文件,放入resource目錄下的driver下面
2.4 java運行exe文件
//第一個參數是exe路徑,后面是執行cmd得參數,這個也就是對應保存PDF的名稱
String[] commandArray = {"src/main/resources/driver/pdf.exe", sample.getCode() + ".pdf"};
runtime.exec(commandArray);
3 結尾
雖然我寫的這個博客是關于java+selenium+autolt將html打印成PDF,但是也可以用到下載文件里邊,原理是一樣的。在進行爬蟲的時候,經常要遇到下載文件的業務,這樣可以很好的完成。

浙公網安備 33010602011771號