java,利用Selenium调用浏览器,动态模拟浏览器事件,动态获取页面信息
1、环境搭建
jdk1.6版本:selenium 2.4版本。
jdk1.8版本:selenium3.14版本。
(1)selenium的jar包下载:
地址:http://selenium-release.storage.googleapis.com/index.html
需要用:selenium-server-standalone-3.9.1.jar(需要在cmd下安装,java -jar ***),selenium-java-2.40.0.jar,selenium-java-2.40.0-srcs.jar还有它的libs。
(2)webDriver下载:
网址: http://chromedriver.storage.googleapis.com/index.html
或者 http://npm.taobao.org/mirrors/chromedriver/
注意:webDriver必须与浏览器版本相对应,否则会出现问题
2、程序代码示例
//固定时间等待:driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS); //设定最大等待时间,一旦标签存在即可返回:wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(".abc"))) WebDriver driver = new ChromeDriver(); // 新建一个WebDriver 的对象,但是new 的是谷歌的驱动 driver.get(url); // 打开指定的网站 try { Thread.sleep(60000);// 60秒 driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS); } catch (Exception e) { e.printStackTrace(); } //定位层级元素 WebElement e = driver.findElement(By.cssSelector(".animation-toggle")); e.click(); //等待加载完页面 try { Thread.sleep(60000);// 60秒 driver.manage().timeouts().implicitlyWait(60,TimeUnit.SECONDS);//等待界面加载完 } catch (Exception e2) { e2.printStackTrace(); } SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); Date d=new Date(); List<WebElement> list = driver.findElements(By.cssSelector("img.frame"));//img标签,class为frame int i=-1; for (WebElement el : list) { String img_url=el.getAttribute("src"); //System.out.println(img_url); String time = sdf.format(d.getTime()+i*24*60*60*1000); loadPage(img_url,type,time); i=i+1; } driver.quit();// 退出浏览器
3、元素定位
(1)根据tagName
driver.findElement(By.cssSelector("input")
(2)根据ID
driver.findElement(By.cssSelector("input#username"));html标签和#id
driver.findElement(By.cssSelector("#username"));只是#id
(3)根据className
单一class:driver.findElement(By.cssSelector(".username"));.class
复合class:driver.findElement(By.cssSelector(".username.**.***"));.classA.classB
(4)根据元素属性
1)精准匹配:
[A] driver.findElement(By.cssSelector("input[name=username]"));属性名=属性值,id,class,等都可写成这种形式
[B] driver.findElement(By.cssSelector("img[alt]"));存在属性。例如img元素存在alt属性
[C] driver.findElement(By.cssSelector("input[type='submit'][value='Login']"));多属性
2)模糊匹配:(正则表达式匹配属性)
[A] ^= driver.findElement(By.cssSelector(Input[id ^='ctrl']));匹配到id头部 如ctrl_12
[B] $= driver.findElement(By.cssSelector(Input[id $='ctrl']));匹配到id尾部 如a_ctrl
[C] *= driver.findElement(By.cssSelector(Input[id *= 'ctrl']));匹配到id中间如1_ctrl_12
更多正则匹配原则请查看CSS3 选择器——属性选择器 http://www.w3cplus.com/css3/attribute-selectors
(5)查询子元素
<form id="form" class="fm" name="f"> <span id="s_kw_wrap" class="bg s_ipt_wr quickdelete-wrap"> <input id="kw" class="s_ipt" type="text" autocomplete="off" maxlength="100" name="wd"> </span> <span id="s_btn_wr" class="btn_wr s_btn_wr bg"> <input id="su" class="btn self-btn bg s_btn" type="submit" value="百度一下"> </span> </form>
以上代码是百度首页搜索输入框和按钮的html,下面讲解以此为例
1)子元素 A>B
WebElement input= driver.findElement(By.cssSelector("form>span>input"));//搜索输入框
2)后代元素 A空格B
WebElement input= driver.findElement(By.cssSelector("form input"));//搜索输入框
3)第一个后代元素 :first-child
WebElement span= driver.findElemet(By.cssSelector("form :first-child"));//冒号前有空格,定位到form下所有级别的第一个子元素
可定位到三个元素:<span id="s_kw_wrap".../> <input id="kw"..../> <input id="su"........./>
WebElement span= driver.findElemet(By.cssSelector("form input:first-child"));//冒号前无空格,定位到form下所有级别的第一个input元素
可定位到两个元素:<input id="kw"..../> <input id="su"........./>
WebElement span= driver.findElemet(By.cssSelector("form>span:first-child"));//冒号前无空格,定位到form直接子元素中的第一个span元素
可定位到一个元素:<span id="s_kw_wrap".../>
4)最后一个子元素 :last-child [类同:first-child]
WebElement userName = driver.findEleme(By.cssSelector("form :last-child"));//冒号前有空格,定位到form下所有级别的第一个子元素
5)第2个子元素 :nth-child(N) [类同:first-child]
WebElement userName = driver.findElemet(By.cssSelector("form#form :nth-child(2)"));//冒号前有空格,定位到form下所有级别的第二个子元素
(6)查询兄弟元素
driver.findElement(By.cssSelector("form#form span+span")); 定位到a 再定位到和它相邻的b
4、页面响应等待问题
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);不靠谱
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(".abc")));不实用
Thread.sleep(60000);比较实用
最后,在附赠一个列子:
import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import org.openqa.selenium.Alert; import org.openqa.selenium.By; import org.openqa.selenium.Cookie; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.interactions.Actions; import org.openqa.selenium.support.ui.Select; public class Test1 { public static void main(String[] args) { System.setProperty("webdriver.chrome.driver", "D:\\webDriver\\chromedriver.exe");// chromedriver服务地址 WebDriver driver = new ChromeDriver(); // 新建一个WebDriver 的对象,但是new 的是谷歌的驱动 String url = "http://www.baidu.com"; driver.get(url); // 打开指定的网站 //driver.navigate().to(url); // 打开指定的网站 /* * * driver.findElement(By.id("kw")).sendKeys(new String[] { "hello" });// * 找到kw元素的id,然后输入hello driver.findElement(By.id("su")).click(); // 点击按扭 */ try { /** * WebDriver自带了一个智能等待的方法。 dr.manage().timeouts().implicitlyWait(arg0, arg1); * Arg0:等待的时间长度,int 类型 ; Arg1:等待时间的单位 TimeUnit.SECONDS 一般用秒作为单位。 */ driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS); } catch (Exception e) { e.printStackTrace(); } //获取当前浏览器的信息 System.out.println("Title:" + driver.getTitle()); System.out.println("currentUrl:" + driver.getCurrentUrl()); //执行js脚本 String jString = "alert('122')"; ((JavascriptExecutor) driver).executeScript(jString); //获取单个元素 WebElement element = driver.findElement(By.id("wrapper")); System.out.println(element.getAttribute("class")); //获取多个元素 List<WebElement> elList = driver.findElements(By.tagName("input")); for (WebElement e : elList) { System.out.println("获取多个元素:"+e.getAttribute("name")); } //定位层级元素 WebElement e = driver.findElement(By.cssSelector("#qrcode-item qrcode-item-1")); List<WebElement> list = e.findElements(By.tagName("div")); for (WebElement e1 : list) { System.out.println("定位层级元素:"+e1.getAttribute("class")); } //获取当前的窗口 String currentWindow = driver.getWindowHandle(); //获取所有的窗口 Set<String> handles = driver.getWindowHandles(); //遍历窗口 Iterator<String> iterator = handles.iterator(); while (iterator.hasNext()) { if (currentWindow == iterator.next()) continue; //跳转到弹出的窗口 WebDriver driver2 = driver.switchTo().window(iterator.next()); driver2.getTitle(); } //处理弹出框 Alert alert = driver.switchTo().alert(); alert.getText(); alert.dismiss();//相当于点击取消 Alert confirm = driver.switchTo().alert(); confirm.getText(); confirm.accept();//相当于点击确认 Alert prompt = driver.switchTo().alert(); prompt.getText(); prompt.accept(); prompt.sendKeys("测试1");//输入值 //处理下拉列表 Select select = new Select(driver.findElement(By.id("select"))); select.selectByIndex(1); select.selectByValue("西安"); select.selectByVisibleText("咸阳"); //获取下拉框的全部选项 List<WebElement> list2 = select.getOptions(); for (WebElement webElement : list2) { webElement.click();//点击下拉框 } //处理cookie //添加一个cookie Cookie cookie = new Cookie("COOKIE", "NAME","D://COOKIES"); driver.manage().addCookie(cookie); //获取cookies Set<Cookie> set = driver.manage().getCookies(); Iterator<Cookie> iterator2 = set.iterator(); while (iterator2.hasNext()) { Cookie c = iterator2.next(); c.getName(); c.getValue(); c.getPath(); } driver.manage().deleteAllCookies(); driver.manage().deleteCookie(cookie); driver.manage().deleteCookieNamed("COOKIE"); //等待加载完页面 try { driver.manage().timeouts().wait(1); driver.manage().timeouts().implicitlyWait(1,TimeUnit.SECONDS);//等待界面加载完 } catch (InterruptedException e2) { e2.printStackTrace(); } //模拟鼠标和键盘操作 Actions action = new Actions(driver); action.click(); action.dragAndDrop(element, e); action.sendKeys(element,"12222").perform(); action.click(element); action.keyDown(currentWindow); // driver.quit();// 退出浏览器 /** * dr.quit()和dr.close()都可以退出浏览器,简单的说一下两者的区别:第一个close, * 如果打开了多个页面是关不干净的,它只关闭当前的一个页面。第二个quit, * 是退出了所有Webdriver所有的窗口,退的非常干净,所以推荐使用quit最为一个case退出的方法。 */ } }