1.通过Maven安装依赖
注意:这里会发现maven导入的 4.10.0 版本,结果发现selenium的版本由4.10.0变成了3.141.59。这里会报错 java.lang.NoClassDefFoundError: org/openqa/selenium/internal/Require
原因:去spring-boot-dependencies模块中去搜索selenium发现默认的版本的为3.141.59,到这里发现是springboot的pom坐标配置覆盖了自己写的pom坐标,所以才会出现类org/openqa/selenium/internal/Require找不到的情况。
这里有个疑惑点,难道不应该是自己写的pom坐标覆盖spring-boot-dependencies中的pom坐标嘛?
解决办法:就是让自己的坐标覆盖默认的坐标!改动如下,程序正常运行
该问题只有在selenium与springboot一起使用时才会出现!
2.下载浏览器驱动
当selenium升级到3.0之后,对不同的浏览器驱动进行了规范。如果想使用selenium驱动不同的浏览器,必须单独下载并设置不同的浏览器驱动。 各浏览器下载地址:
Firefox浏览器驱动:geckodriver
Chrome浏览器驱动:chromedriver、taobao备用地址
IE浏览器驱动:IEDriverServer
Edge浏览器驱动:MicrosoftWebDriver
safari浏览器驱动:由于safari浏览器本身已经集成了safaridriver,只要启用并开启即可
safaridriver --enable
Opera浏览器驱动:operadriver
PhantomJS浏览器驱动:phantomjs
注:部分浏览器驱动地址需要科学上网。
3.验证浏览器驱动
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.opera.OperaDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
public class Itest {
public static void main(String[] args) {
ChromeOptions options = new ChromeOptions();
WebDriver driver = new ChromeDriver(); //Chrome浏览器
FirefoxOptions options = new FirefoxOptions();
WebDriver driver = new FirefoxDriver(); //Firefox浏览器
EdgeOptions options = new EdgeOptions();
WebDriver driver = new EdgeDriver(); //Edge浏览器
InternetExplorerOptions options = new InternetExplorerOptions();
WebDriver driver = new InternetExplorerDriver(); // Internet Explorer浏览器
SafariOptions options = new SafariOptions();
WebDriver driver = new SafariDriver(); //Safari浏览器
}
}
4.常见操作(后续我遇到之后也会继续更新)
4.1 获取网页元素的方法
//chromeDriver.findElement()为查询某个元素,当有多个时候只会返回第一个对象
//chromeDriver.findElements()方法可以查找元素列表
//以上两种方式都是从浏览器的根节点出发来找元素的
//获取到的WebElement对象都可以继续进行findElement()或者findElements()的操作,这个是从当前元素出发开始寻找WebElement对象
//参数有By.id(),By.tagName(),By.xpath()等,可以使用不同的方式来定位
WebElement body= chromeDriver.findElement(By.tagName("body"));//寻找html页面上的第一个body标签的元素
List<WebElement> divs = body.findElements(By.tagName("div"));//查找所有body标签下的div元素
//一般情况下可以通过以上这两种方法的组合获取到页面的任何一种元素
4.2 执行网页的js代码并取到js的返回值
//执行document.body.scrollHeight并将返回值拿到(获取body标签的高度)
Long totalHeight = (Long) chromeDriver.executeScript("return document.body.scrollHeight")
//有些操作在java里面操作特别麻烦,但是在js中操作可能就会简单很多,可以直接执行js的代码
//网页向下滚动
chromeDriver.executeScript("window.scrollTo(0,100)");//无需返回值的时候就不需要进行return
4.3 鼠标移动到某一元素,并点击(一些简单的模拟登录就会需要这个操作)
//先定位到登录按钮的元素
WebElement loginButton= chromeDriver.findElement(By.id("login_id"));
//鼠标移动到该元素上然后点击
Actions actions = new Actions(webDriver);//操作对象,里面有很多的鼠标、键盘动作可自行试一下
actions.moveToElement(loginButton).click().perform();
4.4 滚动页面,在解决滚动加载时是个好办法
//实际上也是来执行js代码进行滚动网页的
//获取到body的高度
//然后滚动到最下方
Long totalHeight = (Long) chromeDriver.executeScript("return document.body.scrollHeight");
chromeDriver.executeScript("window.scrollTo(0," + totalHeight + ")");
5.常见的坑!!!!!!
5.1 网页没有加载完获取元素时会失败
当元素加载未完成的时候,html并没有当前的元素节点,获取不到就是报错(这样我感觉很奇怪,但没办法人家就是这么设计的)
解决办法:
5.1.1 固定等待
在chromeDriver.get(“www.baidu.com”)方法执行完之后,线程休眠一段时间,等他加载完,但是这样就显得很不智能,不过确实是一个办法
Thread.sleep(2000);//具体休眠时间看你电脑网速,还是有加载完网页的时间,预估一下就行
5.1.2 隐式等待
全局生效,每次获取元素的时候都会等5秒(根据你自己需要设置),一旦元素出现就会继续执行下去。只需要设置一次就行了,driver实例被关闭后也就消失。
这种方式程序只会等到页面加载完了(浏览器上那个小圈圈不转了)才会去执行下面代码,如果有时候页面大部分元素都加载完了,只有极个别元素,这样就很浪费时间
//在driver实例化后完成之后设置隐式等待,设置超时的时间为5s
chromeDriver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
5.1.3 显示等待
用来等待某个条件发生后再继续执行后续代码(如找到元素、元素可点击、元素已显示等)
方法 | 条件 |
---|---|
visibilityOfElementLocated(By Locator) | 页面元素在页面存在并且可见 |
elementToBeClickable(By Locator) | 页面元素是否在页面上可用和可被单击 |
elementToBeSelected(WebElement element) | 页面元素处于被选中状态 |
textToBePresentInElement(By locator) | 在页面元素中是否包含特定的文本 |
presenceOfElementLocated(By locator) | 页面元素在页面中存在 |
//显示等待
WebDriverWait webDriverWait=new WebDriverWait(chromeDriver, 5);
webDriverWait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("xxxx")));
5.2 有些元素在iframe标签下面,导致获取不到
使用代码,将chromeDriver切换到iframe里面
有些网页可能有多层的iframe这时就需要进行一层一层的切进去,但是切出来只需要一下就好
5.2.1 如果iframe标签有name或者id的话
//直接切换到他frame()方法的参数为iframe的name或者id
chromeDriver.switchTo().frame("");
5.2.2 iframe当作一个元素进行切换
//找到iframe的标签
WebElement iframe = driver.findElement(By.tagName("iframe"));
//切换到改iframe
chromeDriver.switchTo().frame(iframe);
5.2.3切出iframe
chromeDriver.switchTo().defaultContent();
5.3 解决一些selenium识别的反爬
5.3.1 禁用启用Blink运行时的功能
window.navigator.webdriver的值设置为false
options.addArguments("--disable-blink-features=AutomationControlled");
chromeDriver.executeScript("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})", "");