当前位置: 首页 > news >正文

JAVA爬虫实战项目——OKX解析

文章目录

  • 前言
  • 介绍
  • 主要技术
  • 初始配置
  • JSoup主程序
  • Selenium+ChromeDriver程序
  • 进一步开发


前言

因为项目的需要,所以需要学习Java爬虫,我是参照B站教程:【【狂神说Java】Jsoup爬虫入门实战】这一视频教程,进行学习的,在这里记录一下自己的学习经验和问题解答,以供后续复盘回看。

介绍

爬虫的生命周期:

  • 页面下载
  • 链接提取
  • URL管理
  • 内容抽取及持久化

通用爬虫:宽度遍历,对网页进行无差别的进行抓取,但是效率不高,因为是爬取的网页上的所有内容

垂直型爬虫:关注内容与准确率,仅仅抓取到有效信息的数据
例如webmagic

主要技术

模拟浏览器:HttpClient
html解析:jsoup

初始配置

新建Maven项目直接使用Project,不需要选下面的Maven Archetype
在这里插入图片描述
项目建好之后,pom.xml中添加Jsoup的依赖,Jsoup 是一款专为 Java 打造的 HTML 解析利器,它能轻松从 URL、文件或字符串中解析 HTML 内容。其具备易用、快速、灵活的特性,可通过类似 CSS 选择器的语法精准定位元素,方便地提取元素文本与属性值,还能自如地进行 DOM 操作,如添加、删除、修改元素等,在网页数据抓取、信息提取及 HTML 文档处理等场景中广受 Java 开发者青睐,是处理 HTML 数据的得力助手。
我这里用的是1.10.2版本的

        <dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.10.2</version></dependency>

JSoup主程序

因为需要访问的是OKX,所以我们需要在代码中添加代理服务器,在这里先打印的是document,因为还不确定,能不能找到我们需要的类,所以先测试页面的读取效果。

package com.tuling.utils;import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;public class HtmlParse {public static void main(String[] args) throws IOException {// 设置要解析的urlString url = "https://www.okx.com";// 设置代理服务器Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("代理服务器地址", 代理服务器端口));// 解析网页Document document = Jsoup.connect(url).proxy(proxy).userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko)Chrome/91.0.4472.124 Safari/537.36").get();// 获取指定class的元素Elements element = document.getElementsByClass("要查找的类");System.out.println(document.html());}
}

这返回的结果并没有找到我们想要的数据,问题就在于jsoup读取的是静态的界面,而对于动态更新的数据,不能捕获到。

后来我们通过F12开发者工具,监控Network,看看能不能找到我们想要的东西
在这里插入图片描述
可以看到,有一个filter-list的信息,里面储存的信息刚好可以和界面对应上,需要我们点击按钮才能获取到这一信息,所以在程序开发的时候,需要有点击这一操作,所以只靠Jsoup肯定是不能满足我们的需求,这时就需要找到另一个工具——Selenium。

Selenium+ChromeDriver程序

程序启动后,会调用ChromeDriver启动模拟浏览器,Selenium点击按钮并读取json数据,给他保存起来。
为了更好的满足可读性,需要从json中获取我们需要的数据,假如字段中含有price,则把price后的数据打印出来。

依赖安装

 <dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.9.0</version></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>31.0.1-jre</version></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.2</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.14</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.14</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.8.0</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.14.2</version></dependency>
package com.tuling;import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v85.network.Network;
import org.openqa.selenium.devtools.v85.network.model.RequestId;
import java.io.FileWriter;
import java.io.IOException;
import java.time.Instant;
import java.util.Optional;public class Main {public static void main(String[] args) {// 设置chromedriver.exe的路径System.setProperty("webdriver.chrome.driver", "C:\\Program Files\\Google\\Chrome\\Application\\chromedriver.exe");WebDriver chromeDriver = new ChromeDriver();DevTools devTools = ((ChromeDriver) chromeDriver).getDevTools();devTools.createSession();final RequestId[] targetRequestId = new RequestId[1];boolean found = false;// 启用网络监控devTools.send(Network.enable(Optional.of(100000000), Optional.empty(), Optional.empty()));// 先访问页面//https://www.okx.com/zh-hans/web3/detail/501/5QS7RcHfGUa2ZtrovPvEJMB9coqroiT7H48dPSwFpumpString url = "https://www.okx.com/zh-hans/web3/detail/501/GorvUUSkJGSzJUebM5W6berUkZ5pG8nmnn7tmk74pump";chromeDriver.get(url);try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}// 添加响应监听器,捕获特定URL的响应devTools.addListener(Network.responseReceived(), responseReceived -> {if (responseReceived.getResponse().getUrl().contains("filter-list")) {targetRequestId[0] = responseReceived.getRequestId();}});while (true) {// 点击交易历史按钮WebElement button = chromeDriver.findElement(By.className("index_tab-item__z34vL"));button.click();try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}// 获取响应体if (targetRequestId[0]!= null) {try {String jsonResponse = devTools.send(Network.getResponseBody(targetRequestId[0])).getBody();System.out.println("历史数据json已获取");System.out.println("解析json......获取价格数据");ObjectMapper mapper = new ObjectMapper();JsonNode root = mapper.readTree(jsonResponse);JsonNode dataNode = root.get("data");if (dataNode!= null && dataNode.has("list")) {JsonNode listNode = dataNode.get("list");int count = 0;System.out.println("==========价格=============");for (JsonNode item : listNode) {if (count >= 10) {break;}if (item.has("price")) {System.out.println(item.get("price"));count++;}}System.out.println("=========================");}long timestamp = Instant.now().getEpochSecond();String fileName = timestamp + ".json";try (FileWriter fileWriter = new FileWriter(fileName)) {fileWriter.write(jsonResponse);} catch (IOException e) {e.printStackTrace();}} catch (Exception e) {e.printStackTrace();}}try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}
}

进一步开发

上面我们已经完成了对动态数据的获取,那对于在Network中找不到json数据的,我们只能采用静态获取的方式,这方法的优点是易于寻找数据,但是缺点是数据不灵活,就是已经写死的。

package com.tuling;import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v85.network.Network;
import org.openqa.selenium.devtools.v85.network.model.RequestId;
import java.io.FileWriter;
import java.io.IOException;
import java.time.Instant;
import java.util.Optional;public class Main {public static void main(String[] args) {// 设置chromedriver.exe的路径System.setProperty("webdriver.chrome.driver", "C:\\Program Files\\Google\\Chrome\\Application\\chromedriver.exe");WebDriver chromeDriver = new ChromeDriver();DevTools devTools = ((ChromeDriver) chromeDriver).getDevTools();devTools.createSession();final RequestId[] targetRequestId = new RequestId[1];boolean found = false;// 启用网络监控devTools.send(Network.enable(Optional.of(100000000), Optional.empty(), Optional.empty()));// 先访问页面//https://www.okx.com/zh-hans/web3/detail/501/5QS7RcHfGUa2ZtrovPvEJMB9coqroiT7H48dPSwFpumpString url = "https://www.okx.com/zh-hans/web3/detail/501/GorvUUSkJGSzJUebM5W6berUkZ5pG8nmnn7tmk74pump";chromeDriver.get(url);try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}// 添加响应监听器,捕获特定URL的响应devTools.addListener(Network.responseReceived(), responseReceived -> {if (responseReceived.getResponse().getUrl().contains("filter-list")) {targetRequestId[0] = responseReceived.getRequestId();}});while (true) {// 点击交易历史按钮WebElement button = chromeDriver.findElement(By.className("index_tab-item__z34vL"));button.click();try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("币种名称:ZAILGO");//获取MarketCap和Liquidity,静态获取方法,和VPN所在地区有关,在哪即为哪里的货币java.util.List<WebElement> elementList = chromeDriver.findElements(By.className("index_value__QnvWy"));if (elementList.size() >= 2) {// 通过索引0获取第一个元素WebElement firstElement = elementList.get(0);System.out.println("Market Cap: " + firstElement.getText());// 通过索引1获取第二个元素WebElement secondElement = elementList.get(1);System.out.println("Liquidity: " + secondElement.getText());}// 获取响应体if (targetRequestId[0]!= null) {try {String jsonResponse = devTools.send(Network.getResponseBody(targetRequestId[0])).getBody();//System.out.println("历史数据json已获取");//System.out.println("解析json......获取价格数据");ObjectMapper mapper = new ObjectMapper();JsonNode root = mapper.readTree(jsonResponse);JsonNode dataNode = root.get("data");if (dataNode!= null && dataNode.has("list")) {JsonNode listNode = dataNode.get("list");int count = 0;System.out.println("==========价格=============");for (JsonNode item : listNode) {if (count >= 10) {break;}if (item.has("price")) {System.out.println(item.get("price"));count++;}}System.out.println("=========================");}long timestamp = Instant.now().getEpochSecond();String fileName = timestamp + ".json";try (FileWriter fileWriter = new FileWriter(fileName)) {fileWriter.write(jsonResponse);} catch (IOException e) {e.printStackTrace();}} catch (Exception e) {e.printStackTrace();}}try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}
}
http://www.dtcms.com/a/428376.html

相关文章:

  • 解除网站开发合同 首付款是否退长沙公司网站设计报价
  • DOM CSS:深入理解与高效运用
  • 闵行网站建设外包微信营销策略有哪些
  • 创建网站怎么赚钱的如何做一个好网站
  • Elasticsearch - Linux下使用Docker对Elasticsearch容器设置账号密码
  • 10. Spring AI + RAG
  • wordpress做自建站上海高品质网站建设公司
  • 网站开发如何找甲方网站后台维护费用
  • 智能化企业级CRM系统开发实战飞算JavaAI全流程体验
  • Matlab通过GUI实现点云的PCA配准(附最简版)
  • 10.17 上海 Google Meetup:从数据出发,解锁 AI 助力增长的新边界
  • 免费成品网站下载上海网站设计多少钱
  • 外管局网站上做预收登记制作公司网页图片
  • 【DockerFile+Nginx+DockerCompose】前后端分离式项目部署(docker容器化方式)
  • 快速傅里叶变换简介及python实现
  • 网站的实现怎么写重庆网站seo方法
  • 公司建设网站费用会计分录哈尔滨建筑工程招聘信息
  • 猫眼网站建设适合小县城开的加盟店
  • 网站开发 系统需求文档个性化定制网站
  • IDEA+SpringBoot实现远程DEBUG到本机
  • 网站建设与维护 目录开发公司前期手续流程
  • 物品奖励系统介绍
  • 广州站西手表公司彩页设计制作
  • sat4j中参数作用
  • 网站建设课程有哪些收获西安注册公司虚拟地址
  • 哪家做网站性价比高朋友圈自己做的网站
  • 建设网站需要掌握什么编程语言川菜餐馆网站建设模板美食餐厅企业建站php源码程序
  • 网上商城公司网站建设方案被网上教开网店的骗了怎么办
  • 网站域名无法访问国外建站工具
  • SurfaceFlinger BufferQueue(三) DequeueBuffer