news 2026/6/10 12:48:37

使用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/6/10 16:04:31

苹果AirPods Max拆解:内部用料与设计全解析

HeyGem 数字人视频生成系统 —— 架构解析与实战指南 在短视频内容爆炸式增长的今天&#xff0c;企业对高效、低成本制作宣传素材的需求日益迫切。一个能自动将语音转为“会说话的数字人”的工具&#xff0c;早已不是科幻场景&#xff0c;而是正在被广泛落地的技术现实。其中&a…

作者头像 李华
网站建设 2026/6/10 13:00:31

Word操作题第10套完整排版指南

VibeVoice-WEB-UI 完整使用指南 在播客内容爆发式增长的今天&#xff0c;制作一档高质量的多人对话节目不再只是专业录音棚的专利。越来越多的内容创作者开始借助AI语音技术&#xff0c;将结构化脚本自动转化为自然流畅的多角色对话音频。微软最新开源的 VibeVoice-WEB-UI 正是…

作者头像 李华
网站建设 2026/6/10 16:03:29

BiliDrive 备份的计算机电子书资源汇总

BiliDrive 计算机电子书资源与高效学习指南 在信息爆炸的时代&#xff0c;优质技术资料的价值愈发凸显。对于开发者而言&#xff0c;一本好书往往能带来突破性的启发——无论是理解底层原理、掌握新框架&#xff0c;还是提升工程思维。然而&#xff0c;面对海量碎片化内容&…

作者头像 李华
网站建设 2026/6/9 22:25:31

10大企业级Agentic AI架构全解析:从入门到实战,破解AI Agent落地难题

本文详解10大企业级Agentic AI架构&#xff0c;包括Salesforce、AKKA等公司的解决方案&#xff0c;破解技术稳定、系统集成、合规落地等核心难题。这些架构以自主协作的AI Agent为核心&#xff0c;通过分层设计实现人类智能体协同&#xff0c;助力企业构建安全可控的智能系统&a…

作者头像 李华
网站建设 2026/6/10 15:10:22

拯救高AI率论文:亲测3款工具,AI检测率从红变绿全过程

写的文章明明是一个字一个字敲的&#xff0c;提交后却被导师批“满屏机器味”&#xff1f;自查AIGC率飙到87%&#xff0c;改了3遍还是降不下来&#xff1f; 我踩过替换同义词越改越假、用错降AI率工具反升的坑&#xff0c;今天把9个原创免费降AI率技巧3款实测工具深度测评分享…

作者头像 李华
网站建设 2026/6/10 15:54:47

AE高效合成必备的10个技巧与快捷键

AE高效合成必备的10个技巧与快捷键 在语音合成技术飞速发展的今天&#xff0c;零样本语音克隆已经不再是实验室里的概念&#xff0c;而是真正走进了内容创作、智能客服、有声书制作等实际场景。GLM-TTS 凭借其出色的音色还原能力、情感迁移特性以及对中英文混合文本的良好支持…

作者头像 李华