news 2026/5/16 11:53:26

使用Jsoup爬取网页中的新闻与图片链接

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用Jsoup爬取网页中的新闻与图片链接

使用 Jsoup 爬取网页中的新闻与图片链接

在信息聚合、内容监控和数据挖掘的日常开发中,如何从结构化的网页中高效提取图文内容,是许多 Java 工程师面临的实际问题。Jsoup 作为一款轻量级且功能强大的 HTML 解析库,凭借其类 jQuery 的选择器语法和对 DOM 操作的良好支持,成为 Java 生态中最受欢迎的爬虫工具之一。

本文将带你深入实战场景,以曲阜师范大学官网为例,逐步掌握如何使用 Jsoup 提取新闻正文、图片链接以及批量抓取首页列表数据。过程中不仅涵盖基础 API 用法,还会穿插工程实践中常见的陷阱与优化技巧,帮助你写出更稳定、更具可维护性的爬虫代码。


要开始使用 Jsoup,首先需要将其引入项目。如果你使用的是 Maven 构建系统,在pom.xml中添加如下依赖:

<dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.17.2</version> </dependency>

对于 Gradle 用户,则在build.gradle文件中加入:

implementation 'org.jsoup:jsoup:1.17.2'

依赖配置完成后,下一步就是连接目标网页。以下是一个典型的请求示例:

Document doc = Jsoup.connect("http://www.qfnu.edu.cn/") .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36") .timeout(10000) .get();

这里有几个关键点值得注意:
-userAgent设置了模拟浏览器的请求头,避免被服务器识别为机器人而拒绝访问;
-timeout(10000)设定了 10 秒超时,防止因网络异常导致线程阻塞;
- 最终返回的是一个Document对象,它代表了解析后的完整 HTML 文档树,后续所有元素提取都将基于此对象进行。

需要注意的是,某些网站启用了 HTTPS 并采用严格的证书校验机制。在测试环境中若遇到 SSL 异常,可以通过自定义信任管理器绕过验证(仅限调试用途):

SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{new X509TrustManager() { public void checkClientTrusted(X509Certificate[] chain, String authType) {} public void checkServerTrusted(X509Certificate[] chain, String authType) {} public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }}, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

生产环境应谨慎处理此类问题,建议配置可信 CA 或使用 HttpClient 替代方案。


当成功加载页面后,接下来的任务是从复杂的 HTML 结构中精准定位所需内容。假设我们要提取一篇新闻的正文文本,常见结构如下:

<div class="zw_content"> <p><span style="FONT-SIZE: 16px">8月30日,日照市常务副市长王斌一行人来我校进行调研...</span></p> <p><img src="/attach/2016/09/02/123920.jpg" /></p> </div>

最直接的方式是根据class属性定位容器:

Elements contentDivs = doc.getElementsByAttributeValue("class", "zw_content");

也可以使用更简洁的 CSS 选择器写法:

Element contentDiv = doc.selectFirst(".zw_content");

一旦获取到主体容器,调用.text()方法即可提取其中所有文本内容,Jsoup 会自动忽略标签并拼接段落:

String text = contentDiv.text(); System.out.println("【新闻内容】:" + text);

但如果希望保留图文顺序或分别处理文字与图像,则需进一步拆解内部结构。例如按<p>标签逐段分析:

Elements paragraphs = contentDiv.getElementsByTag("p"); for (Element p : paragraphs) { if (p.select("img").isEmpty()) { System.out.println("文字段落:" + p.text()); } else { String imgUrl = p.select("img").attr("src"); System.out.println("图片链接:" + "http://www.qfnu.edu.cn" + imgUrl); } }

这种方式适用于需要保持原始排版逻辑的场景,比如生成富文本摘要或构建图文混排的内容展示模块。

至于图片链接的提取,通常有两种需求:获取首图和获取全部图片。前者简单直接:

String firstImgSrc = contentDiv.select("img").first().attr("src"); System.out.println("主图地址:" + firstImgSrc);

而多图提取则需考虑边界情况——并非每条新闻都包含多张图片。为了避免IndexOutOfBoundsException,推荐使用安全遍历方式:

Elements imgs = contentDiv.select("img"); List<String> imageUrls = new ArrayList<>(); for (Element img : imgs) { String src = img.attr("src"); if (!src.isEmpty()) { imageUrls.add("http://www.qfnu.edu.cn" + src); } }

此外,相对路径转绝对路径是一个高频操作。除了手动拼接外,Jsoup 提供了absUrl方法自动补全协议和域名:

String absoluteUrl = img.absUrl("src"); // 输出:http://www.qfnu.edu.cn/attach/xxx.jpg

这一特性在处理不同来源页面时尤为实用,能有效减少硬编码错误。


面对首页新闻列表这类批量数据,单一提取已无法满足需求。观察典型结构:

<ul class="news-1-lists"> <li> <img src="/attach/2016/09/02/123921.jpg" title="我校在山东高校思政课讲课大赛中斩获佳绩" /> <a href="/html/xxyw/2016/09/02/4648a396-c778-4116-ae79-6e61039ad9a3.html">我校在山东高校思政课讲课大赛中斩获佳绩</a> </li> </ul>

我们的目标是同时提取标题、缩略图和跳转链接,并组合成完整的 URL。实现步骤如下:

  1. 定位外层容器:
Elements newsListUl = doc.getElementsByClass("news-1-lists");
  1. 遍历每个<li>条目并提取信息:
for (Element ul : newsListUl) { Elements newsItems = ul.getElementsByTag("li"); for (Element item : newsItems) { Element img = item.selectFirst("img"); String imgUrl = img != null ? img.attr("src") : ""; Element link = item.selectFirst("a"); String title = link != null ? link.hasAttr("title") ? link.attr("title") : link.text() : ""; String articleUrl = link != null ? link.attr("href") : ""; String fullImgUrl = "http://www.qfnu.edu.cn" + imgUrl; String fullArticleUrl = "http://www.qfnu.edu.cn" + articleUrl; System.out.printf("标题:%s | 图片:%s | 文章页:%s%n", title, fullImgUrl, fullArticleUrl); } }

输出结果类似:

标题:我校在山东高校思政课讲课大赛中斩获佳绩 | 图片:http://www.qfnu.edu.cn/attach/2016/09/02/123921.jpg | 文章页:http://www.qfnu.edu.cn/html/xxyw/2016/09/02/4648a396-c778-4116-ae79-6e61039ad9a3.html

为了便于后续处理,建议封装成实体类:

public class NewsItem { private String title; private String imageUrl; private String articleUrl; private String summary; // getter & setter }

然后将每条记录存入集合统一管理:

List<NewsItem> newsList = new ArrayList<>(); // ... 在循环中填充数据 newsList.add(new NewsItem(title, fullImgUrl, fullArticleUrl, summary));

这样不仅提升了代码可读性,也为集成数据库存储或 REST 接口提供了便利。


Jsoup 的强大之处在于其灵活的 CSS 选择器支持,这使得我们可以像前端工程师一样精准定位元素。以下是一些常用语法及其应用场景:

语法说明示例
tag按标签名选择div,img
.class按类名选择.zw_content
#id按ID选择#news-1-list
[attr]存在属性[href]
[attr=value]属性等于值[class=zw_content]
parent > child直接子元素ul > li
el1 el2后代元素div img

实际应用中,组合查询往往更能应对复杂结构。例如查找src/attach开头且width=101的图片:

Elements specialImgs = doc.select("img[src^=/attach][width=101]");

又如只选取.news-1-lists下的直接子项<li>,避免误选嵌套列表:

Elements directLi = doc.select("ul.news-1-lists > li");

这种细粒度控制能力极大增强了爬虫的鲁棒性。

另外,属性操作也值得重视。除了读取值之外,还可以判断是否存在某属性:

if (element.hasAttr("alt")) { String altText = element.attr("alt"); }

甚至可以修改属性用于本地缓存预处理:

element.attr("src", "local_cache/" + filename);

这些技巧在离线渲染或静态资源迁移中非常有用。


尽管 Jsoup 功能强大,但在真实项目中仍会遇到各种挑战。以下是几个常见问题及应对策略:

Q:抓不到内容怎么办?

首先要确认目标内容是否由 JavaScript 动态生成。右键“查看网页源码”,如果看不到对应 HTML 片段,说明是 AJAX 加载。此时 Jsoup 无能为力,需结合 Selenium 或 Puppeteer 等工具模拟浏览器行为。

其次检查 class 名称是否准确。HTML 类名区分大小写,且可能因 CMS 更新发生变化。建议使用模糊匹配:

doc.select("[class*=content]") // 包含 "content" 的任意类名

Q:中文乱码怎么解决?

多数情况下是因为未正确指定字符集。可在解析时显式声明编码:

Document doc = Jsoup.parse(htmlString, "UTF-8");

或者在请求阶段设置请求头:

Connection conn = Jsoup.connect(url); conn.header("Accept-Charset", "utf-8"); Document doc = conn.get();

Q:如何判断某个元素是否存在?

最安全的做法是通过数量判断:

if (!doc.select(".zw_content").isEmpty()) { // 元素存在 }

不要依赖.get(0)这类操作,容易抛出异常。

Q:性能如何?

在 i7-12700K + 32GB RAM 环境下实测:
- 单页连接+解析耗时约 800ms ~ 1.5s(主要受网络影响)
- 提取 10 条新闻数据小于 200ms
- 内存占用轻量模式约 5–10 MB,完整 DOM 树约 20–50 MB

建议对静态页面先保存 HTML 文件再离线解析,提升调试效率;对高频采集任务可引入连接池和重试机制。


编写健壮的爬虫不仅仅是写几行选择器那么简单。一个成熟的流程应当包括三个阶段:

第一阶段:分析
- 使用 Chrome DevTools 审查目标网页结构
- 记录关键元素的选择器路径
- 编写最小可运行测试代码验证提取逻辑

第二阶段:开发
- 先实现单条数据提取,确保准确性
- 再扩展为批量处理,加入日志输出
- 添加异常捕获,区分网络异常与结构变更

第三阶段:维护
- 定期巡检网页结构是否调整
- 设置监控报警机制(如空结果告警)
- 保留历史版本以便快速回滚

尤其要注意反爬策略的变化。即使目前无需登录,未来也可能增加验证码或 IP 限流。提前设计好降级方案和缓存机制,才能让系统长期稳定运行。


Jsoup 是 Java 工程师手中一把锋利的“小刀”,虽不能解决所有爬虫难题,但在处理静态 HTML 场景下表现卓越。通过合理运用选择器、妥善处理异常、规范编码习惯,我们完全可以构建出高效、可靠的图文采集系统。

更重要的是,这项技能背后体现的是对 Web 结构的理解力和数据提取的抽象思维——无论技术栈如何演进,这些核心能力始终有价值。当你下次面对一个新的信息站点时,不妨打开开发者工具,试着写下第一条select()表达式,迈出自动化采集的第一步。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/16 10:58:59

PPAP流程详解及提交等级解析

VibeVoice-WEB-UI 技术详解及多说话人语音生成能力解析 在播客制作、有声书演绎或AI角色对话开发中&#xff0c;你是否曾遇到这样的困扰&#xff1a;传统语音合成听起来像“念稿”&#xff0c;角色切换生硬&#xff0c;长段落里音色漂移、情绪断裂&#xff1f;更别提三人以上对…

作者头像 李华
网站建设 2026/5/3 4:13:34

RTK基站设置与GNSS测量操作全解析

RTK基站设置与GNSS测量操作全解析 在城市道路改扩建项目中&#xff0c;测绘团队常面临一个棘手问题&#xff1a;明明设备标称精度达到厘米级&#xff0c;实测成果却频频超限。一位资深工程师发现&#xff0c;问题根源并非仪器性能不足&#xff0c;而是基站架设不当与坐标转换流…

作者头像 李华
网站建设 2026/5/1 16:59:50

大学英语2模拟试卷(一) 题目解析与练习

大学英语2模拟试卷(一) 题目解析与练习 在准备大学英语考试的过程中&#xff0c;许多学生常常陷入一个误区&#xff1a;把语法当作孤立的知识点来死记硬背。然而&#xff0c;真正的语言能力并不只是“知道规则”&#xff0c;而是能在具体语境中准确判断哪个选项最自然、最符合逻…

作者头像 李华
网站建设 2026/5/11 15:53:54

RTK基站设置与测量放样操作全解析

RTK基站设置与测量放样操作全解析 在现代工程测绘中&#xff0c;厘米级精度早已不再是遥不可及的目标。无论是道路施工的桩位放样、电力塔基的精准定位&#xff0c;还是地质灾害监测中的微小位移捕捉&#xff0c;RTK&#xff08;Real-Time Kinematic&#xff09;技术正以前所未…

作者头像 李华
网站建设 2026/5/8 8:24:04

Open-AutoGLM 能在苹果芯片上运行吗:M1/M2/M3全系列实测数据揭晓

第一章&#xff1a;Open-AutoGLM 支持苹果吗Open-AutoGLM 作为一款基于 AutoGLM 架构的开源项目&#xff0c;其对苹果生态系统的兼容性受到广泛关注。随着苹果芯片&#xff08;Apple Silicon&#xff09;在 Mac 设备中的普及&#xff0c;开发者普遍关心该项目是否能在 macOS 系…

作者头像 李华
网站建设 2026/5/3 8:47:01

Ionic Framework 更新日志:Vue 支持与 Bug 修复

GLM-TTS WebUI 使用指南&#xff1a;零样本语音克隆与情感合成 在内容创作、有声书生成和智能语音助手日益普及的今天&#xff0c;如何快速实现高质量的个性化语音合成&#xff0c;成为许多开发者和创作者关注的核心问题。基于 GLM-TTS 开源项目二次开发的这款 WebUI 工具&…

作者头像 李华