简介
写过爬虫的朋友一定遇到过这样一个问题:网页的部分内容是由js(ajax)技术生成的,而这部分内容恰恰是我们想要的,并且这个ajax请求的url或者生成的cookie信息我们很难拿到。
普通的爬虫工具例如HttpClient只能模拟http发送请求,我们无法拿到url或者cookie,所以当然也无法拿到动态网页内容;htmlunit具有js渲染的功能,某些场景下使用htmlunit是一个比较合适的选择,但是 htmlunit对于某些复杂js却显得无能为力,关于htmlunit的使用,我们会在另外一篇博客中详细叙述。
Selenium,作为一个Web应用程序测试的工具,功能显然更加强大。Selenium的核心Selenium Core基于JsUnit,完全由 JavaScript编写,因此可运行于任何支持JavaScript的浏览器上。显然,Selenium非常适合解决上述我们提到的动态网页加载问题。
这里我们主要讲一下Selenium如何在java平台上使用、以及一些使用过程中出现的坑。
入门
环境搭建
-
首先我们要准备一些jar包,里面有一些api可供我们使用,具体如下:
commons-codec-1.9.jar commons-collections-3.2.1.jar commons-exec-1.1.jar commons-io-2.4.jar commons-lang3-3.3.2.jar commons-logging-1.1.3.jar cssparser-0.9.14.jar guava-15.0.jar httpclient-4.3.4.jar httpcore-4.3.2.jar httpmime-4.3.3.jar jna-3.4.0.jar phantomjsdriver-1.2.0.jar selenium-api-2.41.0.jar selenium-chrome-driver-2.44.0.jar selenium-firefox-driver-2.44.0.jar selenium-htmlunit-driver-2.44.0.jar selenium-ie-driver-2.44.0.jar selenium-java-2.44.0.jar selenium-remote-driver-2.41.0.jar selenium-safari-driver-2.44.0.jar selenium-support-2.44.0.jar
其中版本是我自己选取,若要使用其他版本,大家可以自己尝试哦。
2. 由于Selenium可以操作各种浏览器进行测试,所以在使用之前我们需要在电脑上安装对应的浏览器。注意,Selenium版本与浏览器版本不一定兼容,以下是FireFox和Chrome具体对应版本:
FireFox:
2.25.0 -> 18
2.30.0 -> 19
2.31.0 -> 20
2.42.2 -> 29
2.44.0 -> 33 (不支持31)
2.53.0 -> 43,46(不支持47)
2.41.0 -> 26(绿色版本)
2.44 -> 32.0-35.0
2.53.0-2.53.6 -> 40.0.3
Chrome:
2.29 -> 56-58
2.28 -> 55-57
2.27 -> 54-56
2.26 -> 53-55
2.25 -> 53-55
2.24 -> 52-54
2.23 -> 51-53
2.22 -> 49-52
2.21 -> 46-50
2.20 -> 43-48
2.19 -> 43-47
2.18 -> 43-46
2.17 -> 42-43
2.13 -> 42-45
2.15 -> 40-43
2.14 -> 39-42
2.13 -> 38-41
2.12 -> 36-40
2.11 -> 36-40
2.10 -> 33-36
2.9 -> 31-34
2.8 -> 30-33
2.7 -> 30-33
2.6 -> 29-32
2.5 -> 29-32
2.4 -> 29-32
- java环境搭建部分此处略过。打开Eclipse,新建Java Project,取名selenium_demo,然后将下载的jar包导入工程。至此,环境搭建完毕。
代码实现
-
使用Selenium新建一个浏览器(这里以火狐浏览器为例,我这里是mac操作系统):
String browserPath = "/Applications/Firefox.app/Contents/MacOS/firefox"; System.setProperty("webdriver.firefox.bin", browserPath); WebDriver driver = new FirefoxDriver();
其中browserPath是火狐浏览器的驱动路径。如果要新建一个PhantomJs浏览器,则代码如下:
String browserPath = "/opt/app/PhantomJS/phantomjs-2.1.1-linux-x86_64/bin/phantomjs";
System.setProperty("phantomjs.binary.path", browserPath);
WebDriver driver = new PhantomJSDriver();
-
为Selenium设置代理:
FireFox:String proxyIp = "10.10.10.1"; int proxyPort = 80; FirefoxProfile profile = new FirefoxProfile(); profile.setPreference("network.proxy.type", 1); profile.setPreference("network.proxy.http", proxyIp); profile.setPreference("network.proxy.http_port", proxyPort); profile.setPreference("network.proxy.ssl", proxyIp); profile.setPreference("network.proxy.ssl_port", proxyPort); WebDriver driver = new FirefoxDriver(profile);
PhantomJs:
DesiredCapabilities desiredCapabilities = DesiredCapabilities.phantomjs();
Proxy proxy = new Proxy();
proxy.setProxyType(org.openqa.selenium.Proxy.ProxyType.MANUAL);
proxy.setAutodetect(false);
String proxyIp = "10.10.10.1";
int proxyPort = 80;
proxy.setHttpProxy(proxyIp + ":" + proxyPort);
desiredCapabilities.setCapability(CapabilityType.PROXY, proxy);
WebDriver driver = new PhantomJSDriver(desiredCapabilities);
-
打开一个url并获取对应的网页源码:
String url = "http://www.baidu.com"; driver.get(url); String pageSource = driver.getPageSource(); System.out.println(pageSource);
-
浏览器窗口最大化:
driver.manage().window().maximize();
-
定位某个元素:
根据ID定位元素: WebElement ele = driver.findElement(By.id("id")); 根据Class定位元素: WebElement ele = driver.findElement(By.className("className")); 根据xpath定位元素: WebElement ele = driver.findElement(By.xpath("xpath"));
-
向表单填数据:
WebElement ele = driver.findElement(By.id("id")); ele.clear(); ele.sendKeys("str");
-
触发元素的点击事件:
WebElement ele = driver.findElement(By.id("id")); ele.click();
一些坑
- 使用find_element_by_xxxx()方法查找元素时,如果元素找不到,不会返回null,而是抛出异常,所以需要自己捕获异常。
- 使用firefox后,很多选项虽然在浏览器中进行了设置,但是通过selenium启动firefox后,设置并没有生效,所以这些设置你需要在代码中添加。
- 使用WebDriver点击Button元素时,如果Button元素其他元素遮住了,或没出现在界面中(比如Button在页面底部,但是屏幕只能显示页面上半部分),使用Click()方法可能无法触发Click事件。