㊗️本期内容已收录至专栏《Python爬虫实战》持续完善知识体系与项目实战建议先订阅收藏后续查阅更方便㊙️本期爬虫难度指数⭐福利一次订阅后专栏内的所有文章可永久免费看持续更新中保底1000(篇)硬核实战内容。全文目录 开篇语0️⃣ 前言Preface1️⃣ 摘要Abstract2️⃣ 背景与需求Why3️⃣ 合规与注意事项必写⚠️4️⃣ 技术选型与整体流程What/How5️⃣ 环境准备与依赖安装可复现6️⃣ 核心实现请求层Fetcher7️⃣ 核心实现解析层Parser8️⃣ 数据存储与导出Storage强大的 SQLite9️⃣ 运行方式与结果展示 常见问题与排错爬虫律师的避坑指南1️⃣1️⃣ 进阶优化AI 赋能法务数据1️⃣2️⃣ 总结与延伸阅读 文末✅ 专栏持续更新中建议收藏 订阅✅ 互动征集✅ 免责声明 开篇语哈喽各位小伙伴们你们好呀我是【喵手】。运营社区 C站 / 掘金 / 腾讯云 / 阿里云 / 华为云 / 51CTO欢迎大家常来逛逛一起学习一起进步我长期专注Python 爬虫工程化实战主理专栏 《Python爬虫实战》从采集策略到反爬对抗从数据清洗到分布式调度持续输出可复用的方法论与可落地案例。内容主打一个“能跑、能用、能扩展”让数据价值真正做到——抓得到、洗得净、用得上。专栏食用指南建议收藏✅ 入门基础环境搭建 / 请求与解析 / 数据落库✅ 进阶提升登录鉴权 / 动态渲染 / 反爬对抗✅ 工程实战异步并发 / 分布式调度 / 监控与容错✅ 项目落地数据治理 / 可视化分析 / 场景化应用专栏推广时间如果你想系统学爬虫而不是碎片化东拼西凑欢迎订阅专栏《Python爬虫实战》一次订阅后专栏内的所有文章可永久免费阅读持续更新中。订阅后更新会优先推送按目录学习更高效0️⃣ 前言Preface大家好我是你们的爬虫向导。今天我们将跨界进入法律领域使用 Python 的requests和BeautifulSoup抓取公开的仲裁/法院案例目录。我们将实现一套“列表分页遍历 详情页穿透”的双层爬虫并把提取到的案由、文号、机构等核心字段优雅地沉淀到SQLite 数据库中。读完这篇分享你将获得掌握针对严谨政务/司法类网站的稳定抓取与解析策略。学会从大段的法律文书详情页中精准抽取出“首段摘要Abstract”。熟练运用 Python 内置的sqlite3模块构建支持 SQL 检索的本地轻量级数据库。1️⃣ 摘要Abstract本文详细展示了针对公开司法案例网站的自动化数据采集全流程。程序首先构造分页循环抓取案例列表中的文号、案由、发布日期等扁平字段并获取详情页链接随后深入详情页提取长文本的段落摘要。最终利用 SQLite 的UNIQUE约束实现数据的无感去重插入输出一个名为legal_cases_archive.db的标准数据库文件为后续的法律数据挖掘Data Mining提供坚实底座。2️⃣ 背景与需求Why为什么要爬公开案例库类案类判检索遇到新案件时快速在本地数据库中通过 SQL 模糊匹配寻找历史相似案例的裁判逻辑。合规风控模型统计特定行业如互联网、金融的高频“案由”为企业提供法律风险预警。法务自动化传统的手动去各个仲裁委网站翻找案例简直是折磨自动化采集能让律师把时间花在核心的法律逻辑分析上。目标字段清单精准映射Cause_of_Action(案由如买卖合同纠纷)Case_Number(文号如(2023)京某仲裁字第123号 -作为主键)Publish_Date(发布日期)Institution(审理/仲裁机构)Summary(案件摘要/首段核心诉求)Source_Link(原始页面链接确保证据溯源)3️⃣ 合规与注意事项必写⚠️在法律的边缘试探是大忌以下红线请牢记只采公开数据必须且只能抓取网站上无需登录、无需特殊权限即可公开访问的脱敏案例。严控访问频率司法/政务机构的服务器是公共资源。必须设置 3-5 秒的抓取延时绝对禁止使用多线程并发攻击做一名遵纪守法的数据极客。不触碰个人隐私法律文书通常经过了脱敏处理如化名“张某某”。我们在解析和存储时要保持中立客观不可尝试还原或拼接当事人的隐私信息。4️⃣ 技术选型与整体流程What/How技术栈requests(基础网络请求) bs4(DOM 节点抽取) sqlite3(本地轻量级关系型数据库)。业务流转图解Standard WorkflowDoneAll Pages DoneStart SpiderInitialize SQLite DB: legal_cases_archive.dbLoop Pages 1 to NFetch Case List PageExtract Case No., Cause, Date, URLsIterate Detail URLsFetch Detail HTMLExtract First Paragraph as SummaryAssemble Record DictionaryInsert OR Ignore into SQLiteClose DB Finish5️⃣ 环境准备与依赖安装可复现让我们搭建好法务数据分析的无尘工作室Python 版本Python 3.9 (对 SQLite 支持极佳)安装依赖包pipinstallrequests beautifulsoup4项目目录结构legal_case_spider/ │ ├── case_archiver.py # 主爬虫引擎 └── database/ └── legal_cases_archive.db # 英文命名的本地数据库文件6️⃣ 核心实现请求层Fetcher政务网站经常有简单的防刷机制伪装好 UA 和妥善处理异常是我们请求层的第一要务。importrequestsimporttimeimportrandomclassLegalFetcher:def__init__(self):self.sessionrequests.Session()self.headers{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36,Accept:text/html,application/xhtmlxml,Referer:https://www.example-arbitration.org/cases}deffetch_html(self,url):try:print(f⚖️ Requesting:{url})responseself.session.get(url,headersself.headers,timeout15)response.raise_for_status()response.encodingutf-8returnresponse.textexceptExceptionase:print(f❌ Fetch Error on{url}:{e})returnNone7️⃣ 核心实现解析层Parser这一步我们分为两层一层解析外面的表格拿基础信息另一层进到详情页像老律师看卷宗一样一眼揪出“案件摘要”。frombs4importBeautifulSoupfromurllib.parseimporturljoinimportredefparse_case_list(html,base_url):解析列表页提取文号、案由、日期及链接soupBeautifulSoup(html,html.parser)cases[]# 假设案例列表是以标准的 ul li 或 tr 组织的itemssoup.find_all(div,class_case-item)foriteminitems:title_nodeitem.find(a,class_case-title)ifnottitle_node:continue# 很多时候文号包含在标题里比如 张某诉李某买卖合同纠纷案[(2023)仲某字第1号]full_titletitle_node.get_text(stripTrue)detail_urlurljoin(base_url,title_node[href])date_nodeitem.find(span,class_publish-date)publish_datedate_node.get_text(stripTrue)ifdate_nodeelse1970-01-01# 利用正则巧妙抽离出【案由】和【文号】# 假设格式XXXX纠纷案 [(2023)京仲裁字第XX号]case_numberUnknown-Nocausefull_title num_matchre.search(r\[(.*?)\]|(.*?)|\((.*?)\),full_title)ifnum_match:# 提取括号里的文号case_numbernum_match.group(1)ornum_match.group(2)ornum_match.group(3)# 删掉文号部分剩下的作为粗略的案由/标题causere.sub(r\[.*?\]|.*?|\(.*?\),,full_title).strip()cases.append({Cause_of_Action:cause,Case_Number:case_number,Publish_Date:publish_date,Detail_URL:detail_url})returncasesdefparse_case_detail(html):深入详情页抽取机构与首段摘要soupBeautifulSoup(html,html.parser)# 1. 抽取发布机构 (通常在文章抬头的某个 span 里)org_nodesoup.find(span,class_institution-name)institutionorg_node.get_text(stripTrue)iforg_nodeelsePublic Arbitration Commission# 2. 抽取首段摘要 (Abstract)# 法律文书正文非常长往往第一段 p 是核心情况说明summaryNo abstract available.content_divsoup.find(div,class_article-content)ifcontent_div:# 寻找第一个包含实质性文字的段落 (长度大于 20过滤掉占位空格)paragraphscontent_div.find_all(p)forpinparagraphs:textp.get_text(stripTrue)iflen(text)20:summarytextbreakreturninstitution,summary8️⃣ 数据存储与导出Storage强大的 SQLite为什么选择 SQLite因为文号Case Number是唯一的利用 SQLite 的UNIQUE约束和INSERT OR IGNORE语法我们可以完美实现**“增量更新与去重”**importsqlite3importosclassLegalDatabase:def__init__(self,db_pathdatabase/legal_cases_archive.db):os.makedirs(os.path.dirname(db_path),exist_okTrue)self.connsqlite3.connect(db_path)self.cursorself.conn.cursor()self._init_table()def_init_table(self):# 核心设计Case_Number 设为 UNIQUE 唯一索引create_table_sql CREATE TABLE IF NOT EXISTS cases ( id INTEGER PRIMARY KEY AUTOINCREMENT, cause_of_action TEXT, case_number TEXT UNIQUE, publish_date TEXT, institution TEXT, summary TEXT, source_link TEXT ) self.cursor.execute(create_table_sql)self.conn.commit()definsert_case(self,case_data):# INSERT OR IGNORE 保证了就算跑重复的页码也不会存入重复的案例insert_sql INSERT OR IGNORE INTO cases (cause_of_action, case_number, publish_date, institution, summary, source_link) VALUES (?, ?, ?, ?, ?, ?) self.cursor.execute(insert_sql,(case_data[Cause_of_Action],case_data[Case_Number],case_data[Publish_Date],case_data[Institution],case_data[Summary],case_data[Source_URL]))self.conn.commit()returnself.cursor.rowcount# 返回 1 表示新增0 表示已存在defclose(self):self.conn.close()9️⃣ 运行方式与结果展示主调度器就位。为了让你一键跑通我在代码中注入了模拟的 HTML 源码你可以清晰地看到整个清洗和入库过程。defmain():print( Legal Case Archiver Engine starting...)dbLegalDatabase()# 演示模拟我们从第 1 页抓到了列表数据base_domainhttps://example-arbitration.orgmock_list_html div classcase-item a classcase-title href/case/detail/101甲公司诉乙公司技术开发合同纠纷案[(2023)深仲字第001号]/a span classpublish-date2023-10-15/span /div div classcase-item a classcase-title href/case/detail/102王某与某科技公司劳动争议案[2023京劳人仲字第999号]/a span classpublish-date2023-11-02/span /div # 1. 解析列表cases_listparse_case_list(mock_list_html,base_domain)print(f✅ Found{len(cases_list)}cases on current page. Piercing details...)# 2. 遍历详情并入库forcaseincases_list:# 模拟抓取详情页mock_detail_htmlf div classarticle-header span classinstitution-name地方商事仲裁委员会/span /div div classarticle-content p /p !-- 干扰空行 -- p本案中申请人就其与被申请人于2022年签订的技术开发合同的违约责任提起仲裁。申请人主张被申请人交付的代码存在严重缺陷.../p /div print(f Analyzing:{case[Case_Number]})institution,summaryparse_case_detail(mock_detail_html)# 组装最终数据字典record{Cause_of_Action:case[Cause_of_Action],Case_Number:case[Case_Number],Publish_Date:case[Publish_Date],Institution:institution,Summary:summary,Source_URL:case[Detail_URL]}# 插入数据库addeddb.insert_case(record)ifadded:print(f ➕ Successfully archived new case into DB.)else:print(f ⏩ Case already exists. Skipped.)# 敬畏规则文明爬取真实环境下这里一定要有休眠time.sleep(random.uniform(2.0,4.0))db.close()print( All operations completed! Check your legal_cases_archive.db)if__name____main__:main()用 SQLite 工具如 DBeaver打开legal_cases_archive.db后的惊艳效果cause_of_actioncase_numberpublish_dateinstitutionsummary甲公司诉乙公司技术开发合同纠纷案2023)深仲字第001号2023-10-15地方商事仲裁委员会本案中申请人就其与被申请人于2022年…王某与某科技公司劳动争议案2023京劳人仲字第999号2023-11-02地方商事仲裁委员会本案中申请人就其与被申请人于2022年…(非常干净利落文号被精准剥离成了主键冗长原文被压缩成了核心摘要) 常见问题与排错爬虫律师的避坑指南遇到sqlite3.OperationalError: database is locked原因你的代码在某个地方抛出了异常中途退出导致上一次的 SQLite 连接没有正常close()或者多线程同时在写数据库。对策爬虫脚本尽量保持单线程写库或者在代码的最外层包一个try...finally确保db.close()永远会被执行。摘要抓取出错全是乱码或 JS 代码原因有些高级司法网站为了防止爬虫把正文用 Base64 加密或者做成了 Canvas 字体反爬。对策如果是 Base64抓取节点后用base64.b64decode解码如果是字体反爬这种技术壁垒极高建议更换目标寻找其他开源镜像站点。抓下来的文号带有奇怪的空格如( 2 0 2 3 )对策在insert_case前对文号做一个终极清洗case_number case_number.replace( , )确保主键的绝对干净。1️⃣1️⃣ 进阶优化AI 赋能法务数据当你拥有了数万条 SQLite 结构化数据你可以直接给它加一个“视觉化与 AI 引擎”全文检索Full-Text Search把 SQLite 中的数据导入到Elasticsearch做成一个秒级响应的本地类案检索引擎。词云与案由统计图表读取 SQLite 里的cause_of_action使用 Python 生成一张高频诉讼词云图。( Visualization Note: Default to English labels for charts:Title: Frequency of Legal Disputes,X-axis: Cause of Action,Y-axis: Case Count.)大模型裁判观点提炼接入大语言模型如 ChatGPT / Gemini API把Summary丢进去让 AI 自动输出【判决结果预期】和【核心争议焦点】直接打造高阶 AI 法律助理1️⃣2️⃣ 总结与延伸阅读太出色了今天你不仅学会了多级网页的抓取更是深入理解了**“通过主键Case Number进行数据库去重存储”**这一企业级数据开发的硬核技能。在这个“数据即黄金”的时代公开的裁判与仲裁文书是最具逻辑性和高价值的文本语料。通过这套代码你已经掌握了采集它们的钥匙。如果你在未来遇到某些带有验证码拦截的司法站点可以去了解一下Playwright自动化框架。继续在代码与法律交织的旷野里狂奔吧期待你的下一个伟大作品 文末好啦以上就是本期的全部内容啦如果你在实践过程中遇到任何疑问欢迎在评论区留言交流我看到都会尽量回复咱们下期见小伙伴们在批阅的过程中如果觉得文章不错欢迎点赞、收藏、关注哦三连就是对我写作道路上最好的鼓励与支持❤️✅ 专栏持续更新中建议收藏 订阅墙裂推荐订阅专栏 《Python爬虫实战》本专栏秉承着以“入门 → 进阶 → 工程化 → 项目落地”的路线持续更新争取让每一期内容都做到✅ 讲得清楚原理✅ 跑得起来代码✅ 用得上场景✅ 扛得住工程化想系统提升的小伙伴强烈建议先订阅专栏 《Python爬虫实战》再按目录大纲顺序学习效率十倍上升✅ 互动征集想让我把【某站点/某反爬/某验证码/某分布式方案】等写成某期实战评论区留言告诉我你的需求我会优先安排实现(更新)哒~⭐️ 若喜欢我就请关注我叭更新不迷路⭐️ 若对你有用就请点赞支持一下叭给我一点点动力⭐️ 若有疑问就请评论留言告诉我叭我会补坑 更新迭代✅ 免责声明本文爬虫思路、相关技术和代码仅用于学习参考对阅读本文后的进行爬虫行为的用户本作者不承担任何法律责任。使用或者参考本项目即表示您已阅读并同意以下条款合法使用 不得将本项目用于任何违法、违规或侵犯他人权益的行为包括但不限于网络攻击、诈骗、绕过身份验证、未经授权的数据抓取等。风险自负 任何因使用本项目而产生的法律责任、技术风险或经济损失由使用者自行承担项目作者不承担任何形式的责任。禁止滥用 不得将本项目用于违法牟利、黑产活动或其他不当商业用途。使用或者参考本项目即视为同意上述条款,即 “谁使用谁负责” 。如不同意请立即停止使用并删除本项目。