使用selenium模拟浏览器操作页面及问题处理(采用Java语言)
有一个需求是:页面上有一批测试数据要删除,一共10万条数据,每页显示20条,一共5000页,手动删除的操作一般是先点击全选本页20条,点击"删除"按钮,再点击弹出"确认"按钮完成一次操作。人工点击太费时费力,本来写了一个js脚本,每隔10秒定时去操作,把脚本放在当前页面的浏览器控制台执行,不一会浏览器就卡死了。这时selenium就派上用场了
所需依赖:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.53.1</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-api</artifactId>
<version>2.53.1</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>2.53.1</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-support</artifactId>
<version>2.53.1</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-server</artifactId>
<version>2.53.1</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-remote-driver</artifactId>
<version>2.53.1</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-htmlunit-driver</artifactId>
<version>2.52.0</version>
</dependency>
代码实现逻辑:
// 加载驱动 System.setProperty("webdriver.chrome.driver", "D:/chromedriver/chromedriver.exe"); driver = new ChromeDriver(); // 访问登陆页面 driver.get("这里写登陆页url"); // 跳转到原始登录页 WebElement oldLogBtn=((ChromeDriver) driver).findElementByLinkText("旧版页面登录"); oldLogBtn.click(); // 用户名 WebElement username=((ChromeDriver) driver).findElementById("username"); username.sendKeys("这里写用户名"); // 密码 WebElement password=((ChromeDriver) driver).findElementById("password"); password.sendKeys("这里写密码"); // 记住登录状态 WebElement remember=((ChromeDriver) driver).findElementById("rememberMe"); remember.click(); // 提交登陆 WebElement submit =((ChromeDriver) driver).findElementById("login"); submit.click(); driver.get("这里写抓取页url"); // 当前页面全选框 WebElement checkbox = ((ChromeDriver) driver).findElementById("checkbox"); // 通讯录删除按钮 WebElement delBtn = ((ChromeDriver) driver).findElement(By.xpath("//*[@id=\"content-header\"]/div/button[2]")); // 删除确认按钮 // WebElement confirmBtn = ((ChromeDriver) driver).findElement(By.cssSelector(".btn.btn-primary.submit ")); WebElement confirmBtn = ((ChromeDriver) driver).findElement(By.xpath("//*[@id=\"del-contacts\"]/div/div[3]/div[1]/button[1]")); System.out.println("confirmBtn=" + confirmBtn); Timer timer = new Timer(); timer.schedule(new TimerTask() { public void run() { // 全选 checkbox.click(); try { // 删除 delBtn.click(); Thread.sleep(1000); // 确认 confirmBtn.click(); } catch (InterruptedException e) { e.printStackTrace(); } } }, 2000, 5000);
注意要点:
第一:根据你所使用的浏览器,我这里使用的chrome驱动,当然你也可以使用Firefox或者ie等等驱动,下载地址为chromedriver.exe驱动下载,注意驱动版本与电脑上浏览器的版本兼容关系
第二:在找元素的时候,有的时候元素只有一个class属性,而且是多个值,中间还有空格,一般我们在javascript中,通过jQuery这么选取:$(".btn.btn-light"),但是如果在selenium中你通过下面这种方式获取就会报错
(1)org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"class name","selector":".btn.btn-light"}:
WebElement button = ((ChromeDriver) driver).findElementByClassName(".btn.btn-light");
(2)接下来我把class属性值中的“.”去掉,改用空格替代,保持页面上class属性值的原样,又报新错误
了org.openqa.selenium.InvalidSelectorException: invalid selector: Compound class names not permitted:
WebElement delBtn1 = ((ChromeDriver) driver).findElementByClassName("btn btn-light");
这是因为selenium的这个api不支持复合属性
(3)幸好selenium支持css选择器,然后我改成下面的
WebElement confirmBtn2 = ((ChromeDriver) driver).findElement(By.cssSelector(".btn.btn-light"));
这次获取button元素没有出错,但是在调用这个元素的click方法时
报错org.openqa.selenium.ElementNotVisibleException: element not visible :
网上说这个错误可能是因为元素选错了,也有可能是这个class属性很多元素都有,所以不唯一;也有可能是页面还没渲染出来,要等待一会;还有可能是这是隐藏元素或遮罩层的元素,反正那个博客分析的挺详细的,你可以慢慢排查,我会在文章下面的参考地址贴出那篇博客;文章建议优先根据元素id来获取元素,没有id就使用xpath路径;尽量不要使用class来获取;
第三:有的人可能不会xpath语法,没关系,打开浏览器控制台,在element标签下,选中你要的元素,鼠标右键,在弹出的菜单中选择“copy”---》“copy xpath”,粘贴到程序中完事,如下图:
第四:selenium再智能,也要通过浏览器操作,之所以要下载chromedriver.exe,运行程序时会弹出chrome浏览器,一切就绪后,千万不要用鼠标去操作页面,一旦动了页面,程序功能就失效了
第五:遇到渲染慢的页面,sleep一下
后来发现采用httpclient模拟浏览器处理比上面好用;在你不知道按钮发送的请求连接情况下用上面selenium,知道的话还是httpclient效率高一些
参考地址:https://blog.csdn.net/BerlinLove/article/details/70053808
https://blog.csdn.net/duzilonglove/article/details/78603956