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

selenium 爬虫

selenium 可以动态爬取网页数据,就像真实用户操作浏览器一样,从终端用户的角度测试应用程序,WebDriver通过原生浏览器支持或者浏览器扩展直接控制浏览器

webdriver下载

因为selenuim对浏览器的版本存在兼容问题,顾需要针对指定浏览器下载指定版本。

1、添加依赖

        <dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.11.0</version></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>32.1.2-jre</version></dependency>

2、工具类

import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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.chrome.ChromeOptions;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;/*** Selenium 工具类** @author kou*/
@Slf4j
@RequiredArgsConstructor
@Component
public class SeleniumUtil {private final ReptileProperties reptileProperties;/*** 获取chromeDriver** @return chromeDriver*/public WebDriver chromeDriver() {// 加载驱动路径System.setProperty("webdriver.chrome.driver", "D:/chromedriver.exe");// Chrome默认不允许跨机器调试,需要给启动命令加上白名单System.setProperty("webdriver.chrome.whitelistedIps", "");ChromeOptions options = new ChromeOptions();// 开启一个实验性参数excludeSwitches,用来隐藏window.navigator.webdriver返回true,这个参数必须是Listoptions.setExperimentalOption("useAutomationExtension", false);// 开启开发者模式options.setExperimentalOption("excludeSwitches", Lists.newArrayList("enable-automation"));// 发现主要是这句是关键options.addArguments("--disable-blink-features=AutomationControlled");// options.addArguments("--incognito");// options.addArguments("--disable-infobars");//options.addArguments("user-agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36");options.addArguments("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36");// 禁用沙箱options.addArguments("--no-sandbox");// 无头浏览器,这样不会打开浏览器窗口// options.addArguments("--headless");// options.addArguments("--disable-gpu");options.addArguments("--remote-allow-origins=*");// 初始化一个谷歌浏览器实例,实例名称叫driverWebDriver driver = new ChromeDriver(options);return driver;}/*** 获取edgeDriver** @return edgeDriver*/public WebDriver edgeDriver() {// 加载驱动路径System.setProperty("webdriver.edge.driver", "D:/msedgedriver.exe");EdgeOptions options = new EdgeOptions();// 开启一个实验性参数excludeSwitches,用来隐藏window.navigator.webdriver返回true,这个参数必须是Listoptions.setExperimentalOption("useAutomationExtension", false);//开启开发者模式options.setExperimentalOption("excludeSwitches", Lists.newArrayList("enable-automation"));// 发现主要是这句是关键options.addArguments("--disable-blink-features=AutomationControlled");options.addArguments("--incognito", "--disable-infobars");// options.addArguments("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36");options.addArguments("user-agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36");// 禁用沙箱options.addArguments("--no-sandbox");// 无头浏览器,这样不会打开浏览器窗口// options.addArguments("--headless");options.addArguments("--disable-gpu");options.addArguments("--remote-allow-origins=*");// 初始化一个谷歌浏览器实例,实例名称叫driverWebDriver driver = new EdgeDriver(options);return driver;}/*** 获取firefoxDriver** @return firefoxDriver*/public WebDriver firefoxDriver() {// 加载驱动路径System.setProperty("webdriver.gecko.driver", "D:/geckodriver.exe");System.setProperty("webdriver.chrome.whitelistedIps", "");FirefoxOptions options = new FirefoxOptions();options.addArguments("user-agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36");// 无头浏览器,这样不会打开浏览器窗口options.addArguments("--headless");// 初始化一个谷歌浏览器实例,实例名称叫driverWebDriver driver = new FirefoxDriver(options);return driver;}/*** 获取表头** @param table 表格* @return 表头*/public List<String> getTableHead(WebElement table) {log.info("开始解析表头...");// 获取表头WebElement head = table.findElement(By.tagName("thead"));if (null == head) {return Collections.emptyList();}List<WebElement> headths = head.findElements(By.tagName("th"));List<String> headList = new ArrayList<>(headths.size());headths.forEach(t -> {headList.add(t.getText());});log.info("表头解析完成!!!");return headList;}/*** 获取表数据** @param table 表格* @return 表头*/public List<List<String>> getTableBody(WebElement table) {log.info("开始解析表数据...");// 获取表头WebElement tbody = table.findElement(By.tagName("tbody"));if (null == tbody) {return Collections.emptyList();}// 获取body数据行List<WebElement> bodyTrs = tbody.findElements(By.tagName("tr"));if (CollectionUtil.isEmpty(bodyTrs)) {return Collections.emptyList();}List<List<String>> bodyDatas = new ArrayList<>(bodyTrs.size());bodyTrs.stream().forEach(r -> {List<WebElement> tds = r.findElements(By.tagName("td"));List<String> rows = new ArrayList<>(tds.size());tds.forEach(d -> {rows.add(d.getText());});bodyDatas.add(rows);});log.info("表数据解析完成!!!");return bodyDatas;}/*** 将参数转化为路径参数** @param params 参数* @return 路径参数*/public String convertPathParams(Map<String, Object> params) {if (CollectionUtil.isEmpty(params)) {return "";}StringBuffer path = new StringBuffer();for (Map.Entry<String, Object> p : params.entrySet()) {path.append(p.getKey()).append("=").append(p.getValue().toString()).append("&");}return path.substring(0, path.length() - 1);}}

3、爬取数据

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;/*** 数据接口实现类** @author kou*/
@Slf4j
@RequiredArgsConstructor
@Service
public class DataServiceImpl {private final SeleniumUtil seleniumUtil;/*** 获取页面数据** @return 数据*/@Overridepublic Map<String, Object> getHtmlData() {try {Map<String, Object> data = new HashMap<>();String url = "url";Map<String, Object> params = new HashMap<>();params.put("pageNum", 1);params.put("pageSize", 1000);String fullUrl = url + seleniumUtil.convertPathParams(params);WebDriver driver = seleniumUtil.firefoxDriver();driver.get(fullUrl);// 打开一个站点log.info("开始访问:{}", fullUrl);driver.get(fullUrl);String title = driver.getTitle();log.info("网页:{}", title);// 获取表格数据WebElement table = driver.findElement(By.id("table"));//显式等待,针对某个元素等待,等待超时时间100s,2s检测一次WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(100), Duration.ofSeconds(2));// wait.until(ExpectedConditions.presenceOfElementLocated(By.id("table")));wait.until(new ExpectedCondition<WebElement>() {@Overridepublic WebElement apply(WebDriver text) {log.info("开始检查tbody数据是否已加载");WebElement table = text.findElement(By.id("table")).findElement(By.tagName("tbody"));if (!table.isDisplayed()) {log.info("检查结果:tbody数据未加载完,等待加载...");return null;}log.info("检查结果:tbody数据加载完成!!!");return table;}});// 获取表头List<String> headList = seleniumUtil.getTableHead(table);List<List<String>> bodyList = seleniumUtil.getTableBody(table);data.put("header", headList);data.put("body", bodyList);driver.close();return data;} catch (Exception e) {throw new RuntimeException(e);}}}

相关文章:

selenium 爬虫

selenium 可以动态爬取网页数据&#xff0c;就像真实用户操作浏览器一样&#xff0c;从终端用户的角度测试应用程序&#xff0c;WebDriver通过原生浏览器支持或者浏览器扩展直接控制浏览器 webdriver下载 因为selenuim对浏览器的版本存在兼容问题&#xff0c;顾需要针对指定浏…...

​亚商投资顾问 早餐FM/0815生成式人工智能服务管理

01/亚商投资顾问 早间导读 商务部等9部门&#xff1a;促进农村大宗商品消费更新换代中央财办等九部门印发指导意见推动农村流通高质量发展《生成式人工智能服务管理暂行办法》今起施行 02/亚商投资顾问 新闻早餐 // 热点聚焦 // 商务部等9部门印发《县域商业三年行动计划&…...

C语言题目的多种解法分享 2之字符串左旋和补充题

前言 有的时候&#xff0c;这个系列专栏中的解法之间并无优劣&#xff0c;只是给大家提供不同的解题思路 我决定将代码实现的过程写成注释&#xff0c;方便大家直接找到对应的函数&#xff0c;只有需要补充说明的知识才会单拿出来强调 这个系列的文章会更的比较慢&#xff0…...

科技云报道:算力之战,英伟达再度释放AI“炸弹”

科技云报道原创。 近日&#xff0c;在计算机图形学顶会SIGGRAPH 2023现场&#xff0c;英伟达再度释放深夜“炸弹”&#xff0c;大模型专用芯片迎来升级版本。 英伟达在会上发布了新一代GH200 Grace Hopper平台&#xff0c;该平台依托于搭载全球首款搭载HBM3e处理器的新型Grac…...

油电同价、标配8155,奇瑞猛攻10-15万中型SUV市场

8月8日&#xff0c;奇瑞瑞虎8冠军家族在北京国家奥林匹克体育中心正式上市&#xff0c;推出了瑞虎8 PRO冠军版、瑞虎8新能源冠军版两款新车&#xff0c;燃油混动双线同步发力。 其中&#xff0c;瑞虎8 PRO冠军版共推7款车型&#xff0c;官方指导价12.69万元-16.39万元&#xf…...

【leetcode】【图解】617. 合并二叉树

题目 难度&#xff1a;简单 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff09;。你需要将这两棵树合并成一棵新二叉树。合并的规则是&#xf…...

基于java的汽车改装方案网站设计与实现

摘要 本文主要讲述了基于SpringBootMySql开发技术开发的汽车改装方案网站的设计与实现。这里的汽车改装方案网站是通过一个平台使所有的汽车爱好者们可以不用出门就可以体验到专业的汽车改装方案设计服务。现实生活中如果需要进行汽车改装的方案设计&#xff0c;往往要跑很多次…...

DC电源模块减小输入电源与输出负载之间的能量损失

BOSHIDA DC电源模块减小输入电源与输出负载之间的能量损失 随着电子产品的普及&#xff0c;DC电源模块已成为现代电子设备中不可或缺的组成部分。DC电源模块可以将交流电转化为直流电&#xff0c;并根据需要&#xff0c;以适当的电压和电流提供给输出负载。然而&#xff0c;在输…...

Python自动化小技巧16——分类汇总写入excel不同sheet表

案例背景 上了两个月班的社畜博主最近终于有空来总结一下最近写的代码了。 因为上班都是文职工作&#xff0c;天天不是word就是excel就是PPT和pdf....这和什么机器学习还有数据科学不一样&#xff0c;任务更多的是处理实在的文字和表格等格式&#xff0c;按照领导要求来完成&…...

FlexRay汽车总线静电防护,如何设计保护方案图?

FlexRay是一种高速、实时、可靠、具备故障容错能力的总线技术&#xff0c;是继CAN和LIN总线之后的最新研发成果。FlexRay为线控应用&#xff08;即线控驱动、线控转向、线控制动等&#xff09;提供了容错和时间确定性性能要求。虽然FlexRay将解决当前高端和未来主流车载网络的挑…...

jpg图片太大怎么压缩?这样做轻松压缩图片

图片太大会给存储、分享带来麻烦&#xff0c;但其实现在压缩图片大小也不是什么难事&#xff0c;下面就给大家分享几个一直用的图片压缩方法&#xff0c;包含批量压缩、在线压缩、免费压缩等多种方式&#xff0c;大家按需自取哈~ 方法一&#xff1a;嗨格式压缩大师 这是一个可…...

B057-spring增强 依赖注入 AOP 代理模式 创建Bean

目录 AOP概念代理模式引出AOP实现方式xml方式实现注解方式实现 AOP 概念 事务管理&#xff1a;比如可以抽取try catch的重复代码 日志监控&#xff1a;比如业务逻辑前后打印关于当前订单数量的日志&#xff0c;了解业务做了什么 性能监控&#xff1a;比如业务前后打印时间&…...

小程序多图片组合

目录 子组件 index.js 子组件 index.wxml 子组件 index.wxss 父组件引用&#xff1a; 子组件&#xff1a;preview-image 子组件 index.js Component({properties: {previewData: {type: Array,default: [],observer: function (newVal, oldVal) {console.log(newVal, ol…...

YOLO v8目标跟踪详细解读(二)

上一篇&#xff0c;结合代码&#xff0c;我们详细的介绍了YOLOV8目标跟踪的Pipeline。大家应该对跟踪的流程有了大致的了解&#xff0c;下面我们将对跟踪中出现的卡尔曼滤波进行解读。 1.卡尔曼滤波器介绍 卡尔曼滤波&#xff08;kalman Filtering&#xff09;是一种利用线性…...

【广州华锐视点】AR电力职业技能培训系统让技能学习更“智慧”

随着科技的发展&#xff0c;教育方式也在不断地进步和创新。其中&#xff0c;增强现实(AR)技术的出现&#xff0c;为教育领域带来了全新的可能。AR电力职业技能培训系统就是这种创新教学方法的完美实践&#xff0c;它将虚拟与现实相结合&#xff0c;为学生提供了一个沉浸式的学…...

C#学习,反射

目录 C#学习 .NET的体系结构 二次编译 反射 什么是反射&#xff1f; 什么是Type&#xff1f; 什么是程序集&#xff1f; 反射API&#xff1a; 一&#xff0c;程序集 1&#xff0c; Load 2&#xff0c;LoadFrom 3&#xff0c;LoadFile 二&#xff0c;类型实例 1&a…...

代理模式概述

1.代理模式概述 学习内容 1&#xff09;概述 为什么要有 “代理” &#xff1f; 生活中就有很多例子&#xff0c;比如委托业务&#xff0c;黄牛&#xff08;票贩子&#xff09;等等代理就是被代理者没有能力或者不愿意去完成某件事情&#xff0c;需要找个人代替自己去完成这…...

最新AI系统ChatGPT网站程序源码+搭建教程/公众号/H5端/安装配置教程/完整知识库

1、前言 SparkAi系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。 那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧&#xff01;…...

前端Flex布局

day06-Flex布局 目标&#xff1a;熟练使用 Flex 完成结构化布局 01-标准流 标准流也叫文档流&#xff0c;指的是标签在页面中默认的排布规则&#xff0c;例如&#xff1a;块元素独占一行&#xff0c;行内元素可以一行显示多个。 [外链图片转存失败,源站可能有防盗链机制,建议…...

文盘Rust -- Mutex解决并发写文件乱序问题 | 京东云技术团队

在实际开发过程中&#xff0c;我们可能会遇到并发写文件的场景&#xff0c;如果处理不当很可能出现文件内容乱序问题。下面我们通过一个示例程序描述这一过程并给出解决该问题的方法。 use std::{fs::{self, File, OpenOptions},io::{Write},sync::Arc,time::{SystemTime, UNI…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

规则与人性的天平——由高考迟到事件引发的思考

当那位身着校服的考生在考场关闭1分钟后狂奔而至&#xff0c;他涨红的脸上写满绝望。铁门内秒针划过的弧度&#xff0c;成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定"&#xff0c;构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...

Python环境安装与虚拟环境配置详解

本文档旨在为Python开发者提供一站式的环境安装与虚拟环境配置指南&#xff0c;适用于Windows、macOS和Linux系统。无论你是初学者还是有经验的开发者&#xff0c;都能在此找到适合自己的环境搭建方法和常见问题的解决方案。 快速开始 一分钟快速安装与虚拟环境配置 # macOS/…...

验证redis数据结构

一、功能验证 1.验证redis的数据结构&#xff08;如字符串、列表、哈希、集合、有序集合等&#xff09;是否按照预期工作。 2、常见的数据结构验证方法&#xff1a; ①字符串&#xff08;string&#xff09; 测试基本操作 set、get、incr、decr 验证字符串的长度和内容是否正…...