JSOUP 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。 官网
jsoup实现了WHATWG HTML5规范,并将 HTML 解析为与现代浏览器相同的 DOM。
一般在java平台上,我们会使用apache httpclient作为http客户端,用于发送 http 请求,并对响应进行处理。比如可以使用http客户端与第三方服务(如sso服务)进行集成,当然还可以爬取网上的数据等。okhttp与httpclient类似,也是一个http客户端,提供了对 http/2 和 spdy 的支持,并提供了连接池,gzip 压缩和 http 响应缓存功能;
okhttp是目前非常火的网络库,它有以下特性:
1.支持http/2,允许所有同一个主机地址的请求共享同一个socket连接
2.连接池减少请求延时
3.透明的gzip压缩减少响应数据的大小
4.缓存响应内容,避免一些完全重复的请求
<!-- 爬虫-解析html页面-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.10.0</version>
</dependency>
爬取华北地区,所有省市,一个星期全部的天气
按下f12,就就能查看html的结构进行分析具体该怎么爬,然后找到对应的标签,之后根据标签的位置写出css选择器
具体详情代码如下:
//拿到网页的xml
String doc = OkHttpUtils.builder()
.url("http://www.weather.com.cn/textFC/hb.shtml")
.get()
.sync();
//时间,省市,城市,天气现象
StringBuilder stringBuilder0=new StringBuilder();
//标题
StringBuilder stringBuilder = new StringBuilder("时间,省市,城市,天气现象,风向风力,最高气温,天气现象,风向风力,最低气温");
stringBuilder0.append(stringBuilder).append("\n");
Document document = Jsoup.parse(doc);//将页面转换为Document
//使用css 选择器
Elements selecttop = document.select(".day_tabs li");
//拿到数据列表
Elements select = document.select(".conMidtab");
for (int i1 = 0; i1 < selecttop.size(); i1++) {
Element element = selecttop.get(i1);
String text = element.text();
//进行数据清洗,取出时间
String time = PatternCommon.cutPatternStr(text, "[\\u4e00-\\u9fa5]*\\((\\S*)\\)", 1).get(1);
//取和实际对应的列表
Element element1 = select.get(i1);
Elements midtab = element1.select(".conMidtab2");
for (int i = 0; i < midtab.size(); i++) {
StringBuilder stringBuilder1 = new StringBuilder();
//时间
stringBuilder1.append(time).append(",");
Element element2 = midtab.get(i);
//拿到所有的行
Elements trs = element2.select("table tr");
//拿到省市
Elements select2 = trs.select(".rowspan");
stringBuilder1.append(select2.text()).append(",");
//跳过前3行从第4行开始读取
for (int i2 = 3; i2 < trs.size()-1; i2++) {
StringBuilder stringBuilder2 = new StringBuilder();
Element element3 = trs.get(i2);
//拿到行下所有列 城市,天气现象,风向风力,最高气温,天气现象,风向风力,最低气温
Elements td = element3.select("td");
for (int i3 = 0; i3 < td.size(); i3++) {
Element element4 = td.get(i3);
if(i3 == td.size()-2){
//最后一个不需要逗号
stringBuilder2.append(element4.text());
break;
}
stringBuilder2.append(element4.text()).append(",");
}
StringBuilder stringBuilder3 = new StringBuilder();
stringBuilder3.append(stringBuilder1).append(stringBuilder2);
stringBuilder0.append(stringBuilder3).append("\n");
}
}
}
//将内容按行写入到csv文件中
String absoluteFilePathAndCreate = ResourceFileUtil.getAbsoluteFileOrDirPathAndCreate("/weather.csv");
ReadWriteFileUtils.writeStrCover(new File(absoluteFilePathAndCreate),stringBuilder0.toString());
注意: 下面的参数名称query和cssQuery 就是css选择器
Jsoup:
Document :
Elements:
Element:
高并发爬取使用OkHttp,因为内部做了很多的优化,在爬取的频率很快和多的时候效率是非常好的, JSOUP内部提供了请求方式但效率没有OkHttp高,下面是封装好的直接就可以用,但是只支持返回xml/html页面否则报错,所以尽量使用OkHttp比较灵活,效率还好
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
/**
* 简要描述
* @Author: huanmin
* @Date: 2022/7/17 18:47
* @Version: 1.0
* @Description: 文件作用详细描述....
* Document execute = JsoupConnect.build("http://www.weather.com.cn/textFC/hb.shtml").getExecute();
*/
public class JsoupConnect {
private final Connection connect;
public static JsoupConnect build(String url) {
return new JsoupConnect(url);
}
public Document getExecute() {
Document document = null;
try {
document = connect.get();
} catch (IOException e) {
e.printStackTrace();
}
return document;
}
public Document postExecute() {
Document document = null;
try {
document = connect.get();
} catch (IOException e) {
e.printStackTrace();
}
return document;
}
public JsoupConnect(String url) {
Connection connect1 = Jsoup.connect(url);
TrustManager[] trustManagers = buildTrustManagers();
connect1.timeout(30000);//超时时间 30秒
connect1.sslSocketFactory(createSSLSocketFactory(trustManagers));
connect1.userAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36");
this.connect =connect1;
}
//设置代理
// Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8080));
public JsoupConnect proxy(Proxy.Type type,String ip,int port) {
Proxy proxy = new Proxy(type, new InetSocketAddress(ip, port));
this.connect.proxy(proxy);
return this;
}
public JsoupConnect cookie(String name, String value){
connect.cookie(name,value);
return this;
}
public JsoupConnect header(String name, String value){
connect.header(name,value);
return this;
}
//get 和 post
public JsoupConnect addParameter(String key, String value){
connect.data(key,value);
return this;
}
/**
* 生成安全套接字工厂,用于https请求的证书跳过
*
* @return
*/
private SSLSocketFactory createSSLSocketFactory(TrustManager[] trustAllCerts) {
SSLSocketFactory ssfFactory = null;
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
ssfFactory = sc.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
}
return ssfFactory;
}
private TrustManager[] buildTrustManagers() {
return new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
}
}
User-Agent是Http协议中的一部分,属于头域的组成部分,User Agent也简称UA。用较为普通的一点来说,是一种向访问网站提供你所使用的浏览器类型、操作系统及版本、CPU 类型、浏览器渲染引擎、浏览器语言、浏览器插件等信息的标识。UA字符串在每次浏览器 HTTP 请求时发送到服务器! ,所以大批量爬虫的时候不要一直使用同一个User-Agent, 要多切换切换,不然就会识别到你了给你拉黑
可以利用随机的方式来获取下面的内容
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50
Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50
Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;
Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;
Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11
Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)
Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5
Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5
Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5
Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10
UCWEB7.0.2.37/28/999
Openwave/ UCWEB7.0.2.37/28/999
Mozilla/4.0 (compatible; MSIE 6.0; ) Opera/UCWEB7.0.2.37/28/999
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import com.google.common.io.Resources;
import java.io.File;
import java.net.URL;
import java.util.Collections;
import java.util.List;
/**
* 简要描述
*
* @Author: huanmin
* @Date: 2022/7/17 19:51
* @Version: 1.0
* @Description: 文件作用详细描述....
*/
public class UserAgent {
private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36";
private static List<String> userAgents = null;
static {
URL url = Resources.getResource("userAgents");
if(url != null) {
File file = new File(url.getPath());
try {
userAgents = Files.readLines(file, Charsets.UTF_8);
} catch(Exception ex) {}
}
}
public static String getUserAgent() {
if(userAgents == null || userAgents.size() == 0) {
return DEFAULT_USER_AGENT;
}
Collections.shuffle(userAgents);
return userAgents.get(0);
}
}
后台爬虫在大行其道的时候,也有着些许棘手的、到目前也没有什么好的解决方案问题,而归根结底,这些问题的根本原因是由于后台爬虫的先天不足导致,在正式讨论之前,我们先思考一个问题,“爬虫和浏览器有什么异同?”
相同点: 本质上都是通过http/https协议请求互联网数据
不同点:
了解了这些,我们再来看看后台面临的问题
问题一:交互问题
有些网页往往需要和用户进行一些交互,进而才能走到下一步,比如输入一个验证码,拖动一个滑块,选几个汉字。网站之所以这么做,很多时候都是为了验证访问者到底是人还是机器。
而爬虫程序遇到这种情况很难处理,传统的简单图片验证码可以通过图形处理算法读出内容,但是随着各种各样,花样百出,人神共愤的、变态的验证码越来越多(尤其是买火车票时,分分钟都想爆粗口),这个问题就越来越严重。
问题二:Javascript 解析问题
如前文所述,javascript可以动态生成dom。目前大多数网页属于动态网页**(内容由javascript动态填充),尤其是在移动端,SPA/PWA应用越来越流行,网页中大多数有用的数据都是通过ajax/fetch动态获**取后然后再由js填充到网页dom树中,单纯的html静态页面中有用的数据很少。
目前主要应对的方案就是对于js ajax/fetch请求直接请求ajax/fetch的url ,但是还有一些ajax的请求参数会依赖一段javascript动态生成,比如一个请求签名,再比如用户登陆时对密码的加密等等。
如果一昧的去用后台脚本去干javascript本来做的事,这就要清楚的理解原网页代码逻辑,而这不仅非常麻烦,而且会使你的爬取代码异常庞大臃肿,但是,更致命的是,有些javascript可以做的事爬虫程序是很难甚至是不能模仿的,比如有些网站使用拖动滑块到某个位置的验证码机制,这就很难再爬虫中去模仿。
其实,总结一些,这些弊端归根结底,是因为爬虫程序并非是浏览器,没有javascript解析引擎所致。针对这个问题,目前主要的应对策略就是在爬虫中引入Javascript 引擎,如PhantomJS,但是又有着明显的弊端,如服务器同时有多个爬取任务时,资源占用太大。
还有就是,这些 无窗口的javascript引擎很多时候使用起来并不能像在浏览器环境中一样,页面内部发生跳转时,会导致流程很难控制。
问题三:IP限制
这是目前对后台爬虫中最致命的。网站的防火墙会对某个固定ip在某段时间内请求的次数做限制,如果没有超过上线则正常返回数据,超过了,则拒绝请求,如qq 邮箱。
值得说明的是,ip限制有时并非是专门为了针对爬虫的,而大多数时候是出于网站安全原因针对DOS攻击的防御措施。后台爬取时机器和ip有限,很容易达到上线而导致请求被拒绝。目前主要的应对方案是使用代理,这样一来ip的数量就会多一些,但代理ip需要花钱
Selenium 是一组软件工具集,每一个都有不同的方法来支持测试自动化。大多数使用 Selenium 的QA工程师只关注一两个最能满足他们的项目需求的工具上。然而,学习所有的工具你将有更多选择来解决不同类型的测试自动化问题。这一整套工具具备丰富的测试功能,很好的契合了测试各种类型的网站应用的需要。这些操作非常灵活,有多种选择来定位 UI 元素,同时将预期的测试结果和实际的行为进行比较。Selenium 一个最关键的特性是支持在多浏览器平台上进行测试。
Chrome和Firefox相继推出了无头浏览器模式,由于这些大厂的加入phantomjs的用户量渐渐减少,新版的selenium已经不再支持phantomjs
chrome_options = Options()
chrome_options.add_argument('--headless') //设置无头浏览器模式
chrome_options.add_argument('--disable-gpu')
在实例化一个浏览器对象的时候,带上配置driver = webdriver.Chrome(chrome_options=chrome_options)
Chromedriver下载地址:
http://chromedriver.storage.googleapis.com/index.html
http://npm.taobao.org/mirrors/chromedriver/
两个地址都可以下载,根据自己的chrome浏览器的版本选择下载即可(一定要和自己游览器版本一致,否则没法使用)
查看浏览器版本 ↓
没找到103.0.5060.114那么下载你当前游览器版本的临近最新版就行
下载解压后把exe文件复制到浏览器的安装目录下:C:\Program Files (x86)\Google\Chrome\Application(要根据自己实际安装目录)
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<!-- 如果使用的是boot那么取消version,会自动继承版本,不然会报错,-->
<!-- <version>4.0.0</version>-->
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>22.0</version>
</dependency>
工具类
package com.reptile;
import lombok.SneakyThrows;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.util.concurrent.TimeUnit;
/**
* 简要描述
*
* @Author: huanmin
* @Date: 2022/7/18 17:27
* @Version: 1.0
* @Description: 文件作用详细描述....
*
*/
public class ChromeDriverUtil {
private ChromeDriver driver;
public ChromeDriverUtil(String path) {
System.setProperty("webdriver.chrome.driver",path);
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless"); //无浏览器模式
options.addArguments("--no-sandbox");// 为了让root用户也能执行
// 优化参数
options.addArguments("--disable-dev-shm-usage");
options.addArguments("blink-settings=imagesEnabled=false");
options.addArguments("--disable-gpu");
//随机设置请求头
options.addArguments("--user-agent="+ UserAgent.getUserAgent());
// options.setProxy(proxy()); //设置代理
driver = new ChromeDriver(options);//实例化
driver.manage().window().maximize(); //最大化窗口, 防止有些元素被隐藏
//设置全局等待时间, 指定驱动程序在搜索不立即存在的元素时应等待的时间量 ,超时后就报错NoTouchElementException
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
}
public static ChromeDriverUtil build(String path){
return new ChromeDriverUtil(path);
}
public ChromeDriver getDriver() {
return driver;
}
public void to(String url){
driver.navigate().to(url);
}
//退到上一个页面 ,前提必须前进了一个页面才能回退
public void back(){
driver.navigate().back();
}
//指前进到下一个页面 ,前提是必须后退后才能前进
public void forward(){
driver.navigate().forward();
}
//刷新当前页面
public void refresh(){
driver.navigate().refresh();
}
//睡眠多少毫秒
@SneakyThrows
public void sleep(long ms){
Thread.sleep(ms);
}
//结束当前驱动 ,也就是自动化结束
public void quit(){
driver.quit();
}
// 显示等待 在某些AJAX请求进行渲染的页面,可能我们不能立即获取到渲染后的页面,那么我们就需要进行等待
public WebElement wait(int seconds, ExpectedCondition<WebElement> expectedCondition ){
WebDriverWait webDriverWait = new WebDriverWait(driver, seconds);
WebElement until = webDriverWait.until(expectedCondition);
return until;
}
//自行扩展, 从接口中读取,或者从文件中读取都行
private Proxy proxy(){
String prox = "101.200.127.149:"+3129;
Proxy p = new Proxy();
p.setHttpProxy(prox);//http
// p.setFtpProxy(prox); //ftp
// p.setSslProxy(prox);//ssl
// p.setSocksProxy(prox); //SOCKS
// p.setSocksUsername("");
// p.setSocksPassword("");
return p;
}
}
操作
public static void main(String[] args) {
ChromeDriverUtil build = ChromeDriverUtil.build("D:\\常用资源\\chromedriver.exe");
build.to("http://www.weather.com.cn/textFC/hb.shtml");
WebElement a = build.getDriver().findElementByLinkText("预报");
System.out.println(a.getText());
}
待整理
String href = "https://www.csdn.net";
PhantomJSDriver driver = create();
//获取csdn主页
driver.get(href);
//定位到Java按钮
WebElement java = driver.findElementByLinkText("Java");
//执行点击
java.click();
//用于定位到Java模块列表
WebElement feedlist_id = driver.findElementById("feedlist_id");
List<WebElement> liList = feedlist_id.findElements(By.className("clearfix"));
//循环遍历li
for (WebElement li : liList) {
WebElement title = li.findElement(By.className("title"));
WebElement a = title.findElement(By.tagName("a"));
System.out.println("标题:" + a.getText() + " 链接:" + a.getAttribute("href"));
}
常用的如下:
//通过id的方式获取元素
public WebElement findElementById(String using)
//通过链接文本方式获取单个元素
public WebElement findElementByLinkText(String using)
//通过标签名方式获取单个元素
public WebElement findElementByTagName(String using)
//通过标签名方式获取多个元素
public List<WebElement> findElementsByTagName(String using)
//通过name属性方式获取单个元素
public WebElement findElementByName(String using)
//通过name属性方式获取多个元素
public List<WebElement> findElementsByName(String using)
//通过类名方式获取单个元素
public WebElement findElementByClassName(String using)
//通过类名方式获取多个元素
public List<WebElement> findElementsByClassName(String using)
//通过css选择器方式获取单个元素
public WebElement findElementByCssSelector(String using)
//通过css选择器方式获取多个元素
public List<WebElement> findElementsByCssSelector(String using)
//通过xpath方式获取单个元素
public WebElement findElementByXPath(String using)
//通过xpath方式获取多个元素
public List<WebElement> findElementsByXPath(String using)
void click(); //触发点击事件
String getAttribute(String name) //获取属性值
String getText() //标签文本
element.getAttribute("value") //输入框value值
clear()用于清空元素的内容
sendKeys(CharSequence... keysToSend)用于给输入框赋值
选择下拉框元素
Select select = new Select(driver.findElementById("select"));
//通过索引选择
select.selectByIndex(1);
//通过value值获取
select.selectByValue("zhangsan")
//通过文本值获取
select.selectByVisibleText("张三");
单选和复选
driver.findElementById("radio"); radio.click(); //单选按钮
复选框其实和单选按钮一样,都是定位元素,点击元素,在选择元素之前,我们可以通过isSelected()来判断元素是否被选择,isEnabled()来判断元素是否被禁用。
表单提交
WebElement form = driver.findElementById("form");
//只能用于表单提交
form.submit();
在某些时候,有些网站在执行的时候可能会打开另外一个窗口,这个时候,如果我们想要回到原先的窗口,应该怎么办呢?
//获取窗口的句柄
String windowHandle = driver.getWindowHandle();
//另外一个窗口执行...
//另外一个窗口执行结束后,我们可以通过switchTo()去返回到原先窗口
driver.switchTo().window(windowHandle);
在某些AJAX请求进行渲染的页面,可能我们不能立即获取到渲染后的页面,那么我们就需要进行等待,这里支持两种类型的等待方式:
隐形等待
//针对全局设置,所有命令的超时时间都是10s,如果超过等待时间,则抛出异常。
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
显示等待
WebDriverWait webDriverWait = new WebDriverWait(driver, 10);
webDriverWait.until(new ExpectedCondition<WebElement>() {
@Override
public WebElement apply(WebDriver webDriver) {
return webDriver.findElement(By.id("toolber-keyword"));
}
});
等待某个元素,最大等待10s,默认0.5s为搜索间隔,搜索到元素则停止等待。在使用获取数据的网站中,使用该方式十分方便,若10s都没有结果,那么则认定系统出现故障。
某些时候,我们可能通过getText()的方式获取标签的文本值并不会生效 ,phantomjs能够执行js语句,这可是一个好方式,我们可以通过写js语句来解决大部分问题。 执行js语句Object executeScript(String script, Object... args);
该方法可以供我们执行js语句,script代表我们的js语句,args代表散列值,接受参数使用arguments[0]依次来接受。示例如下:
假设我们想要获取某个标签的文本值
第一种方式:driver.executeScript("document.getElementById('blogClick').innerText")
第二种方式:
WebElement blogClick = driver.findElementById("blogClick");
driver.executeScript("arguments[0].innerText",blogClick);
采用爬虫处理业务,如果是静态网页还比较好处理,如果是AJAX+JS渲染的动态页面,在爬取的过程中,会遇到各种各样的坑,就需要耐心研究了,到底怎么才能获取到
点赞 -收藏-关注-便于以后复习和收到最新内容有其他问题在评论区讨论-或者私信我-收到会在第一时间回复感谢,配合,希望我的努力对你有帮助^_^免责声明:本文部分素材来源于网络,版权归原创者所有,如存在文章/图片/音视频等使用不当的情况,请随时私信联系我。
暑期编程PK赛
得CSDN机械键盘等精美礼品!
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://huanmin.blog.csdn.net/article/details/125831123
内容来源于网络,如有侵权,请联系作者删除!