selenium的使用

简介

Selenium 百度百科

Selenium是一个用于Web应用程序测试的工具, 支持各种浏览器, 一般都是用作自动化测试的, 但是如果配合上代理, 可以实现爬虫的效果。

环境搭建

selenium 成功运行, 必须要有 webdriver + 浏览器, 并且2者的版本号要一致才能使用, 安装chrome浏览器, 把webdriver解压到磁盘中。

chromedriver 淘宝镜像

可以直接使用下面的

https://soscdn.lanzoui.com/b015e2c2h
密码:8ot9

如何使用

maven

<dependency>
	<groupId>org.seleniumhq.selenium</groupId>
	<artifactId>selenium-chrome-driver</artifactId>
	<version>3.141.59</version>
</dependency>
<dependency>
	<groupId>org.seleniumhq.selenium</groupId>
	<artifactId>selenium-server</artifactId>
	<version>3.141.59</version>
</dependency>
<dependency>
	<groupId>org.seleniumhq.selenium</groupId>
	<artifactId>selenium-java</artifactId>
	<version>3.141.59</version>
</dependency>

简单示例

实现点击下面的a标签

  • 页面-a.html
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>a标签</title>
  </head>
  <body>
   <a onclick="javascript:(console.log('a'))">点我</a>
  </body>
</html>

  • 代码
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class Taga {
	public static void main(String[] args) throws Exception {
		// 后面的目录就是上面解压的drvier的目录
		System.setProperty("webdriver.chrome.driver", "D:\\xiaodoubi\\selemium\\chromedriver.exe");
		
		WebDriver driver = new ChromeDriver();
		// 打开网页(把页面放到nginx中)
		driver.get("http://127.0.0.1/a.html");
		// 休眠的时候, 按F12, 打开浏览器控制台-console
		Thread.sleep(5000);
		// 选择
		for (int i = 0; i < 4; i++) {
			driver.findElement(By.tagName("a")).click();
			Thread.sleep(2000);
		}
		// 关闭浏览器
		driver.close();
	}
}

具体api讲解

WebDriver

方法 含义 备注
get(String url) 打开url
getCurrentUrl() 获取当前url
getTitle() 获取标题
findElements(By by) 获取元素
findElement(By by) 获取元素
getPageSource() 获取源码
close() 关闭 Close the current window, quitting the browser if it's the last window currently open.
quit() 退出 Quits this driver, closing every associated window.
getWindowHandles() 获取浏览器窗口名称
getWindowHandle() 获取浏览器窗口名称
switchTo() 切换
navigate() 导航条 返回, 下一步, 刷新, 跳到其他链接等等
manage() 浏览器的控制 cookie的操作, 窗口大小的控制等等
  • 代码
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

public class WebDriverTest {

	public static void main(String[] args) {
		System.setProperty("webdriver.chrome.driver", "D:\\liumq\\selemium\\chromedriver.exe");

		WebDriver driver = new ChromeDriver();
		// 打开网页(把页面放到nginx中)
		driver.get("http://www.baidu.com/");

		// 获取当前url
		System.out.println("---------------------------------------------");
		System.out.println(driver.getCurrentUrl());

		// 获取标题
		System.out.println("---------------------------------------------");
		System.out.println(driver.getTitle());

		// 获取元素
		System.out.println("---------------------------------------------");
		WebElement input = driver.findElement(By.id("su"));
		System.out.println(input.getAttribute("value"));

		// 获取元素
		System.out.println("---------------------------------------------");
		List<WebElement> inputs = driver.findElements(By.tagName("input"));
		for (WebElement webElement : inputs) {
			System.out.println(webElement.getAttribute("value"));
			break;
		}

		// 获取源代码
		System.out.println("---------------------------------------------");
//		System.out.println(driver.getPageSource());

		// 获取窗口
		// 这边模拟了一次搜索点击(后面会细讲)
		System.out.println("---------------------------------------------");
		driver.findElement(By.id("kw")).sendKeys("selenium");
		driver.findElement(By.id("su")).click();
		for (int i = 1; i < 5; i++) {
			driver.findElement(By.id(String.valueOf(i))).findElement(By.tagName("a")).click();
		}
		String windowHandle = driver.getWindowHandle();
		System.out.println(windowHandle);

		driver.getWindowHandles().forEach(System.out::println);

		// 窗口切换
		driver.getWindowHandles().forEach(s->{
			driver.switchTo().window(s);
			try {
				Thread.sleep(3000);
			} catch (Exception e) {
			}
		});
		
		// 导航
		driver.navigate().to("http://360.cn/");
		
		// 浏览器的控制
		driver.manage().window().maximize();
		
		// 上面点开了多个窗口, 就明白了close和quit的区别
//		 driver.close();
		driver.quit();
	}

}

控件的定位

推荐使用css选择器, 对于有爬虫开发经验的来说, 太方便了

By.cssSelector("")

主要控件的操作

input-输入框

radio-单选框

checkbox-复选框

Select-下拉框

键盘输入

鼠标点击

  • html
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>下拉框</title>
  </head>
  <body>
	
	<div>
		<p>输入框</p>
		<input type="text" id="ipt"></input>
	</div>
	
	<div>
		<p>单选框</p>
		<input type="radio" checked value="北京" name="city>" />北京
		<input type="radio" value="上海" name="city>" />上海
		<input type="radio" value="广州" name="city>" />广州
		<input type="radio" value="深圳" name="city>" />深圳
	</div>
	
	
	 <div>
        <p>多选项</p>
        <input type="checkbox" value="羽毛球" name="aihao>" />羽毛球
        <input type="checkbox" value="乒乓球" name="aihao>" />乒乓球
        <input type="checkbox" checked value="足球" name="aihao>" />足球
        <input type="checkbox" value="篮球" name="aihao>" />篮球
    </div>
	
	<div>
	<p>下拉框</p>
    <select class="ppaf-select">
      <option value="AUD">AUD</option>
      <option value="BRL">BRL</option>
      <option value="CAD">CAD</option>
      <option value="CHF">CHF</option>
      <option value="CZK">CZK</option>
      <option value="DKK">DKK</option>
      <option value="EUR">EUR</option>
      <option value="GBP">GBP</option>
      <option value="HKD">HKD</option>
      <option value="HUF">HUF</option>
      <option value="ILS">ILS</option>
      <option value="JPY">JPY</option>
      <option value="MXN">MXN</option>
      <option value="MYR">MYR</option>
      <option value="NOK">NOK</option>
      <option value="NZD">NZD</option>
      <option value="PHP">PHP</option>
      <option value="PLN">PLN</option>
      <option value="RUB">RUB</option>
      <option value="SEK">SEK</option>
      <option value="SGD">SGD</option>
      <option value="THB">THB</option>
      <option value="TRY">TRY</option>
      <option value="TWD">TWD</option>
      <option value="USD">USD</option>
    </select>
	</div>
	
	<div>
		<button id="btn" onclick="javascript:(alert('点我了'))">点我</button>
	</div>
  </body>
</html>
  • 代码
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
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 TagTest {
    public static void main(String[] args) throws AWTException {

		System.setProperty("webdriver.chrome.driver", "D:\\liumq\\selemium\\chromedriver.exe");

		WebDriver driver = new ChromeDriver();
		// 打开网页(把页面放到nginx中)
		driver.get("http://172.18.254.33:7766/html/tags.html");

		// 输入框
		driver.findElement(By.id("ipt")).sendKeys("小逗比");

		// 单选框
		List<WebElement> radios = driver.findElements(By.cssSelector("input[type=radio]"));
		for (WebElement webElement : radios) {
			String value = webElement.getAttribute("value");
			if (value.equals("上海")) {
				webElement.click();
			}
		}

		// 复选框 取消足球, 选择乒乓球, 羽毛球
		List<WebElement> checkbox = driver.findElements(By.cssSelector("input[type=checkbox]"));
		for (WebElement webElement : checkbox) {
			String value = webElement.getAttribute("value");
			System.out.println(value);
			switch (value) {
			case "足球":
				if (webElement.isSelected()) {
					webElement.click();
				}
				break;
			case "羽毛球":
			case "乒乓球":
				if (!webElement.isSelected()) {
					System.out.println(value);
					webElement.click();
				}
				break;
			default:
				break;
			}
		}

		// 下拉框 选择PHP
		Select select = new Select(driver.findElement(By.cssSelector(".ppaf-select")));
		select.selectByValue("PHP");

		// 按键输入
		WebElement findElement = driver.findElement(By.id("ipt"));
		findElement.click();
		// method1: actions 推荐
		Actions actions = new Actions(driver);
		actions.sendKeys("a").keyDown(Keys.SHIFT).sendKeys("a").keyUp(Keys.SHIFT).build().perform();
		// method2: robot
		Robot robot = new Robot();
		robot.keyPress(KeyEvent.VK_B);
		robot.keyRelease(KeyEvent.VK_B);
		robot.keyPress(KeyEvent.VK_SHIFT);
		robot.keyPress(KeyEvent.VK_B);
		robot.keyRelease(KeyEvent.VK_B);
		robot.keyRelease(KeyEvent.VK_SHIFT);
		
		
		// 鼠标点击
		actions.moveToElement(By.id("btn").findElement(driver)).click().build().perform();
	}
}

启动参数配置

Selenium 启动参数设置 ChromeDriver

ChromeDriver

上面我们使用的selenium接口中的WebDriver, 如果我们使用具体对应的浏览器的Driver, 我们发现有了好多花式操作。(简单举例说明)

  • 运行js脚本(神器)
  • 操作LocalStorage
public static void main(String[] args) {
	System.setProperty("webdriver.chrome.driver", "D:\\liumq\\selemium\\chromedriver.exe");
	
	WebDriver driver = new ChromeDriver();
	// 打开网页(把页面放到nginx中)
	driver.get("http://172.18.254.33:7766/html/tags.html");
	
	if(driver instanceof ChromeDriver){
		ChromeDriver cdriver = (ChromeDriver)driver;
		// 运行js脚本, 这个是神器(一些非常不能实现的都可以使用js脚本来实现)
		cdriver.executeScript("alert('aa')", "");
			
		// 获取以及设置存储数据
		LocalStorage localStorage = cdriver.getLocalStorage();
		localStorage.setItem("a", "a");
		System.out.println(localStorage.getItem("a"));

	}
}

超时设置

一旦由于网络原因,或者其他原因, 页面长时间未加载出来, 我们发现就会报控件没有找到错误, 我们需要更好的解决此问题,让程序加载出来

  • 方法1
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
  • 方法2
WebDriverWait webDriverWait = new WebDriverWait(driver, 20);
WebElement element = webDriverWait.until(ExpectedConditions.presenceOfElementLocated(By.id("")));
  • 方法3

我们可以通过try, 不过异常实现一直重试, 就是我们可以直接控制重试时间和次数,

class Continue{
	public static void find(Runnable call) {
		// 进入我的首页
		while (true) {
			try {
				Thread.sleep(1000);
				call.run();
				break;
			} catch (Exception e) {
				System.out.println("未找到");
			}
		}
	}
}

// 选择
Continue.run(() -> {
    Select select = new Select(driver.findElement(By.cssSelector(".ppaf-select")));
    select.selectByValue("PHP");
});