Selenium使用總結(Java版本)
近期開發使用Selenium比較多,因為之前沒用過,趟了太多坑,在此記錄一下
1.環境配置
配置要點:
1.webdriver要和瀏覽器版本對應,chrome使用chromedriver和chrome瀏覽器,firefox使用geckodrive和firefox瀏覽器
2.支援headless:本地開發使用mac環境,預設支援;linux需要安裝xvf8(虛擬GUI)
3.maven專案構建,使用selenium-3.9.1或者最新版本
4.linux配置參考:chrome:blog.csdn.net/qq_39802740… ; firefox:blog.csdn.net/u014283248/…
2.chromium專案使用
chrome啟動引數參考:peter.sh/experiments…
1.系統環境變數配置:webdriver.chrome.driver=DRIVER_PATH
2.常用options配置:
—headless | 無瀏覽器模式 |
---|---|
--no-sandbox | 非沙盒模式,linux部署必填 |
--disable-gpu | 禁用gpu,liinux部署需填,防止未知bug |
blink-settings=imagesEnabled=false | 不載入圖片 |
--user-agent=ua值 | 設定ua |
3.webdriver例項化:
//設定系統環境變數
System.setProperty("webdriver.chrome.driver", env.getProperty("path.chrome.driver"));
WebDriver webDriver = null;
try{
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless"); //無瀏覽器模式
options.addExtensions(new File(env.getProperty("path.chrome.proxy")));//增加代理擴充套件
webDriver = new ChromeDriver(options);//例項化
}catch(Exception e){
e.printStackTrace();
}finally{
//使用完畢,關閉webDriver
if(webDriver != null){
webDriver.quit();
}
}
複製程式碼
3.gecko專案使用
1.系統環境變數配置:webdriver.gecko.driver=DRIVER_PATH
2.常用options配置:
—headless | 無瀏覽器模式 |
---|---|
--no-sandbox | 非沙盒模式,linux部署必填 |
--disable-gpu | 禁用gpu,liinux部署需填,防止未知bug |
--user-agent=ua值 | 設定ua |
preference配置:
permissions.default.image | 2 | 不載入圖片 |
---|---|---|
3.webdriver例項化:
//設定系統環境變數
System.setProperty("webdriver.gecko.driver", env.getProperty("path.gecko.driver"));
WebDriver webDriver = null;
try{
FirefoxOptions options = new FirefoxOptions();
options.addArguments("--headless"); //無瀏覽器模式
FirefoxProfile profile = new FirefoxProfile();
profile.addExtensions(new File(env.getProperty("path.chrome.proxy")));//增加代理擴充套件
profile.setPreference("permissions.default.image", 2);//不顯示圖片
options.setProfile(profile);
//例項化
webDriver = new FirefoxDriver(options);
}catch(Exception e){
e.printStackTrace();
}finally{
//使用完畢,關閉webDriver
if(webDriver != null){
webDriver.quit();
}
}
複製程式碼
4.注意:預設載入會遮蔽部分請求(js請求等)
4.Selenium專案使用基本操作
參考:www.cnblogs.com/linxinmeng/…
一、WebDriver例項化:見2、3
1.獲取頁面:driver.get(url);
2.關閉頁面:driver.close(); 關閉程序:driver.quit();
二、載入等待:頁面初始載入或元素載入時使用,三種方式:
1.執行緒強制休眠等待,Thread.sleep(3000);
2.隱式等待(全域性等待),對所有操作都設定的等待時間,超時會拋異常,driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
3.顯式等待(可控等待,推薦使用),可以對單一操作設定等待觸發事件及等待時間,可自定義事件,超時會拋異常
WebDriverWait wait = new WebDriverWait(webDriver, 60);//初始化等待60s
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("xx")));//等待xx元素出現
//自定義等待事件
WebElement frame = wait.until((ExpectedCondition<WebElement>) driver -> {
WebElement element = driver.findElement(By.id("iframepage"));
return element;
});
複製程式碼
三、獲取內容
String page = driver.getPageSource();//獲取網頁全部資訊
String url = driver.getCurrentUrl();//獲取當前頁url
WebElement element = driver.findElement(By.id("xx"));//獲取元素
element.sendKeys("test");//設定元素值
element.click();//點選元素
element.sendKeys(Keys.BACK_SPACE);//空格鍵盤事件模擬
複製程式碼
四、切換視窗、表單、彈窗:
1.視窗操作
String handle = driver.getWindowHandle();//獲取當前視窗控制代碼
Set<String> handles = driver.getWindowHandles();//獲取全部視窗控制代碼
//切換到另一視窗
for(String h : handles){
if(!h.equals(handle)){
driver.switchTo().window(h);//切換視窗
}else{
driver.close();
}
}
複製程式碼
2.表單操作,frame切換需要從外向內一層一層獲取,可根據pageSource處理
driver.switchTo().frame("top");//切換到top Frame
driver.switchTo().frame("inner");//切換到inner Frame
複製程式碼
3.彈窗操作
Alert alert = webDriver.switchTo().alert();//獲取彈窗
if(alert != null){
alert.sendKeys("123");//設定輸入框文字,只能設定一個輸入框文字
alert.getText();//獲取彈窗資訊
alert.accept();//點選確認
alert.dismiss();//點選取消
}
複製程式碼
五、js指令碼執行
String js = "window.open('http://www.baicu.com')";//js指令碼,開啟一個新頁面
((JavascriptExecutor)driver).executeScript("");//執行js指令碼
複製程式碼
5.PageFactory模式
介紹:整合封裝簡化WebDriver業務操作流程,採用工廠模式配合FindBy等註解使用
PageGenerator page = new PageGenerator(driver);//抽象page物件
//例項化LoginPage物件,並呼叫click方法
page.GetInstance(LoginPage.class).click("admin","123456");
複製程式碼
LoginPage.java
public class LoginPage extends BasePage{
private final static String URL = "https://www.testlogin.com";
@FindBy(id = "login")
private WebElement login;
public LoginPage(WebDriver driver) {
super(driver);
}
public Boolean clickLogin(String name, String pwd){
get(URL);
click(login);
return wait(ExpectedConditions.urlContains("main.html"));
}
}
複製程式碼
BasePage.java
public class BasePage extends PageGenerator {
private Long timeOut = 60L;//預設超時時間60s
public BasePage(WebDriver driver) {
super(driver);
}
public <T> void get(String url) {
driver.get(url);
}
public <T> T wait(ExpectedCondition<T> c){
return wait(c, timeOut);
}
public <T> T wait(ExpectedCondition<T> c, Long t){
WebDriverWait webDriverWait = new WebDriverWait(this.driver, t==null?timeOut:t);
try{
return webDriverWait.until(c);
}catch (Exception e){
return null;
}
}
public <T> void click (T elementAttr) {
if(elementAttr.getClass().getName().contains("By")) {
driver.findElement((By) elementAttr).click();
} else {
((WebElement) elementAttr).click();
}
}
}
複製程式碼
PageGenerator.java
public class PageGenerator {
public WebDriver driver;
public PageGenerator(WebDriver driver){
this.driver = driver;
}
public <T extends BasePage> T GetInstance (Class<T> pageClass) {
try {
return PageFactory.initElements(driver, pageClass);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
}
複製程式碼
6.代理使用
一、無auth驗證代理
String proxyServer = "1.2.3.4:666";
Proxy proxy = new Proxy().setHttpProxy(proxyServer).setSslProxy(proxyServer);
options.setProxy(proxy);
複製程式碼
二、需auth驗證代理
使用browsermobproxy做代理(或其他代理)
//建立一個本地代理
BrowserMobProxyServer bmpServer = new BrowserMobProxyServer();
bmpServer.setChainedProxy(new InetSocketAddress("proxy.com",222));//代理地址埠
bmpServer.chainedProxyAuthorization("user","pwd",AuthType.BASIC);//代理使用者名稱密碼
bmpServer.setTrustAllServers(true);//信任所有服務
bmpServer.start(11112);//啟動一個本地代理服務,並設定埠為11112,訪問地址:localhost:11112
//使用本地代理
String proxyServer = "localhost:11112";
Proxy proxy = new Proxy().setHttpProxy(proxyServer).setSslProxy(proxyServer);
options.setProxy(proxy);
複製程式碼
本地代理可單獨做分散式部署,多節點,使用zk管理
三、使用瀏覽器擴充套件extensions
1.chrome擴充套件:無法在headless模式下使用載入擴充套件,尚未解決
chromeOptions.addExtensions(new File(env.getProperty("path.chrome.proxy")));//代理擴充套件 需要在background.js配置代理賬號密碼後再打包
複製程式碼
參考:
2.firefox擴充套件:無法使用,新版本firefox由於認證問題無法載入,尚未解決
3.firefox使用close-proxy-authentication外掛,需要舊版才能使用:www.site-digger.com/html/articl… addons.thunderbird.net/zh-tw/thund…
四、使用phantom.js
selenium新的api不再支援phantom.js,可以使用舊版api
五、代理其他作用
1.設定黑名單
2.設定header
3.其他
7.遇到的坑
一、頁面載入慢:(需驗證)
chromium雖然是多程序執行,但是js引擎是單執行緒,同時開啟多個視窗,只會載入一個頁面,直到載入結束或開啟下一個窗口才會去載入下一個頁面,參考(blog.csdn.net/ouyanggengc…
firefox可以同時載入多個視窗的頁面,同時會預設遮蔽一些請求
二、設定黑名單:遮蔽某些網頁載入(設定header同理)
1.通過代理設定,browsermobserver
BrowserMobProxy server = new BrowserMobProxyServer();
server.blacklistRequests("http://.*\\.blacklist.com/.*", 200);//方式1,設定單個黑名單
server.setBlacklist();//方式2,設定黑名單列表
複製程式碼
2.通過拓展設定,暫時沒整透
三、bmp代理無法連線
1.採用正確連線方式
//錯誤
Proxy proxy = ClientUtil.createSeleniumProxy(server);//無法獲取到代理的host
//正確
String proxyServer = "localhost:11112";
Proxy proxy = new Proxy().setHttpProxy(proxyServer).setSslProxy(proxyServer);
複製程式碼
2.使用最新的maven包
四、firefox相容使用chrome擴充套件
developer.mozilla.org/zh-CN/docs/…
五、使用auth代理時,彈出登入框
1.options禁止彈窗
2.獲取alert,關閉彈窗
六、grid啟動
1.使用grid啟動:chromedriver的許可權要和grid的許可權一致
2.啟動grid節點: -Dwebdriver.chrome.driver引數放在-jar後面 java -jar -Dwebdriver.chrome.driver=/Users/apple/Downloads/chromedriver selenium-server-standalone-3.141.5.jar -role node -hub http://localhost:4444/grid/register -browser browserName=chrome
8.分散式
使用grid啟動多個節點
注意:單節點使用多執行緒時,最好使用geckodriver,chromium的js引擎是單執行緒執行的
9.wiki、doc參考整理
gecko官方文件:github.com/mozilla/gec…
firefox-source-docs.mozilla.org/testing/gec…
chromium官方文件:chromedriver.chromium.org/getting-sta…