近期開發使用Selenium比較多,由於以前沒用過,趟了太多坑,在此記錄一下html
配置要點:java
1.webdriver要和瀏覽器版本對應,chrome使用chromedriver和chrome瀏覽器,firefox使用geckodrive和firefox瀏覽器node
2.支持headless:本地開發使用mac環境,默認支持;linux須要安裝xvf8(虛擬GUI)linux
3.maven項目構建,使用selenium-3.9.1或者最新版本git
4.linux配置參考:chrome:blog.csdn.net/qq_39802740… ; firefox:blog.csdn.net/u014283248/… www.xnathan.com/2017/12/04/…github
chrome啓動參數參考:peter.sh/experiments…web
1.系統環境變量配置:webdriver.chrome.driver=DRIVER_PATHchrome
2.經常使用options配置:centos
—headless | 無瀏覽器模式 |
---|---|
--no-sandbox | 非沙盒模式,linux部署必填 |
--disable-gpu | 禁用gpu,liinux部署需填,防止未知bug |
blink-settings=imagesEnabled=false | 不加載圖片 |
--user-agent=ua值 | 設置ua |
3.webdriver實例化:api
//設置系統環境變量 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(); } } 複製代碼
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請求等)
參考:www.cnblogs.com/linxinmeng/…
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();//點擊取消 } 複製代碼
String js = "window.open('http://www.baicu.com')";//js腳本,打開一個新頁面 ((JavascriptExecutor)driver).executeScript("");//執行js腳本 複製代碼
介紹:整合封裝簡化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; } } } 複製代碼
String proxyServer = "1.2.3.4:666"; Proxy proxy = new Proxy().setHttpProxy(proxyServer).setSslProxy(proxyServer); options.setProxy(proxy); 複製代碼
使用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管理
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…
selenium新的api再也不支持phantom.js,能夠使用舊版api
1.設置黑名單
2.設置header
3.其餘
chromium雖然是多進程執行,可是js引擎是單線程,同時打開多個窗口,只會加載一個頁面,直到加載結束或打開下一個窗口才會去加載下一個頁面,參考(blog.csdn.net/ouyanggengc…
firefox能夠同時加載多個窗口的頁面,同時會默認屏蔽一些請求
1.經過代理設置,browsermobserver
BrowserMobProxy server = new BrowserMobProxyServer(); server.blacklistRequests("http://.*\\.blacklist.com/.*", 200);//方式1,設置單個黑名單 server.setBlacklist();//方式2,設置黑名單列表 複製代碼
2.經過拓展設置,暫時沒整透
1.採用正確鏈接方式
//錯誤 Proxy proxy = ClientUtil.createSeleniumProxy(server);//沒法獲取到代理的host //正確 String proxyServer = "localhost:11112"; Proxy proxy = new Proxy().setHttpProxy(proxyServer).setSslProxy(proxyServer); 複製代碼
2.使用最新的maven包
developer.mozilla.org/zh-CN/docs/…
1.options禁止彈窗
2.獲取alert,關閉彈窗
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
使用grid啓動多個節點
注意:單節點使用多線程時,最好使用geckodriver,chromium的js引擎是單線程執行的
gecko官方文檔:github.com/mozilla/gec…
firefox-source-docs.mozilla.org/testing/gec…
chromium官方文檔:chromedriver.chromium.org/getting-sta…