Python爬虫实战:手把手教你如何构建政府财政支出功能分类层级数据库
㊗️本期内容已收录至专栏《Python爬虫实战》持续完善知识体系与项目实战建议先订阅收藏后续查阅更方便㊙️本期爬虫难度指数⭐ (基础入门篇)福利一次订阅后专栏内的所有文章可永久免费看持续更新中保底1000(篇)硬核实战内容。全文目录 开篇语0️⃣ 前言Preface1️⃣ 摘要Abstract2️⃣ 背景与需求Why3️⃣ 合规与注意事项4️⃣ 技术选型与整体流程5️⃣ 环境准备与依赖安装6️⃣ 核心实现请求层Fetcher7️⃣ 核心实现解析层Parser8️⃣ 数据存储与导出Storage9️⃣ 运行方式与结果展示 常见问题与排错Troubleshooting1️⃣1️⃣ 进阶优化Optional1️⃣2️⃣ 总结与延伸阅读 文末✅ 专栏持续更新中建议收藏 订阅✅ 互动征集✅ 免责声明 开篇语哈喽各位小伙伴们你们好呀我是【喵手】。运营社区 C站 / 掘金 / 腾讯云 / 阿里云 / 华为云 / 51CTO欢迎大家常来逛逛一起学习一起进步我长期专注Python 爬虫工程化实战主理专栏 《Python爬虫实战》从采集策略到反爬对抗从数据清洗到分布式调度持续输出可复用的方法论与可落地案例。内容主打一个“能跑、能用、能扩展”让数据价值真正做到——抓得到、洗得净、用得上。专栏食用指南建议收藏✅ 入门基础环境搭建 / 请求与解析 / 数据落库✅ 进阶提升登录鉴权 / 动态渲染 / 反爬对抗✅ 工程实战异步并发 / 分布式调度 / 监控与容错✅ 项目落地数据治理 / 可视化分析 / 场景化应用专栏推广时间如果你想系统学爬虫而不是碎片化东拼西凑欢迎订阅专栏《Python爬虫实战》一次订阅后专栏内的所有文章可永久免费阅读持续更新中。订阅后更新会优先推送按目录学习更高效0️⃣ 前言Preface在公共财政管理与大数据审计领域“财政支出功能分类代码”是透视政府钱袋子的“基因组”。本文将带你利用 Python 爬虫技术从复杂的政务公开页面中自动化提取、解析并重构这套三级分类体系类、款、项。通过本文你将获得层级数据重构算法掌握如何利用“栈Stack”结构在单次遍历中复原树状层级。生产级请求封装实现具备指数退避机制Exponential Backoff的抗干扰请求器。数据标准化清洗学会处理政务数据中常见的半角空格、特殊编码及排版错位。1️⃣ 摘要Abstract本文旨在通过 Python 爬虫生态Requests BeautifulSoup4 Pandas针对财政支出分类说明页面进行深度数据挖掘。重点解决层级编码体系的自动化抽取难题通过代码长度识别逻辑建立父子级关联最终产出符合三范式的标准化 CSV 映射表。文章不仅关注采集效率更深挖数据解析过程中的算法优化与工程容错。2️⃣ 背景与需求Why为什么要爬取财政支出分类是研究公共经济学的核心变量。每年政府可能会对部分分类进行微调增设或撤销某个“项”级科目。手动复制数千行、三层深度的说明文档不仅低效且极易出错。目标字段清单Target Fieldscode: 分类代码如 201, 20101。name: 分类名称如 一般公共服务支出。level: 层级1:类, 2:款, 3:项。parent_code: 上级代码实现递归查询的关键。description: 用途说明该科目具体的支出范围。3️⃣ 合规与注意事项在抓取政务或官方标准数据时必须保持高度的职业操守Robots.txt 尊重虽然此类说明页通常为公开信息但仍需检查协议确保不进入禁止抓取的路径。非高峰采集建议将抓取任务定在凌晨 2:00 - 5:00避免占用政府服务器带宽。频率控制严禁使用 10 线程以上的并发请求单线程配合随机延迟是最佳实践。用途申明本教程数据仅用于学术研究与技术交流严禁商业化售卖。4️⃣ 技术选型与整体流程为什么不选 Scrapy对于这种“单页面、深层级”的文档型抓取Requests BS4的灵活性更高能够更方便地在内存中维护一个解析状态机。采集解析流程Fetch获取整页 HTML。Scan识别页面中的表格Table或列表List结构。Stack-based Parsing使用栈结构跟踪当前的“父节点”。Validation校验代码长度与父节点长度的逻辑关系3/5/7位。Storage持久化为 CSV。5️⃣ 环境准备与依赖安装项目推荐目录FiscalProject/ ├── logs/ # 运行日志 ├── data/ # 产出文件 ├── core/ │ ├── fetcher.py # 网络层 │ └── parser.py # 逻辑层 └── main.py # 启动入口依赖安装pipinstallrequests beautifulsoup4 pandas lxml6️⃣ 核心实现请求层Fetcher政务网站有时会因为不稳定的跨境链路或防火墙策略导致连接重置。我们需要一个“打不死”的请求器。importrequestsfromrequests.adaptersimportHTTPAdapterfromurllib3.util.retryimportRetryimporttimeclassFiscalFetcher:def__init__(self):self.sessionrequests.Session()# 定义重试策略总共重试5次退避因子为1retry_strategyRetry(total5,backoff_factor1,status_forcelist[429,500,502,503,504],allowed_methods[HEAD,GET,OPTIONS])adapterHTTPAdapter(max_retriesretry_strategy)self.session.mount(https://,adapter)self.session.mount(http://,adapter)self.headers{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) Expert-Crawler/1.0,Accept:text/html,application/xhtmlxml,xml;q0.9,*/*;q0.8}deffetch_page(self,url):try:responseself.session.get(url,headersself.headers,timeout30)response.raise_for_status()# 解决部分政务网奇怪的编码问题response.encodingresponse.apparent_encodingreturnresponse.textexceptExceptionase:print(f Request Failed:{e})returnNone7️⃣ 核心实现解析层Parser这是全篇最硬核的部分。财政分类代码通常遵循类3位代码如 201款5位代码如 20101项7位代码如 2010101我们要利用这个规律在遍历表格行时自动寻找父节点。frombs4importBeautifulSoupimportreclassFiscalParser:def__init__(self):self.history_stack{1:None,2:None,3:None}# 记录各级当前的最新代码defparse_hierarchy(self,html_content):soupBeautifulSoup(html_content,lxml)table_rowssoup.find_all(tr)processed_data[]forrowintable_rows:cellsrow.find_all(td)iflen(cells)2:continueraw_codecells[0].get_text(stripTrue)raw_namecells[1].get_text(stripTrue)descriptioncells[2].get_text(stripTrue)iflen(cells)2else# 提取数字代码code_matchre.search(r\d,raw_code)ifnotcode_match:continuecodecode_match.group()# 判断层级逻辑level0iflen(code)3:level1eliflen(code)5:level2eliflen(code)7:level3iflevel0:continue# 更新当前层级的父子关系self.history_stack[level]code parent_codeself.history_stack.get(level-1)iflevel1elseTOPprocessed_data.append({code:code,name:raw_name,level:level,parent_code:parent_code,description:description})returnprocessed_data8️⃣ 数据存储与导出Storage对于这种具有强关联性的数据CSV 是最适合做初步清洗的格式。字段映射表 (Field Mapping Table):Field NameTypeExampleDescriptioncodeVARCHAR(10)2010101唯一功能分类编码nameVARCHAR(100)行政运行科目官方名称levelINTEGER3类(1)、款(2)、项(3)parent_codeVARCHAR(10)20101指向上级科目的外键usage_infoTEXT用于行政单位运行…详细预算支出范围说明9️⃣ 运行方式与结果展示如何启动How to Run修改main.py中的TARGET_URL。运行python main.py。系统将实时打印解析状态。结果预览Sample Output[INFO] Parsed: 201 - General Public Services (Level 1) [INFO] Parsed: 20101 - Government Office Affairs (Level 2) [INFO] Parsed: 2010101 - Administrative Operations (Level 3) 常见问题与排错Troubleshooting解析错位有些页面在“类”级只有代码没有名字。解决在解析器中加入判空逻辑如果名称为空则跳过或标记为“待核实”。动态加载JS如果数据是通过 Ajax 加载的。解决监控网络请求直接抓取.json接口或者引入Playwright渲染页面。编码地狱遇到\xa0或\u3000等特殊空格。解决使用unicodedata.normalize(NFKD, text)进行标准化。1️⃣1️⃣ 进阶优化Optional多源校对同时抓取国家和地方的分类表进行 Diff 对比。可视化分析利用Plotly绘制支出科目树状分布图。1️⃣2️⃣ 总结与延伸阅读本教程通过构建一个“带状态感的爬虫”解决了分层编码数据的提取难题。这不仅是爬虫技术的展现更是对数据结构的深度理解。下一步挑战尝试将数据存入PostgreSQL利用其递归查询WITH RECURSIVE功能一键查询某个“类”级下的所有细分科目。 文末好啦以上就是本期的全部内容啦如果你在实践过程中遇到任何疑问欢迎在评论区留言交流我看到都会尽量回复咱们下期见小伙伴们在批阅的过程中如果觉得文章不错欢迎点赞、收藏、关注哦三连就是对我写作道路上最好的鼓励与支持❤️✅ 专栏持续更新中建议收藏 订阅墙裂推荐订阅专栏 《Python爬虫实战》本专栏秉承着以“入门 → 进阶 → 工程化 → 项目落地”的路线持续更新争取让每一期内容都做到✅ 讲得清楚原理✅ 跑得起来代码✅ 用得上场景✅ 扛得住工程化想系统提升的小伙伴强烈建议先订阅专栏 《Python爬虫实战》再按目录大纲顺序学习效率十倍上升✅ 互动征集想让我把【某站点/某反爬/某验证码/某分布式方案】等写成某期实战评论区留言告诉我你的需求我会优先安排实现(更新)哒~⭐️ 若喜欢我就请关注我叭更新不迷路⭐️ 若对你有用就请点赞支持一下叭给我一点点动力⭐️ 若有疑问就请评论留言告诉我叭我会补坑 更新迭代✅ 免责声明本文爬虫思路、相关技术和代码仅用于学习参考对阅读本文后的进行爬虫行为的用户本作者不承担任何法律责任。使用或者参考本项目即表示您已阅读并同意以下条款合法使用 不得将本项目用于任何违法、违规或侵犯他人权益的行为包括但不限于网络攻击、诈骗、绕过身份验证、未经授权的数据抓取等。风险自负 任何因使用本项目而产生的法律责任、技术风险或经济损失由使用者自行承担项目作者不承担任何形式的责任。禁止滥用 不得将本项目用于违法牟利、黑产活动或其他不当商业用途。使用或者参考本项目即视为同意上述条款,即 “谁使用谁负责” 。如不同意请立即停止使用并删除本项目。