Selenium使用总结(Java版本)

8,254 阅读6分钟

近期开发使用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/… www.xnathan.com/2017/12/04/…

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.代理使用

github.com/lightbody/b…

一、无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…

10.项目实战策略:搭配http请求、多线程、grid使用