java高效實現爬蟲

一、前言
在Web爬蟲技術中,Selenium作為一款強大的瀏覽器自動化工具,能夠模擬真實用戶操作,有效應對JavaScript渲染、Ajax加載等復雜場景。而集成代理服務則能夠解決IP限制、地域訪問限制等問題。本文將詳細介紹如何利用Java+Selenium+快代理實現高效的爬蟲系統。

二、Selenium簡介
Selenium是一個用于Web應用程序自動化測試的工具集,它主要用于自動化瀏覽器操作,可以模擬用戶與網頁的交互行為,如點擊按鈕、填寫表單、滾動頁面等。在爬蟲領域,Selenium特別適合處理那些需要JavaScript渲染、需要登錄或有反爬措施的網站。

三、環境準備
JDK1.8
Maven項目管理
相關依賴
<!-- Selenium -->
<dependency>
? ? <groupId>org.seleniumhq.selenium</groupId>
? ? <artifactId>selenium-java</artifactId>
? ? <version>3.141.59</version>
</dependency>
<dependency>
? ? <groupId>io.github.bonigarcia</groupId>
? ? <artifactId>webdrivermanager</artifactId>
? ? <version>5.3.2</version>
</dependency>
<!-- Selenium -->
<dependency>
? ? <groupId>org.seleniumhq.selenium</groupId>
? ? <artifactId>selenium-java</artifactId>
? ? <version>3.141.59</version>
</dependency>
<dependency>
? ? <groupId>io.github.bonigarcia</groupId>
? ? <artifactId>webdrivermanager</artifactId>
? ? <version>5.3.2</version>
</dependency>

四、代碼實現
本系統采用的是工廠模式創建WebDriver實例,這樣做的好處主要是可以提供統一的創建方法,不管使用那種瀏覽器都適用,自由配置。其次就是維護方便,瀏覽器配置變更只需修改工廠類中的相關方法,擴展性也不錯,可以輕松添加新的瀏覽器支持,比如Opera或者Safari等等。

4.1 創建WebDriver工廠類
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
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.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.PageLoadStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
?* WebDriver工廠類,負責創建和配置各種瀏覽器驅動實例
?* 設計思路:
?* 1. 使用工廠模式統一管理不同瀏覽器的WebDriver創建邏輯
?* 2. 采用構建器模式(Builder Pattern)使配置更加靈活
?* 3. 封裝復雜的瀏覽器選項設置,簡化調用代碼
?* 4. 支持多種瀏覽器類型和代理配置
?*?
?* 好處:
?* 1. 代碼復用性高,減少重復代碼
?* 2. 配置靈活,通過鏈式調用設置參數
?* 3. 職責單一,僅負責創建WebDriver
?* 4. 易于擴展,可輕松添加新的瀏覽器類型支持
?*/
public class WebDriverFactory {
? ? // 使用SLF4J記錄日志,便于問題排查
? ? private static final Logger log = LoggerFactory.getLogger(WebDriverFactory.class);
? ??
? ? // 默認配置,可通過構建器方法修改
? ? private boolean headless = true; ? ? ? ? ? ? ? ?// 默認無頭模式
? ? private int pageLoadTimeoutSeconds = 30; ? ? ? ?// 頁面加載超時時間
? ? private int scriptTimeoutSeconds = 30; ? ? ? ? ?// 腳本執行超時時間
? ? private int implicitWaitSeconds = 10; ? ? ? ? ? // 隱式等待時間
? ??
? ? // 代理配置
? ? private boolean proxyEnabled = false; ? ? ? ? ? // 是否啟用代理
? ? private String proxyHost; ? ? ? ? ? ? ? ? ? ? ? // 代理主機地址
? ? private int proxyPort; ? ? ? ? ? ? ? ? ? ? ? ? ?// 代理端口
? ? private String proxyUsername; ? ? ? ? ? ? ? ? ? // 代理用戶名(認證用)
? ? private String proxyPassword; ? ? ? ? ? ? ? ? ? // 代理密碼(認證用)
? ??
? ? /**
? ? ?* 支持的瀏覽器類型枚舉
? ? ?* 便于擴展,后續可以增加其他瀏覽器支持
? ? ?*/
? ? public enum BrowserType {
? ? ? ? CHROME, EDGE, FIREFOX
? ? }
? ??
? ? /**
? ? ?* 設置是否使用無頭模式
? ? ?* 無頭模式下瀏覽器不會顯示界面,更加節省資源
? ? ?*?
? ? ?* @param headless true表示使用無頭模式,false表示顯示瀏覽器界面
? ? ?* @return 當前工廠實例,支持鏈式調用
? ? ?*/
? ? public WebDriverFactory withHeadless(boolean headless) {
? ? ? ? this.headless = headless;
? ? ? ? return this;
? ? }
? ??
? ? /**
? ? ?* 設置頁面加載超時時間
? ? ?*?
? ? ?* @param seconds 超時秒數
? ? ?* @return 當前工廠實例,支持鏈式調用
? ? ?*/
? ? public WebDriverFactory withPageLoadTimeout(int seconds) {
? ? ? ? this.pageLoadTimeoutSeconds = seconds;
? ? ? ? return this;
? ? }
? ??
? ? /**
? ? ?* 設置JavaScript腳本執行超時時間
? ? ?*?
? ? ?* @param seconds 超時秒數
? ? ?* @return 當前工廠實例,支持鏈式調用
? ? ?*/
? ? public WebDriverFactory withScriptTimeout(int seconds) {
? ? ? ? this.scriptTimeoutSeconds = seconds;
? ? ? ? return this;
? ? }
? ??
? ? /**
? ? ?* 設置元素查找隱式等待時間
? ? ?*?
? ? ?* @param seconds 等待秒數
? ? ?* @return 當前工廠實例,支持鏈式調用
? ? ?*/
? ? public WebDriverFactory withImplicitWait(int seconds) {
? ? ? ? this.implicitWaitSeconds = seconds;
? ? ? ? return this;
? ? }
? ??
? ? /**
? ? ?* 配置代理服務器
? ? ?*?
? ? ?* @param host 代理主機地址
? ? ?* @param port 代理端口
? ? ?* @return 當前工廠實例,支持鏈式調用
? ? ?*/
? ? public WebDriverFactory withProxy(String host, int port) {
? ? ? ? this.proxyEnabled = true;
? ? ? ? this.proxyHost = host;
? ? ? ? this.proxyPort = port;
? ? ? ? return this;
? ? }
? ??
? ? /**
? ? ?* 配置代理服務器認證信息
? ? ?*?
? ? ?* @param username 代理用戶名
? ? ?* @param password 代理密碼
? ? ?* @return 當前工廠實例,支持鏈式調用
? ? ?*/
? ? public WebDriverFactory withProxyAuth(String username, String password) {
? ? ? ? this.proxyUsername = username;
? ? ? ? this.proxyPassword = password;
? ? ? ? return this;
? ? }
? ??
? ? /**
? ? ?* 創建指定類型的WebDriver實例
? ? ?* 工廠方法核心,根據指定的瀏覽器類型創建對應的WebDriver
? ? ?*?
? ? ?* @param browserType 瀏覽器類型枚舉
? ? ?* @return 配置好的WebDriver實例
? ? ?*/
? ? public WebDriver createWebDriver(BrowserType browserType) {
? ? ? ? switch (browserType) {
? ? ? ? ? ? case CHROME:
? ? ? ? ? ? ? ? return createChromeDriver();
? ? ? ? ? ? case EDGE:
? ? ? ? ? ? ? ? return createEdgeDriver();
? ? ? ? ? ? case FIREFOX:
? ? ? ? ? ? ? ? return createFirefoxDriver();
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? // 默認使用Edge瀏覽器
? ? ? ? ? ? ? ? log.info("未指定瀏覽器類型,默認使用Edge瀏覽器");
? ? ? ? ? ? ? ? return createEdgeDriver();
? ? ? ? }
? ? }
? ??
? ? /**
? ? ?* 創建Edge瀏覽器WebDriver實例
? ? ?*?
? ? ?* @return 配置好的Edge WebDriver
? ? ?*/
? ? private WebDriver createEdgeDriver() {
? ? ? ? // 自動下載與系統瀏覽器匹配的WebDriver,避免版本不匹配問題
? ? ? ? WebDriverManager.edgedriver().setup();
? ? ? ??
? ? ? ? EdgeOptions options = new EdgeOptions();
? ? ? ??
? ? ? ? // 配置瀏覽器選項
? ? ? ? Map<String, Object> edgePrefs = new HashMap<>();
? ? ? ? // 禁用自動擴展,減少資源占用和干擾
? ? ? ? edgePrefs.put("useAutomationExtension", false);
? ? ? ??
? ? ? ? // 獲取通用瀏覽器參數
? ? ? ? List<String> args = getCommonBrowserArgs();
? ? ? ??
? ? ? ? Map<String, Object> edgeOptions = new HashMap<>();
? ? ? ? edgeOptions.put("args", args);
? ? ? ??
? ? ? ? // 設置User-Agent,模擬真實瀏覽器,減少被網站識別為爬蟲的可能
? ? ? ? options.setCapability("ms.edge.userAgent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36 Edg/135.0.0.0");
? ? ? ??
? ? ? ? // 設置頁面加載策略為NORMAL,確保頁面完整加載
? ? ? ? // 可選值:NONE (不等待加載), EAGER (DOM就緒即可), NORMAL (等待完全加載)
? ? ? ? options.setPageLoadStrategy(PageLoadStrategy.NORMAL);
? ? ? ??
? ? ? ? // Edge特有配置
? ? ? ? options.setCapability("ms:edgeChromium", true);
? ? ? ? options.setCapability("ms:edgeOptions", edgeOptions);
? ? ? ? // 使用隱私模式,避免歷史記錄、cookie等信息的干擾
? ? ? ? options.setCapability("inPrivate", true);
? ? ? ??
? ? ? ? // 配置代理
? ? ? ? configureProxy(options);
? ? ? ??
? ? ? ? // 創建WebDriver實例
? ? ? ? WebDriver driver = new EdgeDriver(options);
? ? ? ? // 配置超時設置
? ? ? ? configureTimeouts(driver);
? ? ? ??
? ? ? ? log.info("Edge WebDriver創建成功");
? ? ? ? return driver;
? ? }
? ??
? ? /**
? ? ?* 創建Chrome瀏覽器WebDriver實例
? ? ?*?
? ? ?* @return 配置好的Chrome WebDriver
? ? ?*/
? ? private WebDriver createChromeDriver() {
? ? ? ? // 自動下載與系統瀏覽器匹配的WebDriver
? ? ? ? WebDriverManager.chromedriver().setup();
? ? ? ??
? ? ? ? ChromeOptions options = new ChromeOptions();
? ? ? ??
? ? ? ? // 根據配置決定是否使用無頭模式
? ? ? ? if (headless) {
? ? ? ? ? ? options.addArguments("--headless");
? ? ? ? }
? ? ? ??
? ? ? ? // 添加通用瀏覽器參數
? ? ? ? for (String arg : getCommonBrowserArgs()) {
? ? ? ? ? ? options.addArguments(arg);
? ? ? ? }
? ? ? ??
? ? ? ? // 設置頁面加載策略
? ? ? ? options.setPageLoadStrategy(PageLoadStrategy.NORMAL);
? ? ? ??
? ? ? ? // Chrome瀏覽器特殊處理代理配置
? ? ? ? configureProxyForChrome(options);
? ? ? ??
? ? ? ? // 創建WebDriver實例
? ? ? ? WebDriver driver = new ChromeDriver(options);
? ? ? ? // 配置超時設置
? ? ? ? configureTimeouts(driver);
? ? ? ??
? ? ? ? log.info("Chrome WebDriver創建成功");
? ? ? ? return driver;
? ? }
? ??
? ? /**
? ? ?* 創建Firefox瀏覽器WebDriver實例
? ? ?*?
? ? ?* @return 配置好的Firefox WebDriver
? ? ?*/
? ? private WebDriver createFirefoxDriver() {
? ? ? ? // 自動下載與系統瀏覽器匹配的WebDriver
? ? ? ? WebDriverManager.firefoxdriver().setup();
? ? ? ??
? ? ? ? FirefoxOptions options = new FirefoxOptions();
? ? ? ??
? ? ? ? // 根據配置決定是否使用無頭模式
? ? ? ? if (headless) {
? ? ? ? ? ? options.addArguments("--headless");
? ? ? ? }
? ? ? ??
? ? ? ? // 配置代理
? ? ? ? configureProxy(options);
? ? ? ??
? ? ? ? // 創建WebDriver實例
? ? ? ? WebDriver driver = new FirefoxDriver(options);
? ? ? ? // 配置超時設置
? ? ? ? configureTimeouts(driver);
? ? ? ??
? ? ? ? log.info("Firefox WebDriver創建成功");
? ? ? ? return driver;
? ? }
? ??
? ? /**
? ? ?* 獲取通用瀏覽器啟動參數
? ? ?* 這些參數適用于基于Chromium的瀏覽器(Chrome, Edge)
? ? ?*?
? ? ?* @return 參數列表
? ? ?*/
? ? private List<String> getCommonBrowserArgs() {
? ? ? ? List<String> args = new ArrayList<>();
? ? ? ??
? ? ? ? // 無頭模式相關參數
? ? ? ? if (headless) {
? ? ? ? ? ? args.add("--headless"); ?// 不顯示瀏覽器界面
? ? ? ? ? ? args.add("--disable-gpu"); ?// 在某些系統上無頭模式需要禁用GPU加速
? ? ? ? }
? ? ? ??
? ? ? ? // 禁用擴展和插件,減少資源占用和干擾
? ? ? ? args.add("--disable-extensions");
? ? ? ??
? ? ? ? // 禁用圖片加載,提高性能
? ? ? ? args.add("--blink-settings=imagesEnabled=false");
? ? ? ??
? ? ? ? // 解決在Docker容器中可能出現的共享內存問題
? ? ? ? args.add("--disable-dev-shm-usage");
? ? ? ??
? ? ? ? // 禁用平滑滾動,減少自動滾動問題
? ? ? ? args.add("--disable-smooth-scrolling");
? ? ? ??
? ? ? ? // 設置固定窗口大小,避免響應式變化導致的元素定位問題
? ? ? ? args.add("--window-size=1366,768");
? ? ? ??
? ? ? ? // 禁用站點隔離,減少內存使用
? ? ? ? args.add("--disable-features=site-per-process");
? ? ? ??
? ? ? ? // 禁用默認應用,減少啟動時間
? ? ? ? args.add("--disable-default-apps");
? ? ? ??
? ? ? ? // 減少日志輸出,提高性能
? ? ? ? args.add("--disable-logging");
? ? ? ??
? ? ? ? // 禁用信息欄,避免干擾
? ? ? ? args.add("--disable-infobars");
? ? ? ??
? ? ? ? // 禁用通知,避免干擾
? ? ? ? args.add("--disable-notifications");
? ? ? ??
? ? ? ? // 添加性能優化參數
? ? ? ? args.add("--disable-web-security"); ?// 禁用同源策略檢查
? ? ? ? args.add("--no-sandbox"); ?// 禁用沙箱模式,提高性能(注意安全風險)
? ? ? ? args.add("--disable-setuid-sandbox"); ?// 禁用setuid沙箱,配合--no-sandbox使用
? ? ? ? args.add("--disable-accelerated-2d-canvas"); ?// 禁用加速2D Canvas,減少GPU使用
? ? ? ? args.add("--disable-crash-reporter"); ?// 禁用崩潰報告
? ? ? ? args.add("--disable-in-process-stack-traces"); ?// 禁用進程內堆棧跟蹤
? ? ? ? args.add("--disable-breakpad"); ?// 禁用斷點調試
? ? ? ? args.add("--aggressive-cache-discard"); ?// 積極丟棄緩存,減少內存使用
? ? ? ? args.add("--disable-ipc-flooding-protection"); ?// 禁用IPC洪水保護
? ? ? ??
? ? ? ? // 限制JavaScript引擎內存使用,防止內存溢出
? ? ? ? args.add("--js-flags=--max-old-space-size=512");
? ? ? ??
? ? ? ? return args;
? ? }
? ??
? ? /**
? ? ?* 為瀏覽器選項配置代理
? ? ?* 適用于Edge和Firefox瀏覽器
? ? ?*?
? ? ?* @param options 瀏覽器選項對象
? ? ?*/
? ? private void configureProxy(Object options) {
? ? ? ? if (proxyEnabled && proxyHost != null && !proxyHost.isEmpty() && proxyPort > 0) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? // 構建代理URL,處理是否需要認證
? ? ? ? ? ? ? ? String proxyUrl;
? ? ? ? ? ? ? ? if (proxyUsername != null && !proxyUsername.isEmpty() && proxyPassword != null) {
? ? ? ? ? ? ? ? ? ? // 帶認證的代理格式:http://username:password@host:port
? ? ? ? ? ? ? ? ? ? proxyUrl = "http://" + proxyUsername + ":" + proxyPassword + "@" + proxyHost + ":" + proxyPort;
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? // 不帶認證的代理格式:http://host:port
? ? ? ? ? ? ? ? ? ? proxyUrl = "http://" + proxyHost + ":" + proxyPort;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? // 創建代理對象
? ? ? ? ? ? ? ? Proxy proxy = new Proxy();
? ? ? ? ? ? ? ? // 同時設置HTTP和HTTPS代理,確保所有請求都通過代理
? ? ? ? ? ? ? ? proxy.setHttpProxy(proxyUrl);
? ? ? ? ? ? ? ? proxy.setSslProxy(proxyUrl);
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? // 根據瀏覽器類型設置代理能力
? ? ? ? ? ? ? ? if (options instanceof EdgeOptions) {
? ? ? ? ? ? ? ? ? ? ((EdgeOptions) options).setCapability(CapabilityType.PROXY, proxy);
? ? ? ? ? ? ? ? } else if (options instanceof FirefoxOptions) {
? ? ? ? ? ? ? ? ? ? ((FirefoxOptions) options).setCapability(CapabilityType.PROXY, proxy);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? log.info("WebDriver配置了代理: {}", proxyHost + ":" + proxyPort);
? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? log.error("配置代理時出錯: {}", e.getMessage());
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ??
? ? /**
? ? ?* 為Chrome瀏覽器特別配置代理
? ? ?* Chrome處理代理的方式與Edge和Firefox略有不同
? ? ?*?
? ? ?* @param options Chrome瀏覽器選項對象
? ? ?*/
? ? private void configureProxyForChrome(ChromeOptions options) {
? ? ? ? if (proxyEnabled && proxyHost != null && !proxyHost.isEmpty() && proxyPort > 0) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? // 構建代理URL,處理是否需要認證
? ? ? ? ? ? ? ? String proxyUrl;
? ? ? ? ? ? ? ? if (proxyUsername != null && !proxyUsername.isEmpty() && proxyPassword != null) {
? ? ? ? ? ? ? ? ? ? // 帶認證的代理
? ? ? ? ? ? ? ? ? ? proxyUrl = "http://" + proxyUsername + ":" + proxyPassword + "@" + proxyHost + ":" + proxyPort;
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? // 不帶認證的代理
? ? ? ? ? ? ? ? ? ? proxyUrl = "http://" + proxyHost + ":" + proxyPort;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? // 創建代理對象
? ? ? ? ? ? ? ? Proxy proxy = new Proxy();
? ? ? ? ? ? ? ? proxy.setHttpProxy(proxyUrl);
? ? ? ? ? ? ? ? proxy.setSslProxy(proxyUrl);
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? // 為Chrome設置代理能力
? ? ? ? ? ? ? ? options.setCapability(CapabilityType.PROXY, proxy);
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? log.info("Chrome WebDriver配置了代理: {}", proxyHost + ":" + proxyPort);
? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? log.error("配置Chrome代理時出錯: {}", e.getMessage());
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ??
? ? /**
? ? ?* 配置WebDriver的各種超時設置
? ? ?*?
? ? ?* @param driver WebDriver實例
? ? ?*/
? ? private void configureTimeouts(WebDriver driver) {
? ? ? ? // 設置頁面加載超時時間
? ? ? ? driver.manage().timeouts().pageLoadTimeout(pageLoadTimeoutSeconds, TimeUnit.SECONDS);
? ? ? ? // 設置腳本執行超時時間
? ? ? ? driver.manage().timeouts().setScriptTimeout(scriptTimeoutSeconds, TimeUnit.SECONDS);
? ? ? ? // 設置隱式等待時間,查找元素時使用
? ? ? ? driver.manage().timeouts().implicitlyWait(implicitWaitSeconds, TimeUnit.SECONDS);
? ? ? ??
? ? ? ? log.debug("WebDriver超時配置完成:頁面加載={}秒,腳本執行={}秒,隱式等待={}秒",
? ? ? ? ? ? ? ? pageLoadTimeoutSeconds, scriptTimeoutSeconds, implicitWaitSeconds);
? ? }
}

import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
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.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.PageLoadStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
?* WebDriver工廠類,負責創建和配置各種瀏覽器驅動實例
?* 設計思路:
?* 1. 使用工廠模式統一管理不同瀏覽器的WebDriver創建邏輯
?* 2. 采用構建器模式(Builder Pattern)使配置更加靈活
?* 3. 封裝復雜的瀏覽器選項設置,簡化調用代碼
?* 4. 支持多種瀏覽器類型和代理配置
?*?
?* 好處:
?* 1. 代碼復用性高,減少重復代碼
?* 2. 配置靈活,通過鏈式調用設置參數
?* 3. 職責單一,僅負責創建WebDriver
?* 4. 易于擴展,可輕松添加新的瀏覽器類型支持
?*/
public class WebDriverFactory {
? ? // 使用SLF4J記錄日志,便于問題排查
? ? private static final Logger log = LoggerFactory.getLogger(WebDriverFactory.class);
? ??
? ? // 默認配置,可通過構建器方法修改
? ? private boolean headless = true; ? ? ? ? ? ? ? ?// 默認無頭模式
? ? private int pageLoadTimeoutSeconds = 30; ? ? ? ?// 頁面加載超時時間
? ? private int scriptTimeoutSeconds = 30; ? ? ? ? ?// 腳本執行超時時間
? ? private int implicitWaitSeconds = 10; ? ? ? ? ? // 隱式等待時間
? ??
? ? // 代理配置
? ? private boolean proxyEnabled = false; ? ? ? ? ? // 是否啟用代理
? ? private String proxyHost; ? ? ? ? ? ? ? ? ? ? ? // 代理主機地址
? ? private int proxyPort; ? ? ? ? ? ? ? ? ? ? ? ? ?// 代理端口
? ? private String proxyUsername; ? ? ? ? ? ? ? ? ? // 代理用戶名(認證用)
? ? private String proxyPassword; ? ? ? ? ? ? ? ? ? // 代理密碼(認證用)
? ??
? ? /**
? ? ?* 支持的瀏覽器類型枚舉
? ? ?* 便于擴展,后續可以增加其他瀏覽器支持
? ? ?*/
? ? public enum BrowserType {
? ? ? ? CHROME, EDGE, FIREFOX
? ? }
? ??
? ? /**
? ? ?* 設置是否使用無頭模式
? ? ?* 無頭模式下瀏覽器不會顯示界面,更加節省資源
? ? ?*?
? ? ?* @param headless true表示使用無頭模式,false表示顯示瀏覽器界面
? ? ?* @return 當前工廠實例,支持鏈式調用
? ? ?*/
? ? public WebDriverFactory withHeadless(boolean headless) {
? ? ? ? this.headless = headless;
? ? ? ? return this;
? ? }
? ??
? ? /**
? ? ?* 設置頁面加載超時時間
? ? ?*?
? ? ?* @param seconds 超時秒數
? ? ?* @return 當前工廠實例,支持鏈式調用
? ? ?*/
? ? public WebDriverFactory withPageLoadTimeout(int seconds) {
? ? ? ? this.pageLoadTimeoutSeconds = seconds;
? ? ? ? return this;
? ? }
? ??
? ? /**
? ? ?* 設置JavaScript腳本執行超時時間
? ? ?*?
? ? ?* @param seconds 超時秒數
? ? ?* @return 當前工廠實例,支持鏈式調用
? ? ?*/
? ? public WebDriverFactory withScriptTimeout(int seconds) {
? ? ? ? this.scriptTimeoutSeconds = seconds;
? ? ? ? return this;
? ? }
? ??
? ? /**
? ? ?* 設置元素查找隱式等待時間
? ? ?*?
? ? ?* @param seconds 等待秒數
? ? ?* @return 當前工廠實例,支持鏈式調用
? ? ?*/
? ? public WebDriverFactory withImplicitWait(int seconds) {
? ? ? ? this.implicitWaitSeconds = seconds;
? ? ? ? return this;
? ? }
? ??
? ? /**
? ? ?* 配置代理服務器
? ? ?*?
? ? ?* @param host 代理主機地址
? ? ?* @param port 代理端口
? ? ?* @return 當前工廠實例,支持鏈式調用
? ? ?*/
? ? public WebDriverFactory withProxy(String host, int port) {
? ? ? ? this.proxyEnabled = true;
? ? ? ? this.proxyHost = host;
? ? ? ? this.proxyPort = port;
? ? ? ? return this;
? ? }
? ??
? ? /**
? ? ?* 配置代理服務器認證信息
? ? ?*?
? ? ?* @param username 代理用戶名
? ? ?* @param password 代理密碼
? ? ?* @return 當前工廠實例,支持鏈式調用
? ? ?*/
? ? public WebDriverFactory withProxyAuth(String username, String password) {
? ? ? ? this.proxyUsername = username;
? ? ? ? this.proxyPassword = password;
? ? ? ? return this;
? ? }
? ??
? ? /**
? ? ?* 創建指定類型的WebDriver實例
? ? ?* 工廠方法核心,根據指定的瀏覽器類型創建對應的WebDriver
? ? ?*?
? ? ?* @param browserType 瀏覽器類型枚舉
? ? ?* @return 配置好的WebDriver實例
? ? ?*/
? ? public WebDriver createWebDriver(BrowserType browserType) {
? ? ? ? switch (browserType) {
? ? ? ? ? ? case CHROME:
? ? ? ? ? ? ? ? return createChromeDriver();
? ? ? ? ? ? case EDGE:
? ? ? ? ? ? ? ? return createEdgeDriver();
? ? ? ? ? ? case FIREFOX:
? ? ? ? ? ? ? ? return createFirefoxDriver();
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? // 默認使用Edge瀏覽器
? ? ? ? ? ? ? ? log.info("未指定瀏覽器類型,默認使用Edge瀏覽器");
? ? ? ? ? ? ? ? return createEdgeDriver();
? ? ? ? }
? ? }
? ??
? ? /**
? ? ?* 創建Edge瀏覽器WebDriver實例
? ? ?*?
? ? ?* @return 配置好的Edge WebDriver
? ? ?*/
? ? private WebDriver createEdgeDriver() {
? ? ? ? // 自動下載與系統瀏覽器匹配的WebDriver,避免版本不匹配問題
? ? ? ? WebDriverManager.edgedriver().setup();
? ? ? ??
? ? ? ? EdgeOptions options = new EdgeOptions();
? ? ? ??
? ? ? ? // 配置瀏覽器選項
? ? ? ? Map<String, Object> edgePrefs = new HashMap<>();
? ? ? ? // 禁用自動擴展,減少資源占用和干擾
? ? ? ? edgePrefs.put("useAutomationExtension", false);
? ? ? ??
? ? ? ? // 獲取通用瀏覽器參數
? ? ? ? List<String> args = getCommonBrowserArgs();
? ? ? ??
? ? ? ? Map<String, Object> edgeOptions = new HashMap<>();
? ? ? ? edgeOptions.put("args", args);
? ? ? ??
? ? ? ? // 設置User-Agent,模擬真實瀏覽器,減少被網站識別為爬蟲的可能
? ? ? ? options.setCapability("ms.edge.userAgent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36 Edg/135.0.0.0");
? ? ? ??
? ? ? ? // 設置頁面加載策略為NORMAL,確保頁面完整加載
? ? ? ? // 可選值:NONE (不等待加載), EAGER (DOM就緒即可), NORMAL (等待完全加載)
? ? ? ? options.setPageLoadStrategy(PageLoadStrategy.NORMAL);
? ? ? ??
? ? ? ? // Edge特有配置
? ? ? ? options.setCapability("ms:edgeChromium", true);
? ? ? ? options.setCapability("ms:edgeOptions", edgeOptions);
? ? ? ? // 使用隱私模式,避免歷史記錄、cookie等信息的干擾
? ? ? ? options.setCapability("inPrivate", true);
? ? ? ??
? ? ? ? // 配置代理
? ? ? ? configureProxy(options);
? ? ? ??
? ? ? ? // 創建WebDriver實例
? ? ? ? WebDriver driver = new EdgeDriver(options);
? ? ? ? // 配置超時設置
? ? ? ? configureTimeouts(driver);
? ? ? ??
? ? ? ? log.info("Edge WebDriver創建成功");
? ? ? ? return driver;
? ? }
? ??
? ? /**
? ? ?* 創建Chrome瀏覽器WebDriver實例
? ? ?*?
? ? ?* @return 配置好的Chrome WebDriver
? ? ?*/
? ? private WebDriver createChromeDriver() {
? ? ? ? // 自動下載與系統瀏覽器匹配的WebDriver
? ? ? ? WebDriverManager.chromedriver().setup();
? ? ? ??
? ? ? ? ChromeOptions options = new ChromeOptions();
? ? ? ??
? ? ? ? // 根據配置決定是否使用無頭模式
? ? ? ? if (headless) {
? ? ? ? ? ? options.addArguments("--headless");
? ? ? ? }
? ? ? ??
? ? ? ? // 添加通用瀏覽器參數
? ? ? ? for (String arg : getCommonBrowserArgs()) {
? ? ? ? ? ? options.addArguments(arg);
? ? ? ? }
? ? ? ??
? ? ? ? // 設置頁面加載策略
? ? ? ? options.setPageLoadStrategy(PageLoadStrategy.NORMAL);
? ? ? ??
? ? ? ? // Chrome瀏覽器特殊處理代理配置
? ? ? ? configureProxyForChrome(options);
? ? ? ??
? ? ? ? // 創建WebDriver實例
? ? ? ? WebDriver driver = new ChromeDriver(options);
? ? ? ? // 配置超時設置
? ? ? ? configureTimeouts(driver);
? ? ? ??
? ? ? ? log.info("Chrome WebDriver創建成功");
? ? ? ? return driver;
? ? }
? ??
? ? /**
? ? ?* 創建Firefox瀏覽器WebDriver實例
? ? ?*?
? ? ?* @return 配置好的Firefox WebDriver
? ? ?*/
? ? private WebDriver createFirefoxDriver() {
? ? ? ? // 自動下載與系統瀏覽器匹配的WebDriver
? ? ? ? WebDriverManager.firefoxdriver().setup();
? ? ? ??
? ? ? ? FirefoxOptions options = new FirefoxOptions();
? ? ? ??
? ? ? ? // 根據配置決定是否使用無頭模式
? ? ? ? if (headless) {
? ? ? ? ? ? options.addArguments("--headless");
? ? ? ? }
? ? ? ??
? ? ? ? // 配置代理
? ? ? ? configureProxy(options);
? ? ? ??
? ? ? ? // 創建WebDriver實例
? ? ? ? WebDriver driver = new FirefoxDriver(options);
? ? ? ? // 配置超時設置
? ? ? ? configureTimeouts(driver);
? ? ? ??
? ? ? ? log.info("Firefox WebDriver創建成功");
? ? ? ? return driver;
? ? }
? ??
? ? /**
? ? ?* 獲取通用瀏覽器啟動參數
? ? ?* 這些參數適用于基于Chromium的瀏覽器(Chrome, Edge)
? ? ?*?
? ? ?* @return 參數列表
? ? ?*/
? ? private List<String> getCommonBrowserArgs() {
? ? ? ? List<String> args = new ArrayList<>();
? ? ? ??
? ? ? ? // 無頭模式相關參數
? ? ? ? if (headless) {
? ? ? ? ? ? args.add("--headless"); ?// 不顯示瀏覽器界面
? ? ? ? ? ? args.add("--disable-gpu"); ?// 在某些系統上無頭模式需要禁用GPU加速
? ? ? ? }
? ? ? ??
? ? ? ? // 禁用擴展和插件,減少資源占用和干擾
? ? ? ? args.add("--disable-extensions");
? ? ? ??
? ? ? ? // 禁用圖片加載,提高性能
? ? ? ? args.add("--blink-settings=imagesEnabled=false");
? ? ? ??
? ? ? ? // 解決在Docker容器中可能出現的共享內存問題
? ? ? ? args.add("--disable-dev-shm-usage");
? ? ? ??
? ? ? ? // 禁用平滑滾動,減少自動滾動問題
? ? ? ? args.add("--disable-smooth-scrolling");
? ? ? ??
? ? ? ? // 設置固定窗口大小,避免響應式變化導致的元素定位問題
? ? ? ? args.add("--window-size=1366,768");
? ? ? ??
? ? ? ? // 禁用站點隔離,減少內存使用
? ? ? ? args.add("--disable-features=site-per-process");
? ? ? ??
? ? ? ? // 禁用默認應用,減少啟動時間
? ? ? ? args.add("--disable-default-apps");
? ? ? ??
? ? ? ? // 減少日志輸出,提高性能
? ? ? ? args.add("--disable-logging");
? ? ? ??
? ? ? ? // 禁用信息欄,避免干擾
? ? ? ? args.add("--disable-infobars");
? ? ? ??
? ? ? ? // 禁用通知,避免干擾
? ? ? ? args.add("--disable-notifications");
? ? ? ??
? ? ? ? // 添加性能優化參數
? ? ? ? args.add("--disable-web-security"); ?// 禁用同源策略檢查
? ? ? ? args.add("--no-sandbox"); ?// 禁用沙箱模式,提高性能(注意安全風險)
? ? ? ? args.add("--disable-setuid-sandbox"); ?// 禁用setuid沙箱,配合--no-sandbox使用
? ? ? ? args.add("--disable-accelerated-2d-canvas"); ?// 禁用加速2D Canvas,減少GPU使用
? ? ? ? args.add("--disable-crash-reporter"); ?// 禁用崩潰報告
? ? ? ? args.add("--disable-in-process-stack-traces"); ?// 禁用進程內堆棧跟蹤
? ? ? ? args.add("--disable-breakpad"); ?// 禁用斷點調試
? ? ? ? args.add("--aggressive-cache-discard"); ?// 積極丟棄緩存,減少內存使用
? ? ? ? args.add("--disable-ipc-flooding-protection"); ?// 禁用IPC洪水保護
? ? ? ??
? ? ? ? // 限制JavaScript引擎內存使用,防止內存溢出
? ? ? ? args.add("--js-flags=--max-old-space-size=512");
? ? ? ??
? ? ? ? return args;
? ? }
? ??
? ? /**
? ? ?* 為瀏覽器選項配置代理
? ? ?* 適用于Edge和Firefox瀏覽器
? ? ?*?
? ? ?* @param options 瀏覽器選項對象
? ? ?*/
? ? private void configureProxy(Object options) {
? ? ? ? if (proxyEnabled && proxyHost != null && !proxyHost.isEmpty() && proxyPort > 0) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? // 構建代理URL,處理是否需要認證
? ? ? ? ? ? ? ? String proxyUrl;
? ? ? ? ? ? ? ? if (proxyUsername != null && !proxyUsername.isEmpty() && proxyPassword != null) {
? ? ? ? ? ? ? ? ? ? // 帶認證的代理格式:http://username:password@host:port
? ? ? ? ? ? ? ? ? ? proxyUrl = "http://" + proxyUsername + ":" + proxyPassword + "@" + proxyHost + ":" + proxyPort;
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? // 不帶認證的代理格式:http://host:port
? ? ? ? ? ? ? ? ? ? proxyUrl = "http://" + proxyHost + ":" + proxyPort;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? // 創建代理對象
? ? ? ? ? ? ? ? Proxy proxy = new Proxy();
? ? ? ? ? ? ? ? // 同時設置HTTP和HTTPS代理,確保所有請求都通過代理
? ? ? ? ? ? ? ? proxy.setHttpProxy(proxyUrl);
? ? ? ? ? ? ? ? proxy.setSslProxy(proxyUrl);
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? // 根據瀏覽器類型設置代理能力
? ? ? ? ? ? ? ? if (options instanceof EdgeOptions) {
? ? ? ? ? ? ? ? ? ? ((EdgeOptions) options).setCapability(CapabilityType.PROXY, proxy);
? ? ? ? ? ? ? ? } else if (options instanceof FirefoxOptions) {
? ? ? ? ? ? ? ? ? ? ((FirefoxOptions) options).setCapability(CapabilityType.PROXY, proxy);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? log.info("WebDriver配置了代理: {}", proxyHost + ":" + proxyPort);
? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? log.error("配置代理時出錯: {}", e.getMessage());
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ??
? ? /**
? ? ?* 為Chrome瀏覽器特別配置代理
? ? ?* Chrome處理代理的方式與Edge和Firefox略有不同
? ? ?*?
? ? ?* @param options Chrome瀏覽器選項對象
? ? ?*/
? ? private void configureProxyForChrome(ChromeOptions options) {
? ? ? ? if (proxyEnabled && proxyHost != null && !proxyHost.isEmpty() && proxyPort > 0) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? // 構建代理URL,處理是否需要認證
? ? ? ? ? ? ? ? String proxyUrl;
? ? ? ? ? ? ? ? if (proxyUsername != null && !proxyUsername.isEmpty() && proxyPassword != null) {
? ? ? ? ? ? ? ? ? ? // 帶認證的代理
? ? ? ? ? ? ? ? ? ? proxyUrl = "http://" + proxyUsername + ":" + proxyPassword + "@" + proxyHost + ":" + proxyPort;
? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? // 不帶認證的代理
? ? ? ? ? ? ? ? ? ? proxyUrl = "http://" + proxyHost + ":" + proxyPort;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? // 創建代理對象
? ? ? ? ? ? ? ? Proxy proxy = new Proxy();
? ? ? ? ? ? ? ? proxy.setHttpProxy(proxyUrl);
? ? ? ? ? ? ? ? proxy.setSslProxy(proxyUrl);
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? // 為Chrome設置代理能力
? ? ? ? ? ? ? ? options.setCapability(CapabilityType.PROXY, proxy);
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? log.info("Chrome WebDriver配置了代理: {}", proxyHost + ":" + proxyPort);
? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? log.error("配置Chrome代理時出錯: {}", e.getMessage());
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ??
? ? /**
? ? ?* 配置WebDriver的各種超時設置
? ? ?*?
? ? ?* @param driver WebDriver實例
? ? ?*/
? ? private void configureTimeouts(WebDriver driver) {
? ? ? ? // 設置頁面加載超時時間
? ? ? ? driver.manage().timeouts().pageLoadTimeout(pageLoadTimeoutSeconds, TimeUnit.SECONDS);
? ? ? ? // 設置腳本執行超時時間
? ? ? ? driver.manage().timeouts().setScriptTimeout(scriptTimeoutSeconds, TimeUnit.SECONDS);
? ? ? ? // 設置隱式等待時間,查找元素時使用
? ? ? ? driver.manage().timeouts().implicitlyWait(implicitWaitSeconds, TimeUnit.SECONDS);
? ? ? ??
? ? ? ? log.debug("WebDriver超時配置完成:頁面加載={}秒,腳本執行={}秒,隱式等待={}秒",
? ? ? ? ? ? ? ? pageLoadTimeoutSeconds, scriptTimeoutSeconds, implicitWaitSeconds);
? ? }
}

4.2 創建爬蟲主類
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
?* Selenium爬蟲示例主類
?* 演示如何使用WebDriverFactory創建瀏覽器實例并進行網頁爬取
?*/
public class SeleniumCrawler {
? ? private static final Logger log = LoggerFactory.getLogger(SeleniumCrawler.class);
? ??
? ? public static void main(String[] args) {
? ? ? ? // 推薦使用快代理的隧道代理:https://www.kuaidaili.com/?ref=soi1rkc6rd82
? ? ? ? String proxyHost = ""; ?// 快代理隧道代理主機
? ? ? ? int proxyPort = 15818; ? ? ? ? ? ? ? ?// 端口,根據實際情況修改
? ? ? ? String proxyUsername = "yourUsername"; // 替換為您的快代理用戶名
? ? ? ? String proxyPassword = "yourPassword"; // 替換為您的快代理密碼
? ? ? ??
? ? ? ? // 創建WebDriver工廠實例,配置爬蟲參數
? ? ? ? // 使用構建器模式,代碼可讀性強,配置靈活
? ? ? ? WebDriverFactory factory = new WebDriverFactory()
? ? ? ? ? ? .withHeadless(false) ?// 設置為false可以看到瀏覽器界面,方便調試
? ? ? ? ? ? .withPageLoadTimeout(30) ?// 頁面加載超時設置為30秒
? ? ? ? ? ? .withScriptTimeout(30) ? ?// 腳本執行超時設置為30秒 ?
? ? ? ? ? ? .withImplicitWait(10) ? ? // 查找元素隱式等待10秒
? ? ? ? ? ? .withProxy(proxyHost, proxyPort) ? ? ? ? ? // 設置快代理的主機和端口
? ? ? ? ? ? .withProxyAuth(proxyUsername, proxyPassword); ?// 設置代理認證信息
? ? ? ??
? ? ? ? WebDriver driver = null;
? ? ? ? try {
? ? ? ? ? ? // 創建Edge瀏覽器實例,也可以選擇Chrome或Firefox
? ? ? ? ? ? log.info("正在初始化WebDriver...");
? ? ? ? ? ? driver = factory.createWebDriver(WebDriverFactory.BrowserType.EDGE);
? ? ? ? ? ??
? ? ? ? ? ? // 開始爬蟲任務
? ? ? ? ? ? crawlWebsite(driver);
? ? ? ? ? ??
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? // 異常處理,記錄詳細錯誤信息便于排錯
? ? ? ? ? ? log.error("爬蟲執行出錯: {}", e.getMessage(), e);
? ? ? ? } finally {
? ? ? ? ? ? // 確保WebDriver正確關閉,避免資源泄露
? ? ? ? ? ? if (driver != null) {
? ? ? ? ? ? ? ? driver.quit();
? ? ? ? ? ? ? ? log.info("WebDriver已關閉,爬蟲任務結束");
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ??
? ? /**
? ? ?* 爬蟲核心邏輯,可根據實際需求擴展
? ? ?*?
? ? ?* @param driver 已配置好的WebDriver實例
? ? ?* @throws InterruptedException 如果線程休眠被中斷
? ? ?*/
? ? private static void crawlWebsite(WebDriver driver) throws InterruptedException {
? ? ? ? // 訪問目標網站
? ? ? ? log.info("開始訪問目標網站");
? ? ? ? driver.get("https://www.baidu.com");
? ? ? ? log.info("網頁標題: {}", driver.getTitle());
? ? ? ??
? ? ? ? // 顯式等待某個元素出現,確保頁面加載完成
? ? ? ? // 比簡單的Thread.sleep更智能
? ? ? ? WebDriverWait wait = new WebDriverWait(driver, 10);
? ? ? ? wait.until(ExpectedConditions.presenceOfElementLocated(By.tagName("body")));
? ? ? ??
? ? ? ? // 獲取頁面內容示例:提取所有鏈接
? ? ? ? log.info("開始提取頁面鏈接");
? ? ? ? List<WebElement> links = driver.findElements(By.tagName("a"));
? ? ? ? log.info("共發現{}個鏈接", links.size());
? ? ? ??
? ? ? ? // 處理提取到的鏈接
? ? ? ? for (WebElement link : links) {
? ? ? ? ? ? String text = link.getText().trim();
? ? ? ? ? ? String href = link.getAttribute("href");
? ? ? ? ? ? // 只記錄有效鏈接
? ? ? ? ? ? if (href != null && !href.isEmpty()) {
? ? ? ? ? ? ? ? log.info("鏈接: {} -> {}", text.isEmpty() ? "[無文本]" : text, href);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ??
? ? ? ? // 模擬更多爬蟲操作,例如點擊某個元素、填寫表單等
? ? ? ? // 這里作為示例,只是簡單等待
? ? ? ? log.info("等待頁面進一步處理...");
? ? ? ? Thread.sleep(2000);
? ? ? ??
? ? ? ? // 如果需要,可以繼續訪問更多頁面
? ? ? ? // driver.get("https://www.another-site.com");
? ? ? ? // ...
? ? ? ??
? ? ? ? log.info("爬蟲任務完成");
? ? }
}

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
?* Selenium爬蟲示例主類
?* 演示如何使用WebDriverFactory創建瀏覽器實例并進行網頁爬取
?*/
public class SeleniumCrawler {
? ? private static final Logger log = LoggerFactory.getLogger(SeleniumCrawler.class);
? ??
? ? public static void main(String[] args) {
? ? ? ? // 推薦使用快代理的隧道代理:https://www.kuaidaili.com/?ref=soi1rkc6rd82
? ? ? ? String proxyHost = ""; ?// 快代理隧道代理主機
? ? ? ? int proxyPort = 15818; ? ? ? ? ? ? ? ?// 端口,根據實際情況修改
? ? ? ? String proxyUsername = "yourUsername"; // 替換為您的快代理用戶名
? ? ? ? String proxyPassword = "yourPassword"; // 替換為您的快代理密碼
? ? ? ??
? ? ? ? // 創建WebDriver工廠實例,配置爬蟲參數
? ? ? ? // 使用構建器模式,代碼可讀性強,配置靈活
? ? ? ? WebDriverFactory factory = new WebDriverFactory()
? ? ? ? ? ? .withHeadless(false) ?// 設置為false可以看到瀏覽器界面,方便調試
? ? ? ? ? ? .withPageLoadTimeout(30) ?// 頁面加載超時設置為30秒
? ? ? ? ? ? .withScriptTimeout(30) ? ?// 腳本執行超時設置為30秒 ?
? ? ? ? ? ? .withImplicitWait(10) ? ? // 查找元素隱式等待10秒
? ? ? ? ? ? .withProxy(proxyHost, proxyPort) ? ? ? ? ? // 設置快代理的主機和端口
? ? ? ? ? ? .withProxyAuth(proxyUsername, proxyPassword); ?// 設置代理認證信息
? ? ? ??
? ? ? ? WebDriver driver = null;
? ? ? ? try {
? ? ? ? ? ? // 創建Edge瀏覽器實例,也可以選擇Chrome或Firefox
? ? ? ? ? ? log.info("正在初始化WebDriver...");
? ? ? ? ? ? driver = factory.createWebDriver(WebDriverFactory.BrowserType.EDGE);
? ? ? ? ? ??
? ? ? ? ? ? // 開始爬蟲任務
? ? ? ? ? ? crawlWebsite(driver);
? ? ? ? ? ??
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? // 異常處理,記錄詳細錯誤信息便于排錯
? ? ? ? ? ? log.error("爬蟲執行出錯: {}", e.getMessage(), e);
? ? ? ? } finally {
? ? ? ? ? ? // 確保WebDriver正確關閉,避免資源泄露
? ? ? ? ? ? if (driver != null) {
? ? ? ? ? ? ? ? driver.quit();
? ? ? ? ? ? ? ? log.info("WebDriver已關閉,爬蟲任務結束");
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ??
? ? /**
? ? ?* 爬蟲核心邏輯,可根據實際需求擴展
? ? ?*?
? ? ?* @param driver 已配置好的WebDriver實例
? ? ?* @throws InterruptedException 如果線程休眠被中斷
? ? ?*/
? ? private static void crawlWebsite(WebDriver driver) throws InterruptedException {
? ? ? ? // 訪問目標網站
? ? ? ? log.info("開始訪問目標網站");
? ? ? ? driver.get("https://www.baidu.com");
? ? ? ? log.info("網頁標題: {}", driver.getTitle());
? ? ? ??
? ? ? ? // 顯式等待某個元素出現,確保頁面加載完成
? ? ? ? // 比簡單的Thread.sleep更智能
? ? ? ? WebDriverWait wait = new WebDriverWait(driver, 10);
? ? ? ? wait.until(ExpectedConditions.presenceOfElementLocated(By.tagName("body")));
? ? ? ??
? ? ? ? // 獲取頁面內容示例:提取所有鏈接
? ? ? ? log.info("開始提取頁面鏈接");
? ? ? ? List<WebElement> links = driver.findElements(By.tagName("a"));
? ? ? ? log.info("共發現{}個鏈接", links.size());
? ? ? ??
? ? ? ? // 處理提取到的鏈接
? ? ? ? for (WebElement link : links) {
? ? ? ? ? ? String text = link.getText().trim();
? ? ? ? ? ? String href = link.getAttribute("href");
? ? ? ? ? ? // 只記錄有效鏈接
? ? ? ? ? ? if (href != null && !href.isEmpty()) {
? ? ? ? ? ? ? ? log.info("鏈接: {} -> {}", text.isEmpty() ? "[無文本]" : text, href);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ??
? ? ? ? // 模擬更多爬蟲操作,例如點擊某個元素、填寫表單等
? ? ? ? // 這里作為示例,只是簡單等待
? ? ? ? log.info("等待頁面進一步處理...");
? ? ? ? Thread.sleep(2000);
? ? ? ??
? ? ? ? // 如果需要,可以繼續訪問更多頁面
? ? ? ? // driver.get("https://www.another-site.com");
? ? ? ? // ...
? ? ? ??
? ? ? ? log.info("爬蟲任務完成");
? ? }
}

4.3 配置代理的注意事項
在使用代理時,需要注意以下幾點:

選擇合適的代理類型:隧道代理適合大規模爬蟲,普通代理適合小規模測試
正確配置認證信息:確保用戶名和密碼正確,特殊字符需要URL編碼
測試代理連通性:使用前先測試代理是否可用
合理設置請求頻率:遵循代理服務商的使用建議,避免觸發反爬機制
注意IP切換時機:適時切換IP,避免同一IP頻繁訪問目標網站
六、總結與展望
本文詳細介紹了如何使用Java+Selenium+快代理實現高效的網頁爬蟲。通過工廠模式和構建器模式的應用,我們實現了一個靈活、可擴展且易于使用的爬蟲框架。該框架解決了代理認證配置的難題,優化了瀏覽器參數設置,提高了爬蟲的穩定性和效率。

Selenium與代理服務的結合為我們提供了強大的爬蟲能力:Selenium模擬真實用戶行為應對JavaScript渲染和復雜交互,而快代理則提供了穩定的IP資源池,有效規避IP封禁和地域限制問題。這種組合特別適合需要處理登錄驗證、動態加載內容或有反爬措施的網站。

在實際應用中,請務必遵守相關法律法規和網站的使用條款,合理設置爬蟲的請求頻率和數量,避免對目標網站造成不必要的負擔。同時,定期更新Selenium和WebDriver版本,以適應瀏覽器的更新和網站的變化。

如果你在使用過程中遇到問題,可以參考快代理或查閱Selenium的相關資料。希望本文對你的爬蟲開發有所幫助!

最后,隨著網站反爬技術的不斷進化,爬蟲技術也需要持續更新迭代。未來,我們可以考慮結合機器學習技術識別驗證碼,或通過更智能的策略調整爬取行為,使爬蟲更加智能和高效。

歡迎在評論區分享你的使用經驗和改進建議!


————————————————

? ? ? ? ? ? ? ? ? ? ? ? ? ? 版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
? ? ? ? ? ? ? ? ? ? ? ??
原文鏈接:https://blog.csdn.net/weixin_66401877/article/details/147825058

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

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

相關文章

【計算機視覺】OpenCV實戰項目:基于OpenCV的車牌識別系統深度解析

基于OpenCV的車牌識別系統深度解析 1. 項目概述2. 技術原理與算法設計2.1 圖像預處理1) 自適應光照補償2) 邊緣增強 2.2 車牌定位1) 顏色空間篩選2) 形態學操作3) 輪廓分析 2.3 字符分割1) 投影分析2) 連通域篩選 2.4 字符識別 3. 實戰部署指南3.1 環境配置3.2 項目代碼解析 4.…

Python核心數據類型全解析:字符串、列表、元組、字典與集合

導讀&#xff1a; Python 是一門功能強大且靈活的編程語言&#xff0c;而其核心數據類型是構建高效程序的基礎。本文深入剖析了 Python 的五大核心數據類型——字符串、列表、元組、字典和集合&#xff0c;結合實際應用場景與最佳實踐&#xff0c;幫助讀者全面掌握這些數據類型…

GPT-4.1和GPT-4.1-mini系列模型支持微調功能,助力企業級智能應用深度契合業務需求

微軟繼不久前發布GPT-4.1系列模型后&#xff0c;Azure OpenAI服務&#xff08;國際版&#xff09;現已正式開放對GPT-4.1和GPT-4.1-mini的微調功能&#xff0c;并通過Azure AI Foundry&#xff08;國際版&#xff09;提供完整的部署和管理解決方案。這一重大升級標志著企業級AI…

構造+簡單樹狀

昨日的牛客周賽算是比較簡單的&#xff0c;其中最后一道構造題目屬實眼前一亮。 倒數第二個題目也是一個很好的模擬題目&#xff08;考驗對二叉樹的理解和代碼的細節&#xff09; 給定每一層的節點個數&#xff0c;自己擬定一個父親節點&#xff0c;構造一個滿足條件的二叉樹。…

apache2的默認html修改

使用127.0.0.1的時候&#xff0c;默認打開的是index.html&#xff0c;可以通過配置文件修改成我們想要的html vi /etc/apache2/mods-enabled/dir.conf <IfModule mod_dir.c>DirectoryIndex WS.html index.html index.cgi index.pl index.php index.xhtml index.htm <…

mysql性能提升方法大匯總

前言 最近在開發自己的小程序的時候&#xff0c;由于業務功能對系統性能的要求很高&#xff0c;系統性能損耗又主要在mysql上&#xff0c;而業務功能的數據表很多&#xff0c;單表數據量也很大&#xff0c;又涉及到很多場景的數據查詢&#xff0c;所以我針對mysql調用做了優化…

多模態RAG與LlamaIndex——1.deepresearch調研

摘要 關鍵點&#xff1a; 多模態RAG技術通過結合文本、圖像、表格和視頻等多種數據類型&#xff0c;擴展了傳統RAG&#xff08;檢索增強生成&#xff09;的功能。LlamaIndex是一個開源框架&#xff0c;支持多模態RAG&#xff0c;提供處理文本和圖像的模型、嵌入和索引功能。研…

LabVIEW中算法開發的系統化解決方案與優化

在 LabVIEW 開發環境中&#xff0c;算法實現是連接硬件數據采集與上層應用的核心環節。由于圖形化編程范式與傳統文本語言存在差異&#xff0c;LabVIEW 中的算法開發需要特別關注執行效率、代碼可維護性以及與硬件資源的適配性。本文從算法架構設計、性能優化到工程實現&#x…

OpenCV中的光流估計方法詳解

文章目錄 一、引言二、核心算法原理1. 光流法基本概念2. 算法實現步驟 三、代碼實現詳解1. 初始化設置2. 特征點檢測3. 光流計算與軌跡繪制 四、實際應用效果五、優化方向六、結語 一、引言 在計算機視覺領域&#xff0c;運動目標跟蹤是一個重要的研究方向&#xff0c;廣泛應用…

零基礎入門MySQL:10分鐘搞定數據庫基本操作

&#x1f4da; 一、MySQL是什么&#xff1f; MySQL 是一個關系型數據庫管理系統&#xff08;簡單理解&#xff1a;用“表格”存儲數據的倉庫&#xff09;。 就像Excel表格一樣&#xff0c;數據按行和列整齊存放&#xff0c;方便快速查找和管理&#xff01; 為什么要學MySQL&a…

LeetCode 3335.字符串轉換后的長度 I:I先遞推

【LetMeFly】3335.字符串轉換后的長度 I&#xff1a;I先遞推 力扣題目鏈接&#xff1a;https://leetcode.cn/problems/total-characters-in-string-after-transformations-i/ 給你一個字符串 s 和一個整數 t&#xff0c;表示要執行的 轉換 次數。每次 轉換 需要根據以下規則替…

Linux 系統如何掛載U盤

一、問題描述 Linux系統不像Windows系統有圖形化界面&#xff0c;對于機房服務器安裝的Linux尤其如此&#xff0c;那么有時候需要拷貝U盤或者光盤的文件到Linux系統中去&#xff0c;與 Windows 系統自動為 U 盤分配盤符不同&#xff0c;Linux 系統需要手動將 U 盤掛載到指定目…

Qt進階開發:QTcpServer的詳解

文章目錄 一、QTcpServer 簡介二、常用成員函數的使用三、信號函數的使用四、虛函數的使用五、連接多客戶端-服務端示例一、QTcpServer 簡介 QTcpServer 是 Qt 網絡模塊中的一個核心類,用于實現 基于 TCP 協議的服務端(Server),它負責監聽端口、接收客戶端連接請求,并通過…

大項目k8s集群有多大規模,多少節點,有多少pod

1. 實際參與過生產級 K8s 集群 回答示例&#xff1a; 目前我負責的 K8s 集群規模為 300 個物理節點&#xff0c;分布在 3 個可用區&#xff08;AZ&#xff09;&#xff0c;采用多控制平面高可用架構。集群日常運行約 12,000 個 Pod&#xff0c;資源利用率保持在 65%-75%&#…

是 OpenCV 的 CUDA 模塊中用于在 GPU 上對圖像或矩陣進行轉置操作函數cv::cuda::transpose

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 cv::cuda::transpose 是 OpenCV 的 CUDA 模塊中的一個函數&#xff0c;用于在 GPU 上對圖像或矩陣進行轉置操作&#xff08;Transpose&#xff0…

使用 goaccess 分析 nginx 訪問日志

介紹 goaccess 是一個在本地解析日志的工具, 可以直接在命令行終端環境中使用 TUI 界面查看分析結果, 也可以導出為更加豐富的 HTML 頁面. 官網: https://goaccess.io/ 下載安裝 常見的 Linux 包管理器中都包含了 goaccess, 直接安裝就行. 以 Ubuntu 為例: sudo apt instal…

Google LLM prompt engineering(谷歌提示詞工程指南)

文章目錄 基本概念AI輸出配置&#xff1a;調整AI的回答方式輸出長度溫度&#xff08;Temperature&#xff09;Top-K和Top-P 提示技術&#xff1a;讓AI更好地理解你零樣本提示&#xff08;Zero-shot&#xff09;少樣本提示&#xff08;Few-shot&#xff09;系統提示&#xff08;…

簡單介紹Qt的屬性子系統

深入理解Qt的屬性系統 ? 筆者最近正在大規模的開發Qt的項目和工程&#xff0c;這里筆者需要指出的是&#xff0c;這個玩意在最常規的Qt開發中是相對比較少用的&#xff0c;筆者也只是在Qt的QPropertyAnimation需要動畫感知筆者設置的一個屬性的時候方才知道這個東西的。因此&…

NestJS 框架深度解析

框架功能分析 NestJS 是一個基于 Node.js 的漸進式框架&#xff0c;專為構建高效、可擴展的服務器端應用程序而設計。其核心理念結合了 面向對象編程&#xff08;OOP&#xff09;、函數式編程&#xff08;FP&#xff09; 和 函數式響應式編程&#xff08;FRP&#xff09;&…

PostgreSQL技術大講堂 - 第89講:重講數據庫完全恢復

PostgreSQL技術大講堂 - 第89講&#xff0c;主題&#xff1a;重講數據庫完全恢復 時間&#xff1a;2025年05月10日19:30 歡迎持續關注CUUG PostgreSQL技術大講堂。