news 2026/9/20 20:39:30

医院数据信息爬虫实战:从数据源到字段清洗的完整方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
医院数据信息爬虫实战:从数据源到字段清洗的完整方案

简介:一份覆盖全国医院等级、擅长病症、地址、邮箱、电话及官网链接的爬虫程序资源,服务医疗数据分析、公共卫生规划与机构运营等场景,适合有一定Python基础、需要批量采集医院结构化信息的开发者。资源包共3个文件,包含一个.py爬虫脚本、一张数据预览图png和一份markdown说明文档,压缩包仅331KB,脚本实现了网页请求、内容解析与字段提取的完整流程,可直接运行或按需修改爬取逻辑。已有七十二人学习浏览,便于快速上手。通过脚本可批量导出易于分析的格式化数据,配合说明文档能迅速完成环境配置、字段映射与运行调试;预览图则直观展示抓取结果,帮助核验数据准确性。整体数据地域覆盖广、字段维度齐,可支撑区域医疗资源分布分析、就医导诊信息整理等实际应用。 做医疗健康类业务的人,应该都体会过被医院数据折腾的痛苦。前阵子公司要给就医导诊平台维护院区信息,急需一份覆盖全国的医院名录,包含等级、擅长病症、地址、邮箱、电话、网站这些核心字段。结果市面上能直接买到的数据不是太老就是字段残缺,卫健委公示文件又分散在各个省市站点的深处,根本没法一键汇总。没办法,只能自己动手写了一个医院数据信息爬虫,把散在各处的医院信息逐层挖出来,整理成结构化数据。这篇文章把这套爬虫项目的完整思路记录下来,从数据源规划、字段解析到反爬应对,希望给有类似需求的同行一些参考。

1. 这个爬虫要解决的真实问题:一份可用的全国医院库从哪来

1.1 医院数据到底散落在哪里

先看清问题本质。医院信息不是某一个网站自己单独拥有的,而是分散在很多地方:

  • 各级卫健委官网的医疗机构执业登记公示、医院等级评审结果页面;
  • 各医院自己的官方网站,尤其是"医院简介""联系我们""重点科室"几个子页面;
  • 第三方挂号平台、健康服务平台聚合的医院标签和科室擅长信息。

单纯抓一个渠道,数据永远缺胳膊少腿。比如从卫健委公示能拿到医院名称、地址和等级,但通常没有擅长病症;从医院官网能拿到科室介绍和联系电话,但又很难批量获取全院等级。所以这个爬虫必须设计成"多源互补"的结构,而不是盯着某一个站点死磕。

1.2 字段设计背后的业务需求

题目标出来的六个字段,其实对应了医疗信息服务的六个使用环节:

  • 等级:用户判断医院综合实力的第一眼信息,也是导诊推荐的核心排序权重;
  • 擅长病症:智能分诊、科室推荐的关键标签,直接影响搜索匹配;
  • 地址:基于LBS的附近医院功能必需,缺了没法做距离排序;
  • 邮箱:部分医院对外事务、转诊联系、商务合作的重要通道;
  • 电话:用户最直接的联系方式,挂号和咨询的终极兜底;
  • 网站:完整信息源入口,给用户留下自行判断的跳转链路。

知道字段要去哪里找以后,下一步就是规划爬取目标。我建议不要把"全国"想成一个单一集合,而是拆成"卫健委源 + 医院官网源 + 第三方聚合源"三个层次分别推进,这样后面写代码才不会乱。

2. 数据源选型与页面信息分布规律:不能只盯一个网站

2.1 公开可用的三类数据源对比

我实际调研后把可用数据源分成三类,各有优缺点:

数据源类型典型例子能提供的字段主要问题
卫健委公示省市卫健委、卫生监督所医院名称、地址、等级、法定代表人页面结构差异极大,无擅长病症,搜索入口弱
医院官网医院"医院简介""联系我们"页等级、地址、电话、邮箱、重点科室、特色技术各站结构完全不同,需要针对性解析
挂号/健康平台健康中国、省级统一挂号平台等级、擅长病症、科室列表、医生简介数据相对规范但存在聚合噪音,部分字段人工维护未必准

这三类源里,真正能批量拿到擅长病症的是挂号平台和医院的"重点科室"页,但它们恰恰是反爬最严格的地方。医院官网虽然结构五花八门,但绝大多数毫无反爬措施,反而适合做基础数据补充。

2.2 一个医院的完整信息要跨多个页面获取

很多人写爬虫失败,是因为以为一个URL就能拿全所有字段。实际上,单家医院的数据经常这样分布:

  • 列表页:医院名称 + 一个详情页链接,这是爬虫的"入口";
  • 详情页:科室介绍、等级描述、部分擅长词条,可能要翻3~5个标签页;
  • 联系方式页:地址、电话、邮箱,往往独立存在;
  • 挂号平台科室介绍页:擅长病症关键词最集中的地方。

所以这个项目本质上不是"单页抓取爬虫",而是一个"以医院为主体的关系型数据聚合器"。爬完列表页,要把它下面的所有子URL都理解成"待补充字段的来源",分别请求、分别解析,最后再合并成一条记录。

2.3 起始URL库怎么组织

我当时建议用"省-市-医院"三级结构来建起始URL库,而不是随便拿几个搜索页硬抓。具体做法是先在各省卫健委官网提取医院公示列表,拿到医院名称后再去搜索引擎或直接拼接医院官网域名,补充详情页地址。这个流程虽然前置工作量大,但能让后期的每个医院都有一条清晰的"抓取血缘",排查缺数据时非常省事。

3. 多级爬取的框架设计与请求策略:从列表页到详情页再到关联页

3.1 选型:Scrapy还是纯requests手写

这个项目我用了Scrapy + requests混合方案。总框架用Scrapy是因为它的异步并发、中间件、Pipeline天然适合多页面任务;但某些反爬严格的挂号平台,Scrapy的默认行为太规整,容易被识别,反而需要临时用requests配合Session单独处理。

如果你只是学习或者抓取量不大,纯requests也能搞定,写法更直观:

import requests from bs4 import BeautifulSoup session = requests.Session() session.headers.update({ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36", "Accept-Language": "zh-CN,zh;q=0.9", }) def fetch(url, retries=3): for i in range(retries): try: resp = session.get(url, timeout=10) if resp.status_code == 200: return resp.text except requests.RequestException as e: print(f"[retry {i+1}] {url} -> {e}") time.sleep(2 ** i) return None

但注意,这只适合单线程小规模任务。真要跑全国几千家医院、每个医院3~5个子页,务必用Scrapy的并发能力,不然单线程跑一个晚上都跑不完。

3.2 主表、子队列与去重设计

核心数据流可以概括为"主表 + 子任务队列":

  1. 医院主表:每抓到一家医院就生成一条主记录,赋予唯一ID;
  2. 子任务队列:把详情页、联系方式页、科室页这些待抓URL按"所属医院ID + 页面类型"写入Redis队列;
  3. 去重:URL做MD5后存入Bloom Filter,避免同一页面被重复请求。

这样做的好处是,哪怕某个子页面抓取失败,也不影响主记录的保存,后续只需要对失败队列做定向重跑。我最初没做子任务队列,结果一个医院详情页挂了,整个医院记录都没了,后面补数据时找不到入口,心态直接崩掉。

3.3 请求频率、UA轮换与代理策略

反爬的平衡点在于"伪装得像真人,又足够快"。我实测下来比较稳的一组参数:

  • 请求间隔:1~3秒随机,同一域名下的连续请求不小于1秒;
  • User-Agent轮换:准备20个左右Chrome/Firefox/Safari的UA,每隔几次请求切换;
  • Referer设置:如果抓的是医院官网"联系我们"页,Referer尽量填同站首页;
  • 普通数据源不做代理,只有被明确封IP后才启用代理池。

代理这块提醒一句:医院官网和卫健委站点基本不反爬,没必要一上来就上代理,反而会因为代理IP质量差拖慢速度。第三方挂号平台反爬比较强,先靠降低频率规避,实在不行再考虑代理。

4. 字段提取逻辑与正则清洗细节:六字段完整解析

4.1 医院等级:两种解析思路

医院等级有两个常见来源,解析逻辑完全不同。

第一种是卫健委公示列表里的直接标注,通常在页面上表现为"三级甲等""二级乙等"等固定文字,直接用正则提取:

import re pattern = r"(三级|二级|一级)[甲乙丙][等]?" text = "该院为三级甲等综合医院" match = re.search(pattern, text) print(match.group()) # 三级甲等

第二种是医院官网"医院简介"页的散文描述,比如"我院是集医疗、教学、科研于一体的三级甲等专科医院"。这种文本更乱,需要用医院全称 + 等级关键词双重定位,再对结果做数据字典映射,统一成"三甲""三乙""二甲"等短编码,方便存储和展示。别直接存原始文本,后面排序筛选的时候你会后悔。

4.2 擅长病症:文本相似度不够,走科室白名单

擅长病症是最难提取的字段,因为它本质上不是"语义识别"问题,而是"标签映射"问题。医院不会直接写一行"擅长心脏病",它写的是"心血管内科率先开展冠心病介入治疗,成功实施多例复杂支架植入术"。

我当时放弃了纯文本相似度方案,改成"科室白名单 + 关键词权重"的提取方式:

department_keywords = { "心血管科": ["冠心病", "心律失常", "心力衰竭", "介入"], "神经科": ["脑卒中", "癫痫", "帕金森", "头痛"], "骨科": ["关节置换", "脊柱", "骨折"], } def extract_departments(text): hits = set() for dept, words in department_keywords.items(): if any(w in text for w in words): hits.add(dept) return list(hits)

这样提取出来的是结构化的科室标签,后续搜索和推荐可以直接用。实际跑下来的体验是:擅长病症字段准确率比想象中难做,能到70%以上就算合格,剩下的人工抽查修正就好,别追求100%自动化。

4.3 地址、邮箱、电话的清洗正则

这三类字段靠正则清洗能解决大部分问题:

phone_pattern = r"(?<!\d)(1[3-9]\d{9}|0\d{2,3}-?\d{7,8}|400-?\d{3,4}-?\d{3,4})(?!\d)" email_pattern = r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" address_pattern = r"[\u4e00-\u9fa5]{2,}(?:省|市|区|县|镇|街道|路|街|号)"

电话要注意去重复匹配和400电话的特殊格式;地址清洗则要保留"省市区"前缀,后面做地理编码和距离排序直接依赖它。这里还有个非常容易踩的坑:很多医院官网页面底部有关键词堆砌,会伪造一堆假地址和假电话,清洗时一定要结合页面标题和正文区域做范围限制,直接全页正则匹配会被脏数据污染。

4.4 字段完整性校验

字段提取完,我会做三个层面的校验:缺失率统计、格式非法率、抽样人工核对。如果某个省份的医院电话缺失率超过15%,基本可以断定这个数据源页面结构判断出了问题,需要回头检查该省份的模板是否写错,而不是继续往后跑。

5. 数据质量校验、去重机制与最终交付

5.1 医院记录怎么去重

全国医院数据的重复问题非常严重,同一家医院可能被卫健委、官网、挂号平台重复抓到三遍。我的去重策略是分层进行:

  • URL级去重:子任务队列阶段,靠Bloom Filter挡掉重复页面;
  • 记录级去重:主记录以"医院全称 + 省份 + 等级"作为联合唯一键,医院改名的情况再基于网站域名做二次归并;
  • 人工兜底:导出后用Excel查看疑似重复记录,比如名称只差"省""市"前缀的,统一人工合并。

医院数据不同于商品数据,没有统一的独立商品ID,所以去重必须多级配合,单靠一个字段做唯一键一定会漏。

5.2 编码与导出格式

最终数据要经得起下游使用,导出格式我通常给两份:

  • CSV/Excel:给产品和运营直接使用,字段顺序固定,中文表头;
  • JSON:给后端API对接,字段保持英文名,避免中文编码起争议。

这里有个细节:导出CSV时统一用utf-8-sig编码,不要用纯utf-8,否则某些Windows环境的Excel打开会乱码。我第一版导出就被运营同事反馈乱码,后来改成签名格式才解决。代码只有一行:

import pandas as pd df.to_csv("hospitals.csv", index=False, encoding="utf-8-sig")

5.3 增量更新比全量重抓更重要

医院数据不是一成不变的,等级调整、地址搬迁、科室变化随时可能发生。如果每次更新都全量重抓,成本太高。在实际落地时,我会做增量调度:每周只抓等级和电话变更频率高的卫健委公示页,医院官网两个月全量扫一次。这样既保证数据新鲜度,又把资源消耗控制在一个可控范围内。

6. 权限边界、踩坑复盘与扩展应用

6.1 robots.txt与公开数据的边界

爬虫做多了,一定要对数据边界有清晰的判断。医院等级、地址、电话、邮箱这些信息属于公开公示内容,在合规层面风险相对可控,但依然要遵守几点:

  • 被抓取站点的robots.txt如果有明确禁止路径,尽量不要硬闯;
  • 请求频率不要高到影响对方站点正常服务,这是爬虫从业者最基本的职业操守;
  • 不做医院内部系统、未公开接口、纯登录后台的数据采集。

合规的意义不在于"能不能躲过封禁",而在于整个数据链条拿到明面上都经得起规则审视,这一点对医疗数据的后续使用尤为重要。

6.2 我踩过的几个典型坑

这个项目我先后翻过几次车,最值得说的有三个。

第一个是挂号平台接口的风控。有段时间为了拿擅长病症,我直接请求了某平台的JSON接口,刚开始一切正常,抓了上万条后突然大批量返回403,排查发现对方启用了频率维度的风控。最后解决方案是退回到公开页面解析+拉大请求间隔+降并发,虽然速度慢了,但再没触发封禁。

第二个是编码混乱。部分老旧地市卫健委网站还是GB2312编码,直接用resp.text会乱码。正确做法是:

resp.encoding = resp.apparent_encoding

或者根据返回头里的charset参数去决定解码方式。这个坑极其隐蔽,因为大部分页面是UTF-8,只有遇到老站才会踩到,排查起来非常耗时。

第三个是动态加载。医院官网的"重点科室"页很多是异步渲染,直接requests拿到的HTML里根本没有擅长病症字段。我的处理方式是先用selenium截获XHR请求,找到真实接口,再回到requests伪造成浏览器请求。这里要记住:动态页面的目标是"找到真正的数据接口",而不是一直开着无头浏览器跑,后者效率太低了。

6.3 数据的后续应用还能往哪走

爬下来的全量医院库,除了导诊平台,还能扩展做很多事情。比如结合地理编码服务,把地址字段转换成经纬度,就能做"附近三甲医院"的LBS检索;把擅长病症和科室白名单映射到标准医学疾病分类,就能做症状到医院的推荐系统。再比如针对每个医院维护邮件联系列表,后续做医疗行业调研问卷、医疗设备厂商的市场推广,都是可以直接用的资源。

我在实际使用中发现,这份数据真正的价值不在"抓"而在"养"。持续维护、持续更新、持续清洗的数据集,比一次抓完扔在硬盘里的压缩包有价值得多。如果你拿到的也是一个"医院数据信息爬虫.zip",建议别急着跑完收工,把增量更新的调度先搭起来,后面你会感谢当初这个决定。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 20:38:02

基于MATLAB的六足机器人步态仿真:三角步态与波动步态实现详解

六足机器人这个坑&#xff0c;我是从一台旧笔记本加一份MATLAB授权开始的。当时手上没有舵机、没有结构件、连一根杜邦线都没有&#xff0c;却特别想弄清楚一个看起来很简单的问题&#xff1a;六条腿到底按什么顺序抬起来&#xff0c;才能走得又稳又快&#xff1f;这个问题的答…

作者头像 李华
网站建设 2026/9/20 20:38:00

Simulink信号与系统仿真课程设计全攻略:建模、滤波与踩坑实录

简介&#xff1a;这是一份基于Matlab Simulink的信号与线性系统仿真课程设计文档&#xff0c;适合电子信息、通信工程等专业学生完成信号与系统相关课设或复习仿真方法。文档以完整课程设计报告形式呈现&#xff0c;涵盖快速傅里叶变换&#xff08;FFT&#xff09;、有限冲击响…

作者头像 李华
网站建设 2026/9/20 20:37:49

AI编程工具横向评测:Claude Code、Codex CLI、OpenClaw、Hermes Agent选型指南

市面上 AI 编程工具这两年冒出来一大堆&#xff0c;名字一个比一个唬人&#xff0c;但真正落到日常写代码、改 bug、跑脚本这些事上&#xff0c;能长期留在工具栏里的其实就那么几个。OpenClaw、Hermes Agent、Claude Code、Codex CLI 这四个是最近被问得最多的&#xff0c;问的…

作者头像 李华
网站建设 2026/9/20 20:36:43

OpenResearch:Claude Code、Codex、OpenCode、Cursor 组合工作流实战

1. 从"OpenResearch"这个名字说起&#xff1a;它到底想解决什么问题第一次看到"OpenResearch"这个标题&#xff0c;加上旁边一串 Claude Code、Codex、OpenCode、Cursor 的热词&#xff0c;我大概能猜到这背后想聊的是什么——不是某一个具体工具的安装教程…

作者头像 李华
网站建设 2026/9/20 20:36:39

WebGIS空气质量可视化实战:Leaflet+ECharts构建湖南省级监测系统源码解析

简介&#xff1a;这是一份面向 WebGIS 入门者、前端开发者及环保数据分析人员的可运行源码包。项目以湖南省空气质量为实际案例&#xff0c;演示了从百度天气接口获取实时空气质量数据&#xff0c;再通过 Leaflet 实现 WebGIS 可视化展示的完整流程&#xff0c;包含省内中、重污…

作者头像 李华