Selenium 是一个用于Web应用程序测试的工具。下面是百度百科对Selenium的介绍:
Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等。这个工具的主要功能包括:测试与浏览器的兼容性——测试你的应用程序看是否能够很好得工作在不同浏览器和操作系统之上。测试系统功能——创建回归测试检验软件功能和用户需求。支持自动录制动作和自动生成 .Net、Java、Perl等不同语言的测试脚本。
这里我们需要使用selenium来方便我们的抓取。平常我们在抓取的时候,需要构造请求,请求中包含参数。但是有些网站为了防止被抓取,有时候会将我们构造请求必需的参数加密,碰到加密参数无法解密或者解密麻烦的时候,就可以使用selenium来帮助我们跳过这些加密的步骤,然后获取这些请求的cookie,就可以继续构造请求进行下一步操作了(如果下一步的请求参数可以获取到)。
下面我们使用chrome浏览器,假设某航司官网登录的那一步请求参数是加密的,无法获取。我们的目标是根据用户的单号跳转到订单详情页面。
在做任务之前需要配置好环境。
- 下载驱动
这里我们使用的是chromedriver.exe。通常还有HtmlUnitDriver和PhantomJSDriver(phantomjs.exe),后面的HtmlUnitDriver适用于页面一步就加载成功的页面,PhantomJSDriver适用于有异步请求的页面(比如有些页面不是一次全部加载完成的,而是要通过多个js或者别的部分加载拼接而成),chromedriver也是适用于这种场景,并且比PhantomJSDriver功能更加强大。这里我们仅仅介绍chrome.exe。
chromedriver.exe (对应谷歌浏览器 版本 67.0.3396.87(正式版本) (64 位),我自己的电脑上chrome版本版本 69.0.3497.100(正式版本) (64 位) 也可以使用这个驱动
不同版本的驱动对应不同版本的chrome,最好让他们对应,防止后面出错。对应的浏览器和驱动版本可以自行百度
2. 添加maven依赖
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.3.1</version>
</dependency>
3. 代码连接驱动
这里封装了一个DriverStrategyFactory,里面只有一个getInstance函数,代码如下:
public static WebDriver getInstance(DriverEnum driverEnum) {
switch (driverEnum) {
case HtmlUnit:
return new HtmlUnitDriverStrategy().getDriver(driverEnum);
case PhantomJS:
return new PhantomJSDriverStrategy().getDriver(driverEnum);
case Chrome:
return new ChromeDriverStrategy().getDriver(driverEnum);
default:
return null;
}
}
这里的DriverEnum就和第一部分提到的驱动有关,下面是这部分代码:
HtmlUnit("HtmlUnitDriver", 1, "HtmlUnit无需设置路径"), PhantomJS("PhantomJSDriver", 2, "driver/phantomjs.exe"), Chrome("ChromeDriver", 3, "driver/chromedriver.exe");
private String name;
private int code;
private String des;
4. 主要代码
String orderNumber = "XXXXXX";
try {
// 获取驱动
WebDriver driver = DriverStrategyFactory.getInstance(DriverEnum.Chrome);
driver.get("http://www.csair.com/cn/index.shtml");
// 点击登录
driver.findElement(By.linkText("登录")).click();
new WebDriverWait(driver, 1);
// 获取用户名
driver.findElement(By.id("userId")).sendKeys("XXXXX");
new WebDriverWait(driver, 3);
// 获取密码
driver.findElement(By.id("passWordPH")).sendKeys("XXXXX");
new WebDriverWait(driver, 1);
// 同意隐私协议
driver.findElement(By.id("loginProtocol")).click();
new WebDriverWait(driver, 1);
// 点击登录
driver.findElement(By.id("mem_btn_login")).click();
//获取cookie
Set<Cookie> cookies = driver.manage().getCookies();
driver.quit();
//创建一个HttpContext对象,用来保存Cookie
HttpClientContext httpClientContext = HttpClientContext.create();
BasicCookieStore basicCookieStore = new BasicCookieStore();
cookies.forEach(cookie -> {
BasicClientCookie clientCookie = new BasicClientCookie(cookie.getName(), cookie.getValue());
clientCookie.setDomain(cookie.getDomain());
clientCookie.setPath(cookie.getPath());
basicCookieStore.addCookie(clientCookie);
});
httpClientContext.setCookieStore(basicCookieStore);
CloseableHttpResponse execute = HttpClients.createDefault().
execute(new HttpGet("http://b2c.csair.com/B2C40/modules/ordernew/orderDetail.jsp?" +
"orderno="+orderNumber+"&time="+System.currentTimeMillis()), httpClientContext);
String index = EntityUtils.toString(execute.getEntity());
System.out.println(index);
} catch (Exception e) {
e.printStackTrace();
}
5. 注意事项
- 上面在运行过程中,会出现找不到元素的错误(比如:org.openqa.selenium.WebDriverException: unknown error: cannot focus element),在排除了元素获取方式错误的基础上,出现这种情况很可能的原因是因为页面还未加载完成,因此找不到对应的元素。这个时候,我们可以增加等到时间,等相应部分加载完成再来获取元素。如果你仅仅是想看效果,就可以直接调试,等看到页面相应部分加载成功之后再执行下一步。
- driver.findElement(By.id("passWordPH")).sendKeys("XXXXX");
这个是获取密码input栏的代码,这个By后面的方法有多种,在chrome中,按了F12之后,可以直接获取这个地方的xpath。
3. By后面的方法:
- By id
- By Class Name
- By Tag Name 根据元素标签名查找。
- By Name 查找 name 属性匹配的表单元素。
- By Link Text 查找链接文字匹配的链接元素。
- By Partial Link Text 查找链接文字部分匹配的链接元素。
- By CSS
官网链接:https://wizardforcel.gitbooks.io/selenium-doc/content/official-site/selenium-web-driver.html