Java爬虫系列四:使用selenium-java爬取js异步请求的数据
在之前的系列文章中介绍了如何使用httpclient抓取页面html以及如何用jsoup分析html源文件内容得到我们想要的数据,但是有时候通过这两种方式不能正常抓取到我们想要的数据,比如看如下例子。
1.需求场景:
想要抓取股票的最新价格,页面F12信息如下:

按照前面的方式,爬取的代码如下:
/**
* @description: 爬取股票的最新股价
* @author: JAVA开发老菜鸟
* @date: 2021-10-16 21:47
*/
public class StockPriceSpider {
Logger logger = LoggerFactory.getLogger(this.getClass());
public static void main(String[] args) {
StockPriceSpider stockPriceSpider = new StockPriceSpider();
String html = stockPriceSpider.httpClientProcess();
stockPriceSpider.jsoupProcess(html);
}
private String httpClientProcess() {
String html = "";
String uri = "http://quote.eastmoney.com/sh600036.html";
//1.生成httpclient,相当于该打开一个浏览器
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
//2.创建get请求,相当于在浏览器地址栏输入 网址
HttpGet request = new HttpGet(uri);
try {
request.setHeader("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36");
request.setHeader("accept", "application/json, text/javascript, */*; q=0.01");
// HttpHost proxy = new HttpHost("3.211.17.212", 80);
// RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
// request.setConfig(config);
//3.执行get请求,相当于在输入地址栏后敲回车键
response = httpClient.execute(request);
//4.判断响应状态为200,进行处理
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
//5.获取响应内容
HttpEntity httpEntity = response.getEntity();
html = EntityUtils.toString(httpEntity, "utf-8");
logger.info("访问{} 成功,返回页面数据{}", uri, html);
} else {
//如果返回状态不是200,比如404(页面不存在)等,根据情况做处理,这里略
logger.info("访问{},返回状态不是200", uri);
logger.info(EntityUtils.toString(response.getEntity(), "utf-8"));
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//6.关闭
HttpClientUtils.closeQuietly(response);
HttpClientUtils.closeQuietly(httpClient);
}
return html;
}
private void jsoupProcess(String html) {
Document document = Jsoup.parse(html);
Element price = document.getElementById("price9");
logger.info("股价为:>>> {}", price.text());
}
}
运行结果:

纳尼,股价为"-" ?不可能。
之所以爬不到正确的结果,是因为这个值在网站上是通过异步加载渲染的,因此不能正常获取。
2.java爬取异步加载的数据的方法
那如何爬取异步加载的数据呢?通常有两种做法:
2.1内置浏览器内核
内置浏览器就是在抓取的程序中启动一个浏览器内核,使我们获取到 js 渲染后的页面就和静态页面一样。常用的内核有
- Selenium
- PhantomJs
- HtmlUnit
这里我选了Selenium,它是一个模拟浏览器,是进行自动化测试的工具,它提供一组 API 可以与真实的浏览器内核交互。当然,爬虫也可以用它。
具体做法如下:
- 引入pom依赖
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
配置对应浏览器的驱动
要使用selenium,需要下载浏览器的驱动,根据不同的浏览器要下载的驱动程序也不一样,下载地址为:https://npm.taobao.org/mirrors/chromedriver/
我用的是谷歌浏览器,因此下载了对应版本的windows和linux驱动。


下载后需要配置进java环境变量里面,指定驱动的目录:
System.getProperties().setProperty("webdriver.chrome.driver", "F:/download/chromedriver_win32_1/chromedriver.exe");
代码实现:
Logger logger = LoggerFactory.getLogger(this.getClass()); public static void main(String[] args) { StockPriceSpider stockPriceSpider = new StockPriceSpider();
stockPriceSpider.seleniumProcess();
} private void seleniumProcess() { String uri = "http://quote.eastmoney.com/sh600036.html"; // 设置 chromedirver 的存放位置
System.getProperties().setProperty("webdriver.chrome.driver", "F:/download/chromedriver_win32_1/chromedriver.exe"); // 设置浏览器参数
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.addArguments("--no-sandbox");//禁用沙箱
chromeOptions.addArguments("--disable-dev-shm-usage");//禁用开发者shm
chromeOptions.addArguments("--headless"); //无头浏览器,这样不会打开浏览器窗口
WebDriver webDriver = new ChromeDriver(chromeOptions); webDriver.get(uri);
WebElement webElements = webDriver.findElement(By.id("price9"));
String stockPrice = webElements.getText();
logger.info("最新股价为 >>> {}", stockPrice);
webDriver.close();
}
执行结果:

爬取成功!
2.2反向解析法
反向解析法就是通过F12查找到 Ajax 异步获取数据的链接,直接调用该链接得到json结果,然后直接解析json结果获取想要的数据。
这个方法的关键就在于找到这个Ajax链接。这种方式我没有去研究,感兴趣的可以百度下。这里略。
3.结束语
以上即为如何通过selenium-java爬取异步加载的数据的方法。通过本方法,我写了一个小工具:
持仓市值通知系统,他会每日根据自己的持仓配置,自动计算账户总市值,并邮件通知到指定邮箱。
用到的技术如下:
相关代码已经上传到我的码云,感兴趣可以看下。
Java爬虫系列四:使用selenium-java爬取js异步请求的数据的更多相关文章
- 爬虫系列4:Requests+Xpath 爬取动态数据
爬虫系列4:Requests+Xpath 爬取动态数据 [抓取]:参考前文 爬虫系列1:https://www.cnblogs.com/yizhiamumu/p/9451093.html [分页]:参 ...
- Java爬虫系列二:使用HttpClient抓取页面HTML
爬虫要想爬取需要的信息,首先第一步就要抓取到页面html内容,然后对html进行分析,获取想要的内容.上一篇随笔<Java爬虫系列一:写在开始前>中提到了HttpClient可以抓取页面内 ...
- Java爬虫学习(1)之爬取新浪微博博文
本次学习采用了webmagic框架,完成的是一个简单的小demo package com.mieba.spiader; import us.codecraft.webmagic.Page; impor ...
- 爬虫系列3:Requests+Xpath 爬取租房网站信息并保存本地
数据保存本地 [抓取]:参考前文 爬虫系列1:https://www.cnblogs.com/yizhiamumu/p/9451093.html [分页]:参考前文 爬虫系列2:https://www ...
- 爬虫系列2:Requests+Xpath 爬取租房网站信息
Requests+Xpath 爬取租房网站信息 [抓取]:参考前文 爬虫系列1:https://www.cnblogs.com/yizhiamumu/p/9451093.html [分页]:参考前文 ...
- 爬虫系列1:Requests+Xpath 爬取豆瓣电影TOP
爬虫1:Requests+Xpath 爬取豆瓣电影TOP [抓取]:参考前文 爬虫系列1:https://www.cnblogs.com/yizhiamumu/p/9451093.html [分页]: ...
- 爬虫系列(1)-----python爬取猫眼电影top100榜
对于Python初学者来说,爬虫技能是应该是最好入门,也是最能够有让自己有成就感的,今天在整理代码时,整理了一下之前自己学习爬虫的一些代码,今天先上一个简单的例子,手把手教你入门Python爬虫,爬取 ...
- scrapy爬虫系列之二--翻页爬取及日志的基本用法
功能点:如何翻页爬取信息,如何发送请求,日志的简单实用 爬取网站:腾讯社会招聘网 完整代码:https://files.cnblogs.com/files/bookwed/tencent.zip 主要 ...
- (转)Python网络爬虫实战:世纪佳缘爬取近6万条数据
又是一年双十一了,不知道从什么时候开始,双十一从“光棍节”变成了“双十一购物狂欢节”,最后一个属于单身狗的节日也成功被攻陷,成为了情侣们送礼物秀恩爱的节日. 翻着安静到死寂的聊天列表,我忽然惊醒,不行 ...
随机推荐
- 移动端常用单位——rem
移动端常用单位: ①px:像素大小,固定值 ②%:百分比 ③em(不常用,但是在首行缩进时可以使用):相对自身的font大小(当自身的字体大小也是em做单位时,才会以父元素的字体大小为基准单位) ④r ...
- 收下这7款插件,让你在使用 Vite 的时候如虎添翼
相信已经有不少小伙伴已经开始用 Vue3 做开发了,也一定使用上 Vite 了,而我今天要介绍的这几款插件,能让你在使用 Vite 做开发时如虎添翼. vite-plugin-restart 通过监听 ...
- 学习小记: Kaggle Learn - Machine Learning Explainability
Method Feature(s) Sample(s) Result Value/Feature Permutation Importance 1 all validation samples Sin ...
- Linux centos7 find 命令
2021-08-13 1. 命令简介 find 命令用来在指定目录下查找文件.任何位于参数之前的字符串都将被视为欲查找的目录名.如果使用该命令时,不设置任何参数,则 find 命令将在当前目录下查找子 ...
- 安装配置Linux Squid代理服务器
1.代理服务器的工作机制 代理服务器的工作机制像生活中的代理商,假设自己的机器为A,想获得的数据由服务器B提供,代理服务器为C,那么连接过程是,A需要B的数据,并直接和C连接:C接受到A的数据请求之后 ...
- 使用 IDEA 配合 Dockerfile 部署 SpringBoot 工程
准备 SpringBoot 工程 新建 SpringBoot 项目,默认的端口是 8080 ,新建 Controller 和 Mapping @RestController public class ...
- Appium问题解决方案(3)- java.lang.IllegalStateException: UiAutomation not connected!
背景 连着手机,运行脚本,一段时间之后就报错了,看了Appium-server,发现报了这样一个错误 如何解决呢? 步骤一 通过 adb devices ,确定设备是否已连接上 步骤二(最终解决方案) ...
- Vue跨域问题解决
项目根目录下创建vue.config.js module.exports = { devServer: { proxy: { //配置跨域 '/api': { //这里是真实的后台接口 target: ...
- CSS001. 纯CSS实现瀑布流(纵向排序)
通过 Multi-columns 相关的属性 column-count.column-gap 配合 break-inside 来实现瀑布流布局. 首先对包裹图片的盒子增加样式,column-count ...
- 植入式Web前端开发方法
上一篇,我讲述了植入式Web前端开发的基本情况,本篇就来探究其开发方法.以下假定CMS只能植入前端代码,并且需求规模是任意大小的. 代码形式 HTML代码是直接植入的毫无疑问,但除非植入的代码非常简短 ...