先上项目地址
格式说明
输出格式为csv,表头为:医院名称,省份,城市,医院等级,擅长病症,医院地址,医院电话,医院邮箱,医院网站。
网站解析
网址的page参数是页数,k1到k3分别是省份、等级、重点科室。k4不知道是干什么的,还有一个title参数用来搜索。我要爬取全部医院所以只需要遍历爬取全部页数的网页即可。
https://www.zgylbx.com/index.php?m=content&c=index&a=lists&catid=106&page=1&k1=&k2=&k3=&k4=
网页结构如图,医院列表装在<table>标签里,第零行是表头,之后的奇数行是基本信息,偶数行是医院地址,医院电话,医院邮箱,医院网站。
代码说明
打开csv文件,writerows的参数是每一行的数据,列表嵌套结构,输入crawler函数返回的数据。
if __name__ == '__main__':
url, headers = init()
with open('hospital.csv', 'a') as f:
write = csv.writer(f)
write.writerows(crawler(url, headers))
crawler函数先设置表头,然后遍历全部页面,将解析成list的数据添加到rows,最后返回rows。
def crawler(u, h):
rows = [["医院名称", '省份', '城市', "医院等级", '擅长病症', '医院地址', '医院电话', '医院邮箱', '医院网站']]
for i in range(1, 1530):
r = requests.get(str(u) + str(i) + "&k1=0&k2=0&k3=0&k4=", headers=h, timeout=20)
print('url:'+str(u) + str(i) + "&k1=0&k2=0&k3=0&k4=")
soup = BeautifulSoup(r.text, "html.parser")
message = soup.find_all('tr')
rows.extend(get_rows(message))
return rows
get_rows函数将每一页的数据解析成一个list,从索引1开始遍历,设置一个flag确定当前行的类型,医院详细信息是写在一个标签里用br标签隔开的,所以手动分割一下。
def get_rows(msg):
row_list = []
row = []
sub_row = False
for line in msg[1:]:
data = line.find_all('td')
if not sub_row:
prov_city = data[1].text.strip().split('-')
row = [
data[0].text,
prov_city[0],
prov_city[1],
data[2].text,
data[3].text
]
sub_row = True
else:
data = str(data[0]).split('<br/>')
add = data[0].strip().split('医院地址:')[-1]
tel = data[1].strip().split('医院电话:')[-1]
mail = data[2].strip().split('医院邮箱:')[-1]
site = data[3].strip().split('医院网站:')[-1][:-5]
row.extend([add, tel, mail, site])
row_list.append(row)
sub_row = False
return row_list