news 2026/9/3 1:14:46

使用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/9/2 11:31:02

C4D材质基础:从金属到玻璃的质感模拟

C4D材质基础&#xff1a;从金属到玻璃的质感模拟 在三维设计中&#xff0c;一个模型是否“真实”&#xff0c;往往不取决于几何形态的复杂度&#xff0c;而在于材质的表现力。哪怕是最简单的球体&#xff0c;只要赋予恰当的材质与光照&#xff0c;也能呈现出不锈钢杯或磨砂玻璃…

作者头像 李华
网站建设 2026/9/3 1:02:47

徕本智能车载无线充支架拆解揭秘

徕本智能车载无线充支架拆解揭秘 在城市通勤日益依赖导航与语音交互的今天&#xff0c;驾驶者对“手不离方向盘、眼不离路面”的操作体验提出了更高要求。传统车载支架早已无法满足这种需求——它不再只是个夹手机的架子&#xff0c;而必须成为一个能听、会说、懂场景的智能终端…

作者头像 李华
网站建设 2026/9/3 1:02:28

实测数据说话:知网AI率87%降至15%,只用了这3个免费工具

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

作者头像 李华
网站建设 2026/9/3 0:02:42

Open-AutoGLM 适配苹果设备进展曝光(2024年唯一官方技术路线图)

第一章&#xff1a;Open-AutoGLM 支持苹果吗Open-AutoGLM 作为一款基于 AutoGLM 架构的开源项目&#xff0c;旨在为大语言模型的自动化任务提供轻量级解决方案。随着苹果生态在开发者群体中的普及&#xff0c;越来越多用户关注其在 macOS 及 Apple Silicon 芯片&#xff08;如 …

作者头像 李华
网站建设 2026/8/31 16:39:22

Open-AutoGLM邀请码获取路径大曝光(限时开放入口+实操步骤)

第一章&#xff1a;Open-AutoGLM邀请码获取 获取 Open-AutoGLM 的访问权限是使用该开源项目的首要步骤&#xff0c;目前项目采用邀请制机制以控制早期用户规模并保障系统稳定性。用户需通过官方渠道申请邀请码&#xff0c;完成身份验证后方可进入平台。 申请流程说明 访问 Op…

作者头像 李华