网站首页 > 技术文章 正文
一、前言
在 Web 爬虫技术中,Selenium 作为一款强大的浏览器自动化工具,能够模拟真实用户操作,有效应对 JavaScript 渲染、Ajax 加载等复杂场景。而集成代理服务则能够解决 IP 限制、地域访问限制等问题。
本文将详细介绍如何利用 Java+Selenium+快代理实现高效的爬虫系统。
二、Selenium简介
Selenium 是一个用于 Web 应用程序自动化测试的工具集,它主要用于自动化浏览器操作,可以模拟用户与网页的交互行为,如点击按钮、填写表单、滚动页面等。在爬虫领域,Selenium 特别适合处理那些需要 JavaScript 渲染、需要登录或有反爬措施的网站。
三、环境准备
- o JDK1.8 #技术分享 #掘金
- o Maven项目管理
- o 相关依赖
<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;
publicclassWebDriverFactory { privatestaticfinalLoggerlog= LoggerFactory.getLogger(WebDriverFactory.class); privatebooleanheadless=true; privateintpageLoadTimeoutSeconds=30; privateintscriptTimeoutSeconds=30; privateintimplicitWaitSeconds=10; privatebooleanproxyEnabled=false; private String proxyHost; privateint proxyPort; private String proxyUsername; private String proxyPassword; publicenumBrowserType { CHROME, EDGE, FIREFOX } public WebDriverFactory withHeadless(boolean headless) { this.headless = headless; returnthis; } public WebDriverFactory withPageLoadTimeout(int seconds) { this.pageLoadTimeoutSeconds = seconds; returnthis; } public WebDriverFactory withScriptTimeout(int seconds) { this.scriptTimeoutSeconds = seconds; returnthis; } public WebDriverFactory withImplicitWait(int seconds) { this.implicitWaitSeconds = seconds; returnthis; } public WebDriverFactory withProxy(String host, int port) { this.proxyEnabled = true; this.proxyHost = host; this.proxyPort = port; returnthis; } public WebDriverFactory withProxyAuth(String username, String password) { this.proxyUsername = username; this.proxyPassword = password; returnthis; } public WebDriver createWebDriver(BrowserType browserType) { switch (browserType) { case CHROME: return createChromeDriver(); case EDGE: return createEdgeDriver(); case FIREFOX: return createFirefoxDriver(); default: log.info("未指定浏览器类型,默认使用 Edge 浏览器"); return createEdgeDriver(); } } private WebDriver createEdgeDriver() { WebDriverManager.edgedriver().setup(); EdgeOptionsoptions=newEdgeOptions(); Map<String, Object> edgePrefs = newHashMap<>(); edgePrefs.put("useAutomationExtension", false); List<String> args = getCommonBrowserArgs(); Map<String, Object> edgeOptions = newHashMap<>(); edgeOptions.put("args", args); 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"); options.setPageLoadStrategy(PageLoadStrategy.NORMAL); options.setCapability("ms:edgeChromium", true); options.setCapability("ms:edgeOptions", edgeOptions); options.setCapability("inPrivate", true); configureProxy(options); WebDriverdriver=newEdgeDriver(options); configureTimeouts(driver); log.info("Edge WebDriver 创建成功"); return driver; } private WebDriver createChromeDriver() { WebDriverManager.chromedriver().setup(); ChromeOptionsoptions=newChromeOptions(); if (headless) { options.addArguments("--headless"); } for (String arg : getCommonBrowserArgs()) { options.addArguments(arg); } options.setPageLoadStrategy(PageLoadStrategy.NORMAL); configureProxyForChrome(options); WebDriverdriver=newChromeDriver(options); configureTimeouts(driver); log.info("Chrome WebDriver 创建成功"); return driver; } private WebDriver createFirefoxDriver() { WebDriverManager.firefoxdriver().setup(); FirefoxOptionsoptions=newFirefoxOptions(); if (headless) { options.addArguments("--headless"); } configureProxy(options); WebDriverdriver=newFirefoxDriver(options); configureTimeouts(driver); log.info("Firefox WebDriver 创建成功"); return driver; } private List<String> getCommonBrowserArgs() { List<String> args = newArrayList<>(); if (headless) { args.add("--headless"); args.add("--disable-gpu"); } args.add("--disable-extensions"); args.add("--blink-settings=imagesEnabled=false"); 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"); args.add("--disable-accelerated-2d-canvas"); 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"); args.add("--js-flags=--max-old-space-size=512"); return args; } privatevoidconfigureProxy(Object options) { if (proxyEnabled && proxyHost != null && !proxyHost.isEmpty() && proxyPort > 0) { try { String proxyUrl; if (proxyUsername != null && !proxyUsername.isEmpty() && proxyPassword != null) { proxyUrl = "http://" +
} else { proxyUrl = "http://" +
} Proxyproxy=newProxy(); proxy.setHttpProxy(proxyUrl); proxy.setSslProxy(proxyUrl); if (options instanceof EdgeOptions) { ((EdgeOptions) options).setCapability(CapabilityType.PROXY, proxy); } elseif (options instanceof FirefoxOptions) { ((FirefoxOptions) options).setCapability(CapabilityType.PROXY, proxy); } log.info("WebDriver 配置了代理: {}", proxyHost +
} catch (Exception e) { log.error("配置代理时出错: {}", e.getMessage()); } } } privatevoidconfigureProxyForChrome(ChromeOptions options) { if (proxyEnabled && proxyHost != null && !proxyHost.isEmpty() && proxyPort > 0) { try { String proxyUrl; if (proxyUsername != null && !proxyUsername.isEmpty() && proxyPassword != null) { proxyUrl = "http://" +
} else { proxyUrl = "http://" +
} Proxyproxy=newProxy(); proxy.setHttpProxy(proxyUrl); proxy.setSslProxy(proxyUrl); options.setCapability(CapabilityType.PROXY, proxy); log.info("Chrome WebDriver 配置了代理: {}", proxyHost +
} catch (Exception e) { log.error("配置 Chrome 代理时出错: {}", e.getMessage()); } } } privatevoidconfigureTimeouts(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;
publicclassSeleniumCrawler { privatestaticfinalLoggerlog= LoggerFactory.getLogger(SeleniumCrawler.class); publicstaticvoidmain(String[] args) { StringproxyHost=""; intproxyPort=15818; StringproxyUsername="yourUsername"; StringproxyPassword="yourPassword"; WebDriverFactoryfactory=newWebDriverFactory() .withHeadless(false) .withPageLoadTimeout(30) .withScriptTimeout(30) .withImplicitWait(10) .withProxy(proxyHost, proxyPort) .withProxyAuth(proxyUsername, proxyPassword); WebDriverdriver=null; try { log.info("正在初始化 WebDriver..."); driver = factory.createWebDriver(WebDriverFactory.BrowserType.EDGE); crawlWebsite(driver); } catch (Exception e) { log.error("爬虫执行出错: {}", e.getMessage(), e); } finally { if (driver != null) { driver.quit(); log.info("WebDriver 已关闭,爬虫任务结束"); } } } privatestaticvoidcrawlWebsite(WebDriver driver)throws InterruptedException { log.info("开始访问目标网站"); driver.get("https://www.baidu.com"); log.info("网页标题: {}", driver.getTitle()); WebDriverWaitwait=newWebDriverWait(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) { Stringtext= link.getText().trim(); Stringhref= link.getAttribute("href"); if (href != null && !href.isEmpty()) { log.info("链接: {} -> {}", text.isEmpty() ? "[无文本]" : text, href); } } log.info("等待页面进一步处理..."); Thread.sleep(2000); log.info("爬虫任务完成"); } }
4.3 配置代理的注意事项
在使用代理时,需要注意以下几点:
- o 选择合适的代理类型: 隧道代理适合大规模爬虫,普通代理适合小规模测试
- o 正确配置认证信息: 确保用户名和密码正确,特殊字符需要URL编码
- o 测试代理连通性: 使用前先测试代理是否可用
- o 合理设置请求频率: 遵循代理服务商的使用建议,避免触发反爬机制
- o 注意IP切换时机: 适时切换IP,避免同一IP频繁访问目标网站
六、总结与展望
本文详细介绍了如何使用 Java+Selenium+快代理实现高效的网页爬虫。通过工厂模式和构建器模式的应用,我们实现了一个灵活、可扩展且易于使用的爬虫框架。该框架解决了代理认证配置的难题,优化了浏览器参数设置,提高了爬虫的稳定性和效率。
Selenium 与代理服务的结合为我们提供了强大的爬虫能力:Selenium 模拟真实用户行为应对 JavaScript 渲染和复杂交互,而快代理则提供了稳定的 IP 资源池,有效规避 IP 封禁和地域限制问题。这种组合特别适合需要处理登录验证、动态加载内容或有反爬措施的网站。
在实际应用中,请务必遵守相关法律法规和网站的使用条款,合理设置爬虫的请求频率和数量,避免对目标网站造成不必要的负担。同时,定期更新 Selenium 和 WebDriver 版本,以适应浏览器的更新和网站的变化。
如果你在使用过程中遇到问题,可以参考快代理或查阅 Selenium 的相关资料。希望本文对你的爬虫开发有所帮助!
最后,随着网站反爬技术的不断进化,爬虫技术也需要持续更新迭代。未来,我们可以考虑结合机器学习技术识别验证码,或通过更智能的策略调整爬取行为,使爬虫更加智能和高效。
猜你喜欢
- 2025-08-03 隐式等待、显示等待和强制等待
- 2025-08-03 零基础C#上位机框架项目实例(完结篇)
- 2025-08-03 一文搞懂构建Web内容的技术
- 2025-08-03 西门子WINCC中的VBScript(VBS)常用于自动化脚本开发
- 2025-08-03 力控和sql2000之间的数据转储
- 2025-08-03 组态王|通过日历控件选择时间段查询历史报警
- 2025-08-03 怎样添加、移除、移动、复制、创建和查找节点?
- 2025-08-03 常见的10种WEB页面元素定位方法及其特点
- 2025-08-03 Vue3 前端监控神器!3000 字实战指南教你秒级定位 Web 性能问题
- 2025-08-03 [汇川PLC] 威纶通宏指令设置当前时间到汇川AM523
- 08-03MySQL数据库的预处理详解
- 08-03《阿常·MySQL 70讲》全套教学视频
- 08-03隐式等待、显示等待和强制等待
- 08-03零基础C#上位机框架项目实例(完结篇)
- 08-03一文搞懂构建Web内容的技术
- 08-03西门子WINCC中的VBScript(VBS)常用于自动化脚本开发
- 08-03力控和sql2000之间的数据转储
- 08-03组态王|通过日历控件选择时间段查询历史报警
- 1521℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 626℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 527℃MySQL service启动脚本浅析(r12笔记第59天)
- 492℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 492℃启用MySQL查询缓存(mysql8.0查询缓存)
- 479℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 461℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 458℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- windowsscripthost (69)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- htmlbackground-image (68)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)