为了账号安全,请及时绑定邮箱和手机立即绑定

使用 Python 抓取、分析、可视化—万家医疗诊所信息

标签:
Java Python

本篇文章是使用 Python 抓取万家医疗上面的诊所信息,并且对关键信息进行分析,实现数据可视化。由于时间和能力的问题,能抓取的数据类型较少,分析的维度也不足。但是尝试去剖析在国家倡导分级诊疗的大环境下,移动医疗在社区诊所上的发展情况。所以抓取了万家医疗网站里面的诊所数据,并从诊所区域分布、科室类型以及是否支持医保上进行了数据分析和可视化。

<strong>准备工作</strong>
首先是开始抓取前准备工作,导入需要使用的库文件,爬虫主要使用的是requests和BeautifulSoup两个库,数据分析主要使用 Numpy 和 Pandas 两个库,外加 matplotlib 库实现数据可视化。

<pre>import requests
from bs4 import BeautifulSoup
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
</pre>

<strong>抓取诊所列表信息</strong>
在抓取前需要先观察下万家医疗诊所列表页面的的结构,URL为“"https://www.pinganwj.com/clinic/pa1”,其中 ”pg1”为页面数,共有846个页面,预计诊所有8460家左右,可以使用循环遍历所有的页面,获取信息。

<pre>#设置 url 的前面部分
url = "https://www.pinganwj.com/clinic/"
</pre>

确定了 URL 链接之后,还需要设置浏览器头部(headers)信息,否则系统会识别爬虫程序,从而阻止访问页面。

<pre>#设置url的前面部分
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36',
'Accept':'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, /; q=0.01',
'Accept-Charset':'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
'Accept-Encoding':'utf-8',
'Connection':'keep-alive',
'Referer':'http://www.baidu.com/link?url=_andhfsjjjKRgEWkj7i9cFmYYGsisrnm2A-TN3XZDQXxvGsM9k9ZZSnikW2Yds4s&wd=&eqid=c3435a7d00006bd600000003582bfd1f'
}
</pre>

使用 for 循环生成 1-847 的数字,转化格式后与前面的 URL 固定部分拼成要抓取的 URL。这里我们设置每两个页面间隔 0.5 秒。抓取到的页面保存在 html 中。

<pre>#循环抓取列表页信息
for i in range(1,847):
if i == 1:
i=str(i)
a=(url+'pg'+i)
r=requests.get(url=a,headers=headers)
html=r.text
else:
i=str(i)
a=(url+'pg'+i)
r=requests.get(url=a,headers=headers)
html2=r.text
html = html + html2
#每次间隔0.5秒
time.sleep(0.5)
#在页面打印爬取进度
print ('正在爬取第'+i+"页")
</pre>

https://img1.sycdn.imooc.com//5d3122a90001a2b607610277.jpg

@爬取进度页面|center

<strong>解析页面并提取信息</strong>
页面爬取下来之后,需要使用 BeautifulSoup 对页面进行解析,变成我们在浏览器查看源代码中看到的样子,这样我们才能提取关键信息。

<pre>#使用 BeautifulSoup 解析抓取的页面内容
wj = BeautifulSoup(html,'html.parser')
</pre>

到目前为止,我们已经 800+ 多个页面的信息爬取下来,并且通过 BeautifulSoup 解释为我们常见的源代码方式。下面就是通过分析爬取字段中 <code>Div</code>的 id 或者 class 提取关键信息。

<pre>#将诊所列表中的信息保存在 hospital 中,其中 find_all 获取的是一个 list,就是每个诊所就是list上的一个对应元素。
hospital = wj.find_all('div',attrs = {"class":"cli-list left"})
</pre>

继续在<code>hospital</code>中提取诊所名称、医保信息、科室和地区信息,将各项信息存储到各自的<code>list</code>中。使用到的方法基本一样,需要自行调整一下定位就好。

<pre>#获取诊所名称
hn = []
for a in hospital:
hospital_name = a.h1.get_text()
hn.append(hosptal_name)

获取诊所医保信息

yb = []
for c in hospital:
yibao_info = c.find_all('span', attrs = {'class':'medicare'})
yibao = yibao_info
yb.append(yibao)

获取诊所科室

ks = []
for b in hospital:
keshi = b.p.get_text()
ks.append(keshi)

获取诊所地址

address = []
for d in hospital:
address_info = d.find_all('script')
address.append(address_info)
</pre>

<strong>数据分析和数据可视化</strong>
将拿到的数据使用 Pandas 库生成数据表,方便后面分析。

<pre>#将诊所名称、医保信息、科室和地区等信息生成数据表
hospital_list=pd.DataFrame({'hospital_name':hn,'hospital_keshi':ks,'hospital_yibao':yb,'hospital_address':address})
</pre>

<strong>诊所分布的省份分析:</strong>
通过使用 groupby 对诊所所在省份进行汇总,通过条形图展示每个省份的诊所数量。

<pre>#对每个省份的诊所数量进行汇总
prov = wj.groupby('hospital_address')['hospital_address'].agg('count')

对省份数据进行排序

prov.sort_values(inplace=True)

生成省份名称列表,下面用作坐标值

prov_name=prov.index

定义图表比例

plt.figure(figsize=(16,9))

定义图表类型并且传入参数

plt.barh(range(len(prov)),prov,tick_label=prov_name)

标注X轴的标签

plt.xlabel(u'诊所数量',fontsize ="14")

用来正常显示中文标签

plt.rcParams['font.sans-serif']=['SimHei']
plt.show()
</pre>

https://img1.sycdn.imooc.com//5d3122af00011d6c07620416.jpg

@诊所省份分布图


有上面的图片可以看出,河南、河北、黑龙江三个省份的诊所数量最多。可能的原因是万家医疗在不同省份推广资源的分配导致的。但是跟深层次的去考虑:为什么不是北京上海广东这些大城市呢?其实很好理解,北京、上海、广东可以说是中国医疗资源最密集的地方,但是这些地方都被大型三甲医院占据,民营的、小型的社区诊所要发展就比较困难。

<strong>诊所分布的科室类型分析:</strong>
使用相同的方式,对不同诊所的科室类型进行分析,分析方法和展示形式基本一样。但是需要强调的是,因为有的诊所拥有多个科室,所以对于这类诊所,我将它们定义为综合类型诊所。

<pre>#对各种科室的诊所数量进行汇总
keshi = wj.groupby("hospital_keshi")["hospital_keshi"].agg("count")

对科室类型数据进行排序

keshi.sort_values(inplace=True)

生成科室名称列表,下面用作坐标值

keshi_name=keshi.index

定义图表比例

plt.figure(figsize=(9,6))

定义图表类型并且传入参数

plt.barh(range(len(keshi)),keshi,tick_label=keshi_name)

标注X轴的标签

plt.xlabel(u'诊所数量',fontsize ="14")

用来正常显示中文标签

plt.rcParams['font.sans-serif']=['SimHei']

展示图表

plt.show()
</pre>

https://img1.sycdn.imooc.com//5d3122b50001aac106050383.jpg

@诊所科室分布


从上面的图表可以看出,占比最大的诊所类型是口腔科类型的诊所,这些诊所大多是民营的,并且倾向私人经营较多。还有中医科主要就是一些私人开办的中医馆。

<strong>诊所是否支持医保:</strong>
对于社区诊所来说,患者还是比较看重是否支持医保支付的,所以医保信息也是相当关键。获取得到的医保数据中,支持医保的显示“是”,不支持医保的为空。统计医保支付的占比,并且制作称饼图。

<pre>#统计汇总医保数量
yibaoinfo = wj.groupby("hospital_yibao")["hospital_yibao"].agg("count")

计算支持医保和非医保数量

yibaoinfo = np.array([yibaoinfo.values,8460-yibaoinfo.values])

定义图表大小

plt.figure(figsize=(9,6))

定义标签值

labels = ['有医保', '无医保']

定义数据值的大小,获取上面的列表信息

size = [yibaoinfo[0],yibaoinfo[1]]
定义图表类型为饼图
plt.pie(size, labels=labels)
plt.axis('equal')
plt.show()
</pre>

https://img1.sycdn.imooc.com//5d3122bb0001054503370344.jpg

@是否支持医保分布|center

从上图可以看到,不到一半的诊所支持医保,也可能是网站信息更新不全,看来医保的路还要继续走呢。

以上就是万家医疗诊所信息爬取和分析的总过程,因为能力的原因,所以爬取数据的维度较少,代码质量和图表也是没有经过美化,显得稍微简陋了一些。如果后面有时间,还会分享更多关于移动医疗+爬虫+数据科学+数据可视化的文章,感谢大家多多关注。

本文为原创文章,如需转载请注明原文出处:<a href = "http://wp.me/p86ISR-gO">http://wp.me/p86ISR-gO</a>



点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消