一、前言
在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