当前位置: 首页 > 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…...

每日热门skill:你的AI终于有“脑子“了!Memory MCP Server让Claude记住你的一切

告别"金鱼记忆",打造真正懂你的AI助手 一、开篇:那个让你崩溃的瞬间 你有没有遇到过这种情况? 昨天刚跟Claude说过:“我是做后端开发的,对Python比较熟悉,前端不太行。” 今天再问:“帮我写个React组件。” 它热情洋溢地回复:“好的!这是一个完整的全栈…...

踩坑无数!终于捋顺Git基础核心工作流(新手必看)

我刚学Git那会&#xff0c;一直有个超级大的疑惑憋在心里&#xff1a;为什么保存代码非要分 git add 和 git commit 两步&#xff1f; 当时网上教程清一色直接甩命令&#xff0c;我照着敲了无数次&#xff0c;只会机械复制粘贴&#xff0c;完全不懂底层逻辑。自己本地瞎写代码还…...

如何快速掌握游戏MOD制作:LSLib开源工具箱的终极指南

如何快速掌握游戏MOD制作&#xff1a;LSLib开源工具箱的终极指南 【免费下载链接】lslib Tools for manipulating Divinity Original Sin and Baldurs Gate 3 files 项目地址: https://gitcode.com/gh_mirrors/ls/lslib 你是否曾经梦想过修改《神界原罪》或《博德之门3》…...

Redis容器内存统计失真与cgroup隔离失效深度解析

1. 这不是“老漏洞复现”&#xff0c;而是Redis容器化部署中被集体忽视的底层内存契约崩塌你有没有遇到过这样的情况&#xff1a;一套跑在Docker里的Redis服务&#xff0c;配置没动、版本没升、流量平稳&#xff0c;某天凌晨突然开始OOM Killer杀进程&#xff0c;docker stats显…...

创业公司利用Taotoken按Token计费模式精细控制AI研发成本

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 创业公司利用Taotoken按Token计费模式精细控制AI研发成本 对于创业公司而言&#xff0c;在产品研发的早期阶段&#xff0c;快速进行…...

终极解放:BetterGI原神自动化工具完整指南

终极解放&#xff1a;BetterGI原神自动化工具完整指南 【免费下载链接】better-genshin-impact &#x1f4e6;BetterGI 更好的原神 - 自动拾取 | 自动剧情 | 全自动钓鱼(AI) | 全自动七圣召唤 | 自动伐木 | 自动刷本 | 自动采集/挖矿/锄地 | 一条龙 | 全连音游 | 自动烹饪 - U…...

如何快速搭建高性能Minecraft服务器:CatServer终极整合方案

如何快速搭建高性能Minecraft服务器&#xff1a;CatServer终极整合方案 【免费下载链接】CatServer 高性能和高兼容性的1.12.2/1.16.5/1.18.2版本ForgeBukkitSpigot服务端 (A high performance and high compatibility 1.12.2/1.16.5/1.18.2 version ForgeBukkitSpigot server)…...

【2024B站算法白皮书级洞察】:ChatGPT如何精准预测“推荐池准入阈值”?3个被官方文档隐去的关键信号

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;【2024B站算法白皮书级洞察】&#xff1a;ChatGPT如何精准预测“推荐池准入阈值”&#xff1f;3个被官方文档隐去的关键信号 Bilibili 2024年Q2推荐系统升级后&#xff0c;“推荐池准入阈值”&#xff…...

微信小程序wxapkg逆向解析原理与合规源码还原实践

1. 这不是“破解”&#xff0c;而是合法合规的源码审计实践微信小程序生态里&#xff0c;每天有数百万个新版本上线&#xff0c;而开发者真正能拿到手的&#xff0c;往往只有.wxapkg文件——一个经过混淆、压缩、资源内联、逻辑分包的二进制容器。很多人第一反应是&#xff1a;…...

NVIDIA显卡终极色彩校准指南:novideo_srgb让广色域显示器回归真实色彩

NVIDIA显卡终极色彩校准指南&#xff1a;novideo_srgb让广色域显示器回归真实色彩 【免费下载链接】novideo_srgb Calibrate monitors to sRGB or other color spaces on NVIDIA GPUs, based on EDID data or ICC profiles 项目地址: https://gitcode.com/gh_mirrors/no/novi…...