Java Jsoup 与 Selenium 对比:3 种动态网页数据抓取方案性能实测

发布时间:2026/7/9 21:00:35

Java Jsoup 与 Selenium 对比:3 种动态网页数据抓取方案性能实测
Java Jsoup 与 Selenium 对比3 种动态网页数据抓取方案性能实测现代网页越来越多地采用JavaScript动态渲染技术这对传统的数据抓取工具提出了新的挑战。本文将深入对比三种主流Java网页抓取方案纯Jsoup静态解析、Selenium动态渲染以及Jsoup直接调用后端API混合模式通过携程旅游网的实际案例分析各方案在开发复杂度、执行效率、资源消耗和反爬虫规避能力等维度的表现差异。1. 技术方案概述与核心差异在开始性能对比前我们需要明确三种技术方案的基本工作原理和适用场景。1.1 Jsoup静态解析方案Jsoup是一款轻量级Java HTML解析器主要特点包括纯静态解析只能获取服务器返回的初始HTML无法执行JavaScriptCSS选择器API类似jQuery的DOM操作方式简单易用学习曲线平缓适合简单静态页面// 典型Jsoup使用示例 Document doc Jsoup.connect(https://hotels.ctrip.com) .timeout(10000) .get(); Elements hotels doc.select(.hotel-item);1.2 Selenium动态渲染方案Selenium WebDriver是浏览器自动化测试工具其核心优势在于完整浏览器环境可执行JavaScript并渲染最终DOM真实用户模拟能处理复杂交互和动态内容多语言支持支持Java、Python等多种语言// Selenium基本配置 WebDriver driver new ChromeDriver(); driver.get(https://hotels.ctrip.com); WebElement searchBtn driver.findElement(By.cssSelector(.search-btn)); searchBtn.click();1.3 JsoupAPI混合方案这种创新方案结合了两者优点使用浏览器开发者工具分析XHR请求直接调用网站后端数据接口用Jsoup解析返回的JSON/HTML// 调用携程城市列表API示例 String apiUrl https://m.ctrip.com/restapi/soa2/13434/json/getDomesticCityList; Document apiResponse Jsoup.connect(apiUrl) .ignoreContentType(true) .execute() .parse();1.4 三方案核心技术对比特性Jsoup静态解析Selenium动态渲染JsoupAPI混合JavaScript执行能力❌ 不支持✅ 完整支持⚠️ 部分支持初始加载速度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐反爬虫规避能力⭐⭐⭐⭐⭐⭐⭐⭐⭐资源消耗低(10-50MB)高(500MB)中(100MB左右)开发复杂度简单复杂中等提示选择方案时需要权衡动态内容需求与系统资源限制对于纯数据展示型页面API混合方案往往是最优解。2. 开发复杂度与实现细节对比不同方案在实现相同功能时代码结构和维护成本存在显著差异。我们以抓取携程酒店列表为例进行具体分析。2.1 Jsoup静态解析实现静态解析方案代码最为简洁但可能无法获取关键数据public ListHotel parseHotelsWithJsoup(String url) throws IOException { ListHotel hotels new ArrayList(); Document doc Jsoup.connect(url) .userAgent(Mozilla/5.0) .get(); // 可能无法获取动态渲染的酒店列表 Elements items doc.select(.hotel-item); for (Element item : items) { Hotel hotel new Hotel(); hotel.setName(item.select(.hotel-name).text()); // 其他字段可能缺失... hotels.add(hotel); } return hotels; }主要痛点动态生成的内容无法获取分页逻辑需要手动构造URL缺乏交互能力如点击展开更多信息2.2 Selenium动态渲染实现Selenium能获取完整数据但代码复杂度显著提升public ListHotel parseHotelsWithSelenium(String url) { WebDriver driver new ChromeDriver(); driver.get(url); // 等待动态内容加载 WebDriverWait wait new WebDriverWait(driver, Duration.ofSeconds(10)); wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(.hotel-item))); // 模拟滚动加载更多 for (int i 0; i 3; i) { ((JavascriptExecutor)driver).executeScript(window.scrollTo(0, document.body.scrollHeight)); wait.until(ExpectedConditions.numberOfElementsToBeMoreThan(By.cssSelector(.hotel-item), i * 20)); } ListWebElement items driver.findElements(By.cssSelector(.hotel-item)); ListHotel hotels new ArrayList(); for (WebElement item : items) { Hotel hotel new Hotel(); hotel.setName(item.findElement(By.cssSelector(.hotel-name)).getText()); // 获取完整信息 hotels.add(hotel); } driver.quit(); return hotels; }开发难点需要处理各种等待条件页面交互逻辑复杂浏览器实例管理繁琐2.3 JsoupAPI混合实现混合方案需要逆向分析接口但代码相对简洁public ListHotel parseHotelsWithHybrid(String apiUrl) throws IOException { // 模拟实际请求参数 String requestBody {\pageIndex\:1,\pageSize\:50,\cityId\:1}; Document doc Jsoup.connect(apiUrl) .header(Content-Type, application/json) .requestBody(requestBody) .ignoreContentType(true) .post(); // 解析JSON响应 JSONObject json new JSONObject(doc.body().text()); JSONArray data json.getJSONArray(data); ListHotel hotels new ArrayList(); for (int i 0; i data.length(); i) { JSONObject item data.getJSONObject(i); Hotel hotel new Hotel(); hotel.setName(item.getString(hotelName)); // 直接获取所有字段 hotels.add(hotel); } return hotels; }关键优势数据获取完整且结构化无需处理页面渲染分页等逻辑通过参数控制2.4 三种方案开发效率对比开发阶段Jsoup静态解析Selenium动态渲染JsoupAPI混合环境搭建10分钟30分钟15分钟基础数据抓取1小时2小时2小时*动态内容处理无法实现额外1-2小时30分钟反爬虫规避有限手段多种策略中等灵活性长期维护成本低高中*注API混合方案初期需要时间分析接口但后续开发效率显著提升3. 性能实测与数据分析我们设计了一套标准测试方案在同一网络环境下对三种技术进行性能对比。测试目标为抓取携程旅游网50页酒店数据约1000条记录。3.1 测试环境配置硬件MacBook Pro M1, 16GB内存网络企业级宽带延迟50ms软件版本Jsoup 1.15.3Selenium 4.8.0 ChromeDriver 112JDK 173.2 关键性能指标对比指标Jsoup静态解析Selenium动态渲染JsoupAPI混合平均请求耗时(ms)3204200280内存占用峰值(MB)35580120CPU使用率峰值(%)158530完整任务耗时(s)4232638数据完整度(%)6210098成功率(%)889592关键发现Selenium资源消耗是其他方案的10-15倍API混合方案在速度上接近纯Jsoup但数据完整度显著提升静态解析方案有近40%的数据缺失3.3 典型场景性能曲线通过JMeter进行压力测试观察各方案在不同并发下的表现吞吐量对比(requests/second)Jsoup静态解析28 req/sSelenium动态渲染3 req/sJsoupAPI混合25 req/s错误率随并发增长趋势Selenium在并发5时错误率急剧上升其他两种方案在并发20时保持稳定3.4 反爬虫机制影响我们模拟了三种常见的反爬虫策略对各方案的影响User-Agent检测所有方案都需要配置合法UASelenium默认UA容易被识别行为指纹检测Selenium可通过stealth.js等工具规避Jsoup需要模拟鼠标移动等事件较困难请求频率限制Selenium受影响最大资源消耗高API混合方案最容易实现分布式抓取// Selenium反检测配置示例 ChromeOptions options new ChromeOptions(); options.addArguments(--disable-blink-featuresAutomationControlled); options.setExperimentalOption(excludeSwitches, Collections.singletonList(enable-automation)); WebDriver driver new ChromeDriver(options); // 执行反检测脚本 ((JavascriptExecutor)driver).executeScript(stealthJsScript);4. 实战案例携程旅游数据抓取下面我们通过具体案例展示三种方案实现携程旅游数据抓取的完整流程。4.1 目标数据分析携程旅游网主要数据接口包括城市列表API/getDomesticCityList酒店搜索API/hotel/search景点信息API/spot/search页面结构特点首屏内容服务器端渲染详情数据动态加载分页采用滚动加载4.2 Jsoup静态解析实现适合获取基础城市信息等静态内容public ListCity parseCitiesWithJsoup() throws IOException { Document doc Jsoup.connect(https://hotels.ctrip.com/citylist) .timeout(10000) .get(); ListCity cities new ArrayList(); Elements cityElements doc.select(.city_item); for (Element cityEl : cityElements) { City city new City(); city.setName(cityEl.select(.city_name).text()); city.setPinyin(cityEl.attr(data-pinyin)); cities.add(city); } return cities; }局限性无法获取酒店实时价格等动态数据4.3 Selenium动态渲染实现完整获取酒店列表及价格信息public ListHotel parseHotelsWithSelenium(String cityCode) { ChromeOptions options new ChromeOptions(); options.addArguments(--headlessnew); WebDriver driver new ChromeDriver(options); String url https://hotels.ctrip.com/hotel/ cityCode; driver.get(url); // 等待价格加载 new WebDriverWait(driver, Duration.ofSeconds(10)) .until(d - d.findElements(By.cssSelector(.price_num)).size() 0); // 模拟滚动加载3次 for (int i 0; i 3; i) { ((JavascriptExecutor)driver).executeScript( window.scrollTo(0, document.body.scrollHeight);); try { Thread.sleep(2000); } catch (Exception e) {} } ListWebElement items driver.findElements(By.cssSelector(.hotel_item)); ListHotel hotels new ArrayList(); for (WebElement item : items) { Hotel hotel new Hotel(); hotel.setName(item.findElement(By.cssSelector(.hotel_name)).getText()); hotel.setPrice(item.findElement(By.cssSelector(.price_num)).getText()); hotels.add(hotel); } driver.quit(); return hotels; }4.4 JsoupAPI混合实现最优方案结合两者优势public ListHotel parseHotelsWithApi(String cityCode) throws IOException { String apiUrl https://m.ctrip.com/restapi/soa2/13434/json/HotelListSearch; // 构造精确请求参数 String requestBody String.format({\cityId\:\%s\,\pageIndex\:1,\pageSize\:50}, cityCode); Document doc Jsoup.connect(apiUrl) .header(Content-Type, application/json) .header(Referer, https://m.ctrip.com/) .requestBody(requestBody) .ignoreContentType(true) .post(); JSONObject json new JSONObject(doc.body().text()); JSONArray hotelsJson json.getJSONObject(data).getJSONArray(hotelList); ListHotel hotels new ArrayList(); for (int i 0; i hotelsJson.length(); i) { JSONObject hotelJson hotelsJson.getJSONObject(i); Hotel hotel new Hotel(); hotel.setName(hotelJson.getString(hotelName)); hotel.setPrice(hotelJson.getJSONObject(priceInfo).getString(actualPrice)); hotels.add(hotel); } return hotels; }4.5 异常处理与日志记录无论采用哪种方案健壮的异常处理都必不可少try { // 尝试主请求 Document doc Jsoup.connect(url) .timeout(10000) .get(); } catch (SocketTimeoutException e) { logger.warn(请求超时尝试重试...); // 重试逻辑 } catch (HttpStatusException e) { logger.error(HTTP错误: e.getStatusCode()); // 处理特定状态码 } catch (IOException e) { logger.error(IO异常, e); // 其他处理 } // Selenium的异常处理 try { WebElement element driver.findElement(By.cssSelector(.hotel_name)); } catch (NoSuchElementException e) { logger.warn(元素未找到检查页面结构是否变化); // 备用选择器或重试 } catch (StaleElementReferenceException e) { logger.warn(元素状态过期重新获取); // 重新查找元素 }5. 技术选型建议与优化策略根据实测结果和实战经验我们总结出以下技术选型指南。5.1 方案选择决策树是否需要交互操作是 → 选择Selenium否 → 进入下一判断数据是否通过API获取是 → 优先选择API混合方案否 → 进入下一判断数据是否为静态内容是 → 选择Jsoup静态解析否 → 只能选择Selenium5.2 性能优化技巧通用优化策略合理设置超时时间通常5-10秒使用连接池复用HTTP连接实现请求重试机制Jsoup特定优化// 启用gzip压缩 Connection conn Jsoup.connect(url) .header(Accept-Encoding, gzip); // 复用cookies MapString, String cookies response.cookies(); Document doc2 Jsoup.connect(url2) .cookies(cookies) .get();Selenium特定优化// 启用无头模式 ChromeOptions options new ChromeOptions(); options.addArguments(--headlessnew); // 禁用图片加载 options.setExperimentalOption(prefs, Map.of( profile.managed_default_content_settings.images, 2 )); // 使用CDP协议拦截不必要请求 devTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty())); devTools.send(Network.setBlockedURLs(List.of(*.jpg, *.png, *.gif)));5.3 反爬虫规避方案防护措施Jsoup应对方案Selenium应对方案API混合方案应对User-Agent检测随机轮换UA使用常见UA模拟移动端UAIP限制使用代理池使用代理浏览器指纹分布式抓取架构行为分析模拟人类请求间隔添加随机鼠标移动轨迹控制合理请求频率验证码第三方打码服务自动化识别或人工打码尽量避免触发验证码TLS指纹检测使用okhttp等现代库无需特别处理使用最新HTTP客户端5.4 扩展性与维护性代码组织建议抽象基础抓取逻辑为父类不同网站实现特定解析器配置与代码分离public abstract class BaseCrawler { protected abstract ListItem parse(Document doc); public ListItem crawl(String url) throws IOException { Document doc fetchDocument(url); return parse(doc); } protected Document fetchDocument(String url) throws IOException { return Jsoup.connect(url) .timeout(10000) .get(); } } public class CtripHotelCrawler extends BaseCrawler { Override protected ListHotel parse(Document doc) { // 实现携程特定解析逻辑 } }监控与告警成功率监控响应时间监控数据质量校验自动恢复机制在实际项目中我们通常会根据业务需求混合使用多种技术方案。例如用Selenium处理登录和获取cookies然后用JsoupAPI进行大规模数据抓取或者对关键数据使用Selenium验证常规数据使用API获取。这种混合策略能够在保证数据质量的同时最大化抓取效率。

相关新闻

C#适配器模式与扩展方法:优雅解决接口不兼容问题

C#适配器模式与扩展方法:优雅解决接口不兼容问题

2026/7/9 21:00:35

1. 项目概述:当设计模式遇上C#语法糖最近在重构一个遗留的上位机数据采集系统时,我遇到了一个典型的“接口不兼容”难题。系统里有一个老旧的第三方硬件驱动库,它的数据上报接口是一堆基于事件回调的、参数复杂的委托方法。而我的新业务模块&…

Windows下JDK 21/17环境变量配置实操指南

Windows下JDK 21/17环境变量配置实操指南

2026/7/9 21:00:35

1. 这不是“又一个JDK教程”,而是你真正能一次配通的实操现场记录如果你搜到这篇内容,大概率正卡在某个环节:下载页面找不到对应版本、安装完Java -version报错、环境变量改了八遍还是提示“不是内部或外部命令”、IDEA里新建项目疯狂报红………

影刀RPA OAuth2.0认证流程实现:授权码模式与客户端模式详解

影刀RPA OAuth2.0认证流程实现:授权码模式与客户端模式详解

2026/7/9 20:50:35

影刀RPA OAuth2.0认证流程实现:授权码模式与客户端模式详解 作者:林焱 调用第三方API时,很多平台要求OAuth2.0认证——先获取access_token,再用token调接口。这篇把最常见的两种OAuth2.0模式讲清楚,并给出在影刀Pyth…

OpenCV 4.8 亚像素边缘检测实战:高斯与线性插值对比,精度提升至1/25像素

OpenCV 4.8 亚像素边缘检测实战:高斯与线性插值对比,精度提升至1/25像素

2026/7/9 22:20:38

OpenCV 4.8 亚像素边缘检测实战:高斯与线性插值对比,精度提升至1/25像素在工业检测、医学影像和自动驾驶等领域,边缘检测的精度往往直接决定整个系统的性能上限。传统像素级边缘检测受限于传感器物理分辨率,当需要测量微米级位移或…

TT马达 3V-6V 直流减速电机选型指南:1:48/1:120/1:220 三档减速比实测对比

TT马达 3V-6V 直流减速电机选型指南:1:48/1:120/1:220 三档减速比实测对比

2026/7/9 22:20:38

TT马达3V-6V直流减速电机深度选型指南:1:48/1:120/1:220减速比性能实测与应用场景解析在智能小车、教育机器人等创客项目中,电机选型往往是决定项目成败的关键因素之一。作为市面上最常见的直流减速电机类型,TT马达以其亲民的价格、稳定的性能…

Godot4 2D灯光系统实战:从PointLight2D到性能优化的完整工作流

Godot4 2D灯光系统实战:从PointLight2D到性能优化的完整工作流

2026/7/9 22:20:38

1. 项目概述:为什么你需要深入理解Godot4的2D灯光系统? 如果你正在用Godot4开发2D游戏,并且希望你的场景不仅仅是平铺的精灵,而是拥有氛围、深度和沉浸感,那么灯光系统就是你绕不开的核心工具。很多开发者初次接触Godo…

Unity热更新实战:HybridCLR核心原理、环境配置与真机调试全解析

Unity热更新实战:HybridCLR核心原理、环境配置与真机调试全解析

2026/7/9 22:20:38

1. 项目概述:为什么HybridCLR是Unity热更新的“硬核”选择?在Unity项目,尤其是手游的漫长生命周期里,最让开发者头疼的莫过于“热更新”。想象一下,你的游戏上线后发现了一个致命Bug,或者想紧急上线一个节日…

MCP3551高精度ADC与PIC32MZ的嵌入式系统设计

MCP3551高精度ADC与PIC32MZ的嵌入式系统设计

2026/7/9 22:20:38

1. 项目背景与硬件选型解析在工业测量和精密仪器领域,22位高精度ADC的应用正变得越来越广泛。MCP3551作为Microchip推出的一款ΔΣ型模数转换器,其单周期转换特性和内置自动校准功能,使其成为低频信号测量的理想选择。与PIC32MZ2048EFM100这款…

Python 代码保护方案对比:PyArmor 8.4.4 加密 vs Cython 编译 vs Nuitka 打包

Python 代码保护方案对比:PyArmor 8.4.4 加密 vs Cython 编译 vs Nuitka 打包

2026/7/9 22:10:38

Python商业级代码保护方案全景评测:PyArmor vs Cython vs Nuitka当Python代码需要作为商业产品分发时,如何有效保护知识产权成为开发者必须面对的挑战。不同于传统编译型语言,Python的字节码相对容易被反编译,这使得代码保护方案的…

解锁AMD Ryzen处理器深层性能:SMU Debug Tool完全指南

解锁AMD Ryzen处理器深层性能:SMU Debug Tool完全指南

2026/7/9 19:40:56

解锁AMD Ryzen处理器深层性能:SMU Debug Tool完全指南 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://gi…

6个月转型AI工程师:实战路径与核心技能

6个月转型AI工程师:实战路径与核心技能

2026/7/9 18:28:30

1. 项目概述:6个月转型AI工程师的可行性路径在2023年大模型技术爆发的背景下,AI工程师岗位需求同比增长217%(LinkedIn数据)。不同于传统算法工程师需要3-5年培养周期,现代AI工程师更侧重工程化落地能力。我在硅谷科技公…

YOLOv5模型剪枝与量化实战:边缘设备部署优化

YOLOv5模型剪枝与量化实战:边缘设备部署优化

2026/7/8 14:04:34

1. 项目背景与核心价值在计算机视觉领域,YOLOv5因其出色的实时检测性能成为工业界宠儿。但当我们尝试将其部署到边缘设备(如树莓派、Jetson Nano或手机终端)时,立刻会遇到两个致命问题:模型体积庞大(原始YO…

平价正宗重庆火锅实测|理性避坑选型指南

平价正宗重庆火锅实测|理性避坑选型指南

2026/7/9 0:09:12

一、引言:重庆火锅消费现存痛点当下大众平价川渝火锅赛道竞争白热化,普通消费者就餐普遍面临三大选型难题:一是口味同质化严重,大量门店采用预制锅底、半成品食材,打着重庆老火锅旗号弱化牛油本味,麻辣口感…

AcFunDown:打破A站视频离线观看壁垒的终极解决方案

AcFunDown:打破A站视频离线观看壁垒的终极解决方案

2026/7/9 0:09:12

AcFunDown:打破A站视频离线观看壁垒的终极解决方案 【免费下载链接】AcFunDown 包含PC端UI界面的A站 视频下载器。支持收藏夹、UP主视频批量下载 😳仅供交流学习使用喔 项目地址: https://gitcode.com/gh_mirrors/ac/AcFunDown 想象一下这样的场景…

【复现】面向新能源消纳能力评估的年负荷序列建模及场景生成方法(Matlab代码实现)

【复现】面向新能源消纳能力评估的年负荷序列建模及场景生成方法(Matlab代码实现)

2026/7/9 0:09:12

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 &#x1f381…