当前位置: 首页 > news >正文

Java 爬虫对百科词条分类信息的抓取与处理

在信息爆炸的互联网时代,百科类平台(如维基百科、百度百科)沉淀了海量结构化的知识内容,其词条的分类体系更是梳理信息的核心脉络。利用 Java 技术构建爬虫抓取并处理百科词条的分类信息,不仅能为知识图谱构建、行业数据分析、智能推荐系统等场景提供基础数据支撑,还能实现对特定领域知识的规模化采集与整合。本文将从技术原理、实现步骤、数据处理等维度,详细讲解如何使用 Java 完成百科词条分类信息的抓取与处理。

一、技术选型与核心原理

1. 核心技术栈

Java 生态中,爬虫开发的技术工具已十分成熟,本次实践选用以下核心技术:

  • 网络请求:Jsoup,一款轻量级的 HTML 解析库,支持 CSS 选择器、XPath 语法,能便捷地从 HTML 文档中提取数据,相比传统的 HttpClient + 正则表达式,开发效率更高。
  • 数据存储:MySQL,用于持久化存储抓取到的词条名称、分类路径、词条链接等结构化数据。
  • 数据处理:Java 集合框架(List、Map)与字符串处理工具(Apache Commons Lang3),用于清洗和规整分类信息。

2. 爬虫核心原理

百科词条的分类信息通常以固定的 HTML 结构呈现(如百度百科的分类栏位于页面侧边或底部,带有明确的 class 或 id 属性)。Java 爬虫的核心逻辑是:

  1. 发送 HTTP 请求获取词条页面的 HTML 源码;
  2. 解析 HTML 源码,定位分类信息的 DOM 节点,提取分类名称与链接;
  3. 对提取的原始数据进行清洗、去重、结构化处理;
  4. 将处理后的数据存储到数据库或本地文件中。

二、爬虫实现步骤:以百度百科为例

1. 环境准备

首先在 Maven 项目中引入依赖,核心依赖包括 Jsoup、MySQL 驱动、Apache Commons Lang3:

xml

<dependencies><!-- Jsoup HTML解析库 --><dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.17.2</version></dependency><!-- MySQL驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version><scope>runtime</scope></dependency><!-- Apache Commons Lang3 工具类 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.14.0</version></dependency></dependencies>

2. 发送 HTTP 请求获取 HTML 源码

使用 Jsoup 的<font style="color:rgba(0, 0, 0, 0.85) !important;">connect()</font>方法发送 GET 请求,设置请求头模拟浏览器访问(避免被反爬机制拦截),获取目标词条页面的 Document 对象(对应 HTML 文档)。

java

运行

importorg.jsoup.Jsoup;importorg.jsoup.nodes.Document;importjava.io.IOException;importjava.util.Map;/** * 网络请求工具类,用于获取百科页面的HTML源码 */publicclassHttpUtil{// 模拟浏览器的请求头privatestaticfinalMap<String,String>HEADERS=Map.of("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36","Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","Accept-Language","zh-CN,zh;q=0.9,en;q=0.8");/** * 获取指定URL的Document对象 * @param url 目标URL * @return Document对象 * @throws IOException 网络请求异常 */publicstaticDocumentgetDocument(Stringurl)throwsIOException{Jsoup.Connectionconnection=Jsoup.connect(url);// 设置请求头for(Map.Entry<String,String>entry:HEADERS.entrySet()){connection.header(entry.getKey(),entry.getValue());}// 设置超时时间为10秒returnconnection.timeout(10000).get();}}

3. 解析 HTML 提取分类信息

百度百科的词条分类信息通常位于<font style="color:rgba(0, 0, 0, 0.85) !important;"><div class="basic-info cmn-clearfix"></font><font style="color:rgba(0, 0, 0, 0.85) !important;"><div class="category-wrap"></font>节点下,通过 Jsoup 的 CSS 选择器定位节点,提取分类名称和对应的链接。

java

运行

importorg.jsoup.nodes.Document;importorg.jsoup.nodes.Element;importorg.jsoup.select.Elements;importjava.util.ArrayList;importjava.util.List;/** * 百科页面解析工具类,用于提取分类信息 */publicclassBaikeParser{/** * 提取百度百科词条的分类信息 * @param doc 词条页面的Document对象 * @param entryName 词条名称 * @return 分类信息列表 */publicstaticList<Category>parseCategory(Documentdoc,StringentryName){List<Category>categoryList=newArrayList<>();// 方式1:定位分类栏节点(不同百科版本可能结构不同,可调整选择器)ElementscategoryElements=doc.select("div.category-wrap a[href]");if(categoryElements.isEmpty()){// 方式2:备用选择器,适配其他结构categoryElements=doc.select("ul.basic-info-list li a[href]");}// 遍历节点提取分类信息for(Elementelement:categoryElements){// 提取分类名称StringcategoryName=element.text().trim();// 提取分类链接(拼接完整URL)StringcategoryUrl="https://baike.baidu.com"+element.attr("href").trim();// 过滤空值if(!categoryName.isEmpty()&&!categoryUrl.isEmpty()){Categorycategory=newCategory();category.setEntryName(entryName);category.setCategoryName(categoryName);category.setCategoryUrl(categoryUrl);categoryList.add(category);}}returncategoryList;}}/** * 分类信息实体类 */classCategory{privateStringentryName;// 词条名称privateStringcategoryName;// 分类名称privateStringcategoryUrl;// 分类链接// 无参构造、有参构造、getter和setter方法publicCategory(){}publicCategory(StringentryName,StringcategoryName,StringcategoryUrl){this.entryName=entryName;this.categoryName=categoryName;this.categoryUrl=categoryUrl;}publicStringgetEntryName(){returnentryName;}publicvoidsetEntryName(StringentryName){this.entryName=entryName;}publicStringgetCategoryName(){returncategoryName;}publicvoidsetCategoryName(StringcategoryName){this.categoryName=categoryName;}publicStringgetCategoryUrl(){returncategoryUrl;}publicvoidsetCategoryUrl(StringcategoryUrl){this.categoryUrl=categoryUrl;}}

4. 数据清洗与存储

提取的原始分类信息可能存在重复、空值或无效字符,使用 Apache Commons Lang3 进行数据清洗,再将处理后的数据存入 MySQL 数据库。

java

运行

importorg.apache.commons.lang3.StringUtils;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.PreparedStatement;importjava.sql.SQLException;importjava.util.List;/** * 数据处理与存储工具类 */publicclassDataProcessor{// MySQL数据库连接信息(需替换为自己的配置)privatestaticfinalStringDB_URL="jdbc:mysql://localhost:3306/baike_spider?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true";privatestaticfinalStringDB_USER="root";privatestaticfinalStringDB_PASSWORD="123456";/** * 清洗分类信息(去重、去除空值和特殊字符) * @param categoryList 原始分类信息列表 * @return 清洗后的分类信息列表 */publicstaticList<Category>cleanCategory(List<Category>categoryList){returncategoryList.stream()// 过滤空值.filter(category->StringUtils.isNoneBlank(category.getEntryName(),category.getCategoryName(),category.getCategoryUrl()))// 去除特殊字符(保留中文、英文、数字).peek(category->{category.setCategoryName(StringUtils.replacePattern(category.getCategoryName(),"[^\\u4e00-\\u9fa5a-zA-Z0-9]",""));category.setEntryName(StringUtils.replacePattern(category.getEntryName(),"[^\\u4e00-\\u9fa5a-zA-Z0-9]",""));})// 去重(根据词条名称和分类名称).distinct().toList();}/** * 将分类信息存入MySQL数据库 * @param categoryList 清洗后的分类信息列表 * @throws SQLException 数据库操作异常 */publicstaticvoidsaveToMySQL(List<Category>categoryList)throwsSQLException{// 注册驱动(MySQL 8.0+可省略)try{Class.forName("com.mysql.cj.jdbc.Driver");}catch(ClassNotFoundExceptione){thrownewRuntimeException("加载MySQL驱动失败",e);}// SQL插入语句Stringsql="INSERT INTO baike_category (entry_name, category_name, category_url) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE category_url = VALUES(category_url)";try(Connectionconn=DriverManager.getConnection(DB_URL,DB_USER,DB_PASSWORD);PreparedStatementpstmt=conn.prepareStatement(sql)){// 批量插入数据for(Categorycategory:categoryList){pstmt.setString(1,category.getEntryName());pstmt.setString(2,category.getCategoryName());pstmt.setString(3,category.getCategoryUrl());pstmt.addBatch();}pstmt.executeBatch();System.out.println("数据存入数据库成功,共插入/更新"+categoryList.size()+"条记录");}}}

5. 主程序入口

整合上述工具类,实现从请求、解析、清洗到存储的完整流程:

java

运行

importorg.jsoup.nodes.Document;importjava.io.IOException;importjava.sql.SQLException;importjava.util.List;/** * 百科爬虫主程序 */publicclassBaikeSpiderMain{publicstaticvoidmain(String[]args){// 目标词条URL(以“Java语言”为例)StringentryUrl="https://baike.baidu.com/item/Java%E8%AF%AD%E8%A8%80";// 词条名称StringentryName="Java语言";try{// 1. 获取页面Document对象Documentdoc=HttpUtil.getDocument(entryUrl);// 2. 解析分类信息List<Category>rawCategoryList=BaikeParser.parseCategory(doc,entryName);// 3. 清洗分类信息List<Category>cleanCategoryList=DataProcessor.cleanCategory(rawCategoryList);// 4. 存入数据库DataProcessor.saveToMySQL(cleanCategoryList);}catch(IOExceptione){System.err.println("网络请求失败:"+e.getMessage());}catch(SQLExceptione){System.err.println("数据库操作失败:"+e.getMessage());}}}

三、反爬机制应对与优化建议

1. 反爬应对策略

百科平台通常设有反爬机制,实际开发中需注意:

  • 请求频率控制:添加延迟(如<font style="color:rgb(0, 0, 0);">Thread.sleep(1000)</font>),避免短时间内大量请求;
  • IP 代理池:若需大规模抓取,使用代理 IP 轮换,防止 IP 被封禁;推荐使用亿牛云隧道代理
  • Cookie 与 Session 维持:部分平台需要登录后访问,可通过 Jsoup 维持 Cookie 会话。

2. 性能优化

  • 多线程抓取:使用线程池(<font style="color:rgb(0, 0, 0);">ExecutorService</font>)并行处理多个词条,提升抓取效率;
  • 数据缓存:将频繁访问的分类信息缓存到 Redis 中,减少数据库查询压力;
  • 增量抓取:记录已抓取的词条 URL,只抓取新增词条,避免重复工作。

四、总结

本文通过 Jsoup、MySQL 等技术,实现了 Java 爬虫对百度百科词条分类信息的抓取、解析、清洗与存储。整个流程体现了 Java 爬虫开发的核心思路:从网络请求获取数据,到解析提取有效信息,再到数据的结构化处理与持久化。在实际应用中,可根据不同百科平台的页面结构调整解析规则,结合反爬策略与性能优化手段,实现规模化的知识信息采集。这种技术方案不仅适用于百科词条分类信息处理,还可拓展到电商商品分类、新闻资讯标签提取等场景,具有广泛的应用价值。

http://www.jsqmd.com/news/130713/

相关文章:

  • OBS直播教程:OBS如何添加歌词显示?OBS怎么把歌词放上去?
  • 软件工程课程学期总结与收获
  • 云南抖音服务商慧多派实力机构,不能错过!
  • LIS2DW12三轴加速度传感器原理图设计,已量产(加速度传感器)
  • 失业 3 个月投 127 份简历?网安零成本转行月薪 12K,你们敢试吗?
  • 【路径规划】基于RRT APF RRT+APF RRT星+APF实现机器人路径规划附matlab代码
  • AJAX本质与核心概念
  • 比话和其他降AI率工具有什么不同,为什么能把知网AI率降低到15%
  • 中山SEO公司:如何在2026年拥抱AI技术,打造差异化竞争优势
  • 满足!** 豆角鸡蛋西红柿捞面 **
  • python执行动态代码方案
  • java计算机毕业设计无人超市支付系统设计与实现 智慧门店自助结算系统设计与实现 无人零售扫码支付平台开发实战
  • 实用指南:CentOS 7 Docker 部署 DVWA 教程
  • day46_Grad-CAM@浙大疏锦行
  • 2026仍考RHCE?别被“全能”标签带偏,这篇给你真实答案
  • 告别无脑 <div>:HTML 语义化标签入门
  • 学校要求知网AIGC查重报告?比话能降知网AI率吗
  • 多软件协同调度规则设计:避免依赖冲突的黄金法则
  • Plotly/Dash高级可视化实战教程:从高维图表到企业级仪表盘
  • 【分布鲁棒】基于Wasserstein距离的两阶段分布鲁棒简易模型附Matlab代码
  • 翻过入门的第一座小山
  • 收藏必备!六个高含金量编程竞赛助你进大厂+网络安全学习资源大放送
  • 基于知识图谱的RAG
  • 8 个降AI率工具推荐,专科生必看!
  • AsyncContext
  • 协议解析引擎横评:NLP技术哪家强?
  • YOLOv11 改进 - 注意力机制 | IIA信息整合注意力(Information Integration Attention ):精准保留空间位置信息,平衡精度与计算成本 | TGRS2025
  • 盐酸-N-取代苯胺类泄漏后应急处置,关键步骤要记牢!
  • 12月23日记
  • Yandex竞价实战指南:5个让ROI翻倍的深度优化技巧