先上项目地址

格式说明

输出格式为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