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);}}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/36386.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/36386.shtml
英文地址,請注明出處:http://en.pswp.cn/news/36386.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SAP系統是什么呢?它有哪些優勢?

SAP系統是全球知名的企業資源規劃&#xff08;ERP&#xff09;解決方案供應商。它集成了財務、供應鏈管理、人力資源管理、銷售和客戶關系管理等多個功能模塊&#xff0c;為企業提供全面、集成的管理體驗。SAP系統已成為各行各業企業管理的智慧選擇&#xff0c;極大地提升了管理…

c++ 有元

友元分為兩部分內容 友元函數友元類 友元函數 問題&#xff1a;當我們嘗試去重載operator<<&#xff0c;然后發現沒辦法將operator<<重載成成員函數。因為cout的輸出流對象和隱含的this指針在搶占第一個參數的位置。this指針默認是第一個參數也就是左操作 數了。…

如何在vue3中加入markdown語法

1、首先需要安裝 md-editor-v3 yarn add md-editor-v3 或者是在vue圖形化界面中直接搜索 md-editor-v3 進行安裝。 2、引入該編輯頁 引入可以參考這個&#xff0c;根據自己的需求進行修改和添加。 <template><md-editor v-model"text"/> </templat…

基于dbn+svr的交通流量預測,dbn詳細原理

目錄 背影 DBN神經網絡的原理 DBN神經網絡的定義 受限玻爾茲曼機(RBM) DBN+SVR的交通流量預測 基本結構 主要參數 數據 MATALB代碼 結果圖 展望 背影 DBN是一種深度學習神經網絡,擁有提取特征,非監督學習的能力,是一種非常好的分類算法,本文將DBN+SVR用于交通流量預測…

二叉樹題目:二叉樹的直徑

文章目錄 題目標題和出處難度題目描述要求示例數據范圍 解法思路和算法代碼復雜度分析 題目 標題和出處 標題&#xff1a;二叉樹的直徑 出處&#xff1a;543. 二叉樹的直徑 難度 3 級 題目描述 要求 給定二叉樹的根結點 root \texttt{root} root&#xff0c;返回其直徑…

考研408 | 【計算機網絡】 傳輸層

導圖 傳輸層的功能 傳輸層的兩個協議 傳輸層的尋址與端口 UDP協議 UDP的主要特點 UDP首部格式&#xff1a; UDP校驗&#xff1a; TCP協議 TCP協議的特點 TCP報文段首部格式 TCP連接管理 TCP的連接建立 SYN洪泛攻擊 TCP的連接釋放 TCP可靠傳輸 序號&#xff1a; 確認&#xff1…

ASEMI快恢復二極管APT80DQ20BG怎么檢查好壞

編輯-Z 二極管APT80DQ20BG是一種高壓快恢復二極管&#xff0c;常用于電源和電能質量控制等領域。如果您的二極管出現故障或需要進行維修&#xff0c;以下是一些可能的解決方案。 首先&#xff0c;確保您已經斷開了電源&#xff0c;并且具備基本的電子維修知識和技能。如果您不…

添加vue devtools擴展工具+添加后F12不顯示Vue圖標

前言&#xff1a;在開啟Vue學習之旅時&#xff0c;遇到問題兩個問題&#xff0c;第一添加不上vue devtools擴展工具&#xff0c;第二添加完成后&#xff0c;F12不顯示Vue圖標。查閱了很多博客&#xff0c;自己解決了問題&#xff0c;故寫此博客記錄。如果你遇到和我一樣的問題&…

React源碼解析18(3)------ beginWork的工作流程【mount】

摘要 OK&#xff0c;經過上一篇文章。我們調用了&#xff1a; const root document.querySelector(#root); ReactDOM.createRoot(root)生成了FilberRootNode和HostRootFilber。 并且二者之間的對應關系也已經確定。 而下一步我們就需要調用render方法來講react元素掛載在ro…

【JavaEE進階】SpringBoot 日志

文章目錄 一. 日志有什么用?二. 自定義日志打印1. 日志的使用與打印 三. 日志級別1. 日志級別有什么用?2. 日志級別的分類及使用 四. 日志持久化五. 更簡單的日志輸出---Lombok1. Lombok的使用2. lombok原理解釋2.1 Lombok更多注解說明 一. 日志有什么用? 在Java中&#xf…

【結構型設計模式】C#設計模式之外觀模式

題目描述&#xff1a; 假設你正在開發一個音樂播放器應用程序&#xff0c;該應用程序需要與多個子系統進行交互&#xff0c;包括音頻解碼、音量控制和播放控制等。請使用外觀模式設計一個音樂播放器的外觀類&#xff0c;并實現相應的子系統類。 要求&#xff1a; 創建一個外觀…

【gogogo專欄】指針

go語言指針 為什么需要指針指針使用實例值傳遞地址傳遞多級指針 為什么需要指針 作為一個大學劃水&#xff0c;畢業一直寫java的程序員來說&#xff0c;多多少少對于指針有點陌生&#xff0c;由于近期需要轉go&#xff0c;正好學到指針這里&#xff0c;就來探究下指針的使用場景…

ThreadLocal詳解

ThreadLocal詳解 一、故事背景二、知識點主要構成1、什么是ThreadLocal&#xff1f;2、ThreadLocal的基本使用內存泄漏問題引用類型&#xff1a;強引用&#xff1a;軟引用弱引用虛引用 ThreadLocal內存泄漏原因 三、總結提升 一、故事背景 最近在學習并發編程相關內容&#xf…

pycharm 安裝庫

這是另一種方式。 搜索到的安裝庫的方式多數是&#xff1a;在桌面上winR鍵運行終端&#xff0c;輸入命令&#xff0c;安裝不了&#xff0c;發現安裝不了。 1、打開pycharm&#xff1b; 2、軟件下部的Terminal終端(需要運行一個代碼才能出現&#xff0c;任何代碼都可)&#xf…

Es、kibana安裝教程-ES(二)

上篇文章介紹了ES負責數據存儲&#xff0c;計算和搜索&#xff0c;他與傳統數據庫不同&#xff0c;是基于倒排索引來解決問題的。Kibana是es可視化工具。 分布式搜索ElasticSearch-ES&#xff08;一&#xff09; 一、ElasticSearch安裝 官網下載地址&#xff1a;https://www…

[C語言] 指針

1. 指針是什么 2. 指針和指針類型 3. 野指針 4. 指針運算 5. 指針和數組 6. 二級指針 7. 指針數組 目錄 1. 指針是什么&#xff1f; 2. 指針和指針類型 2.1 指針-整數 2.2 指針的解引用 3. 野指針 3.1 野指針成因 3.2 如何規避野指針 4. 指針運算 4.1 指針…

不用技術代碼,分班查詢系統怎么做?

暑假即將結束&#xff0c;新學期開始將面臨分班信息公布的工作&#xff01;對于分班信息公布&#xff0c;涉及到學生的個人信息&#xff0c;包括姓名、學號、班級等。在發布這些信息時&#xff0c;必須確保數據的保密性&#xff0c;防止未經授權的人員獲取到學生的個人信息。因…

對字符串中所有單詞進行倒排-C語言/Java

描述 輸入一個字符串&#xff0c;輸出字符串中單詞的倒序。 要求 構成單詞的字符只有26個大寫或小寫英文字母。非構成單詞的字符均視為單詞間隔符&#xff1b;倒排后的單詞間隔符以一個空格表示&#xff1b;如果原字符串中相鄰單詞間有多個間隔符時&#xff0c;倒排轉換后也只…

docker的服務/容器缺少vim問題

背景/問題&#xff1a; docker的服務/容器缺少vim問題 bash: vim: command not found 在docker的mysql服務中安裝Vim 1、執行apt-get update root6d8d17e320a0:/# apt-get update問題:文件下載失敗 Err:1 http://security.debian.org/debian-security buster/updates InRe…

【Linux】程序地址空間

程序地址空間 首先引入地址空間的作用什么是地址空間為什么要有地址空間 首先引入地址空間的作用 1 #include <stdio.h>2 #include <unistd.h>3 #include <stdlib.h>4 int g_val 100;6 int main()7 {8 pid_t id fork();9 if(id 0)10 {11 int cn…