首页 > 其他分享 >爬虫实战带上代码讲解(以爬取好大夫为例)

爬虫实战带上代码讲解(以爬取好大夫为例)

时间:2025-01-19 20:37:20浏览次数:1  
标签:doctor 为例 url text get 爬虫 type 取好 name

前言:
我感觉之前讲的爬虫,太纸面化了,需要给一些实例来帮助理解。毕竟爬虫这项技能,我们经常可能用到,通常用于爬虫数据来训练模型。
延续上一篇文章所说将爬虫分为四个主要部分:

获取网页源代码
解析网页并提取数据
实现自动化抓取逻辑
保存数据到文件(如 execl)

第一步:获取网页源代码

要获取网页内容,最直接的方式是使用 requests 库。帮助我们发送 HTTP 请求并获取网页内容。以下是一个基本示例:

import requests

url = "https://example.com"  # 目标网页地址
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36", 
    "Cookie": "your_cookie_value"
}

# 发送请求并获取响应
response = requests.get(url, headers=headers)
html_content = response.text  # 获取网页的 HTML 源代码

参数说明:
url:目标网页的地址。
headers:请求头,用于伪装成真实浏览器,避免被识别为爬虫。关键字段包括:
User-Agent:指定用户代理信息。
Cookie:某些网站需要登录后才能访问完整内容,Cookie 可以帮助模拟登录状态。
得按照实践情况来添加参数

小贴士:
用F12,查看页面请求时的Cookies,便于构造请求头。
使用 response.status_code 确认请求是否成功(200 表示成功)。

第二步:解析网页并提取数据

获取网页源代码后,需要从中提取出关键信息。这一步可以借助 BeautifulSoup。

示例:

def parse_html(html):
    soup = BeautifulSoup(html, 'html.parser')

    old_disease_info = soup.find('p', class_='diseaseinfo') #疾病信息
    disease_info=get_all_text(old_disease_info)
    #print(disease_info)

    header_title = soup.find('h1', class_='header-title')
    text = header_title.get_text(strip=True)
    type = text.split('- ')[-1]#问诊类型
    #print(type)

    meta_og_url = soup.find('meta', property='og:url')
    disease_url = meta_og_url.get('content') #病例url
    #print(disease_url)

    a_tag = soup.find('a', attrs={'target': '_blank', 'rel': 'noreferrer'})
    doctor_url = a_tag.get('href')#医生url
    #print(doctor_url)


    card_info_text = soup.find('div', class_='card-info-text')
    doctor_info=get_all_text(card_info_text) #医生简介
    #print(doctor_info)

    speciality_div = soup.select_one('div[ref="specialityBox"]')
    if speciality_div:
        doctor_speciality = get_all_text(speciality_div)  # 医生擅长
    else:
        doctor_speciality='无说明'
    #print(doctor_speciality)

    doctor_card_service = soup.find('div', class_='doctor-card-service clearfix')
    doctor_service = get_all_text(doctor_card_service) #医生服务质量
    #print(doctor_service)

    suggestions_marginLeft0 = soup.find('section', class_='suggestions')
    doctor_suggestions = get_all_text(suggestions_marginLeft0) #医生建议
    #print(doctor_suggestions)

    msgboard_js_msgboard = soup.find('section', class_='msgboard')
    message= get_all_text(msgboard_js_msgboard) #医生与患者交流
    #print(message)

    return disease_info,type,disease_url,doctor_url,doctor_info,doctor_speciality,doctor_service,doctor_suggestions,message

这部分是用于解析解析单个病例详细页

该页面的所需内容如下
根据以下图片来进行解析网页并提取数据

就简单拿示例来进行讲解:

1.soup = BeautifulSoup(html, 'html.parser')
html.parser 作为解析器,将 html 解析成 soup 对象,方便后续提取数据。

2.old_disease_info = soup.find('p', class_='diseaseinfo') # 疾病信息
disease_info = get_all_text(old_disease_info)

查找<p>标签,并且该标签的 class 是 "diseaseinfo",即疾病描述信息。

get_all_text(old_disease_info) 是一个自定义函数,它会递归提取该标签及其子标签的所有文本信息。之所以这里创建get_all_text()函数是因为<p>的信息不是连续的而是分布在里面的子标签里面
其代码为

def get_all_text(element):
    text = ''
    for content in element.contents:
        if content.name is None:  
            text += content
        else:
            text += get_all_text(content)  # 递归获取子元素的文本
    return text

如下

3.header_title = soup.find('h1', class_='header-title')
text = header_title.get_text(strip=True)
type = text.split('- ')[-1] # 问诊类型
查找 <h1> 标签,class 为 "header-title",表示文章标题。
get_text(strip=True) 获取标题文本内容,并去除两端的空白字符。
text.split('- ')[-1] 提取问诊类型(格式为 "描述 - 问诊类型" 这样的格式)。
如下

4.meta_og_url = soup.find('meta', property='og:url')
disease_url = meta_og_url.get('content') # 病例url
查找 标签,property 属性为 "og:url",通常用于存储当前页面的 URL。
get('content') 提取 content 属性值,即病例的 URL。
如下

5.a_tag = soup.find('a', attrs={'target': '_blank', 'rel': 'noreferrer'})
doctor_url = a_tag.get('href') # 医生url

get('href') 获取医生的个人主页链接。

6.card_info_text = soup.find('div', class_='card-info-text')
doctor_info = get_all_text(card_info_text) # 医生简介
查找 div 标签,class 为 "card-info-text",其中包含医生的简要信息。
get_all_text(card_info_text) 提取该 div 的所有文本信息。
也是因为其信息在子标签里面
如下

7.speciality_div = soup.select_one('div[ref="specialityBox"]')
if speciality_div:
doctor_speciality = get_all_text(speciality_div) # 医生擅长
else:
doctor_speciality = '无说明'
有些病例url里面医生是没有填写擅长的,所以如果 speciality_div 存在,则提取文本,否则返回 "无说明"。
如下

8.doctor_card_service = soup.find('div', class_='doctor-card-service clearfix')
doctor_service = get_all_text(doctor_card_service) # 医生服务质量
查找 div 标签,class 为 "doctor-card-service clearfix",存储医生的服务评分或质量评价。
get_all_text(doctor_card_service) 提取该 div 内的文本。
如下

9.suggestions_marginLeft0 = soup.find('section', class_='suggestions')
doctor_suggestions = get_all_text(suggestions_marginLeft0) # 医生建议
查找 section 标签,class 为 "suggestions",表示医生的建议。
get_all_text(suggestions_marginLeft0) 提取医生对患者的建议文本。
(因为我现在忘记密码了,是未登录状态,因此展示不了)

10.msgboard_js_msgboard = soup.find('section', class_='msgboard')
message = get_all_text(msgboard_js_msgboard) # 医生与患者交流
查找 section 标签,class 为 "msgboard",表示医生和患者的留言互动。
get_all_text(msgboard_js_msgboard) 提取交流信息的文本。
(因为我现在忘记密码了,是未登录状态,因此展示不了)

第三步:实现自动化抓取逻辑
为了抓取页面信息,可能需要采用构造分页参数等操作。

如本次爬取好大夫病例时,我们可以看到

在源代码下结构为

我们需要爬取里面的每种类型的病例
因此我们目的是从 HTML 页面中提取大类和小类的信息,并将它们组织到一个字典中。字典的结构如下:

{
    '大类1': [
        {'name': '小类1', 'url': '小类URL?p='},
        {'name': '小类2', 'url': '小类URL?p='},
        ...
    ],
    '大类2': [
        {'name': '小类1', 'url': '小类URL?p='},
        ...
    ],
    ...
}

因此帮忙写下以下代码

def gain_typeurl(type_web_html):

    soup = BeautifulSoup(type_web_html, 'html.parser')

    type_dict={}

    big_types = soup.find_all('ul', class_=lambda x: x is None )
    print(big_types)

    for big_type in big_types:
        big_type_tag = big_type.find(class_="izixun-department-title")
        big_type_name = big_type_tag.text.strip()
        type_dict[big_type_name] = []

        small_type_tags = big_type.find(class_="izixun-department-list")

        small_tags = small_type_tags.find_all('a')

        for small_tag in small_tags:
            small_type_name = small_tag.text.strip()
            small_type_url =  small_tag['href']
            type_dict[big_type_name].append({
                'name': small_type_name,
                'url': small_type_url+"?p=",
            })

    print(type_dict)

    return type_dict

但是每一类在线诊断,不只有一个页面,还是有10页

那我们需要有在url后加一个页面参数

def directory_pachong(url, name):
    create_execl(name)
    for i in range(1, 11):
        turl = url
        turl = "https:"+ turl + str(i)
        print(url)
        directory = get_html(turl)
        directory_url = gain_url(directory)
        z = 0
        for d_url in directory_url:
            html = get_html(d_url)
            data = parse_html(html)
            write_back_execl(data,name)
            z = z + 1
            l = (i - 1) * 90 + z
            print(l)

该函数的目标是:

循环抓取多个分页(10 页)
对每一页中的所有链接进行访问,并从每个链接的页面中提取数据。
提取的数据会被逐页、逐条写入到 execl文件中,最终保存所有爬取的数据。

接下来我们需要获取,该页面下的全部病历url

比如现在我们就进去了心血管内科

def gain_url(directory):

    soup = BeautifulSoup(directory, 'html.parser')

    directory_url=[]

    list_items = soup.find_all('span', class_='fl')

    for item in list_items:
        a_tag = item.find('a')
        url = a_tag.get('href')
        directory_url.append(url)
    print(directory_url)
    return directory_url

gain_url(directory) 函数的目的是从传入的 HTML 页面中提取所有符合条件的 URL 链接,并将它们保存在一个列表中返回。通过查找页面中的 span 标签(类名为 'fl')来定位包含 url 的 a 标签,然后提取出每个 a 标签的 href 属性值。

第四步:保存数据到 execl文件
爬取的数据需要持久化存储。execl文件是一种常用的结构化存储方式,可通过 openpyxl 库实现。

首先来创建excel的

def create_execl(name):
    wb = Workbook()
    ws = wb.active
    ws.title = name
    excel_headers = ["疾病信息", "问诊类型", "病例url", "医生url", "医生简介", "医生擅长", "医生服务质量", "医生建议", "医生与患者交流"]
    ws.append(excel_headers)
    wb.save(name+".xlsx")

创建一个新的 execl,并获取取当前活动工作表。
设置该名称为传入的 name。
添加一行表头,如代码中的就是表头为疾病信息、问诊类型、病例 URL、医生简介等字段。
将该保存为一个 execl文件,文件名为 name.xlsx。

接下来到添加数据到execl

def write_back_execl(data, name):
    #wb = Workbook()
    wb = load_workbook(name+".xlsx")
    ws = wb.active
    ws.append(data)
    wb.save(name+".xlsx")

该函数的目的是:

加载指定的 execl文件(name + ".xlsx")。
获取文件中的活动工作表。
将传入的 data 列表作为一行数据追加到该工作表的末尾。
保存修改后的 execl文件。

完整代码:

import requests
from bs4 import BeautifulSoup
from openpyxl import Workbook

from openpyxl.reader.excel import load_workbook

headers = {
    "cookie": "自己添加",
    "user-agent": "自己添加",
}

def gain_typeurl(type_web_html):

    soup = BeautifulSoup(type_web_html, 'html.parser')

    type_dict={}

    big_types = soup.find_all('ul', class_=lambda x: x is None )
    print(big_types)

    for big_type in big_types:
        big_type_tag = big_type.find(class_="izixun-department-title")
        big_type_name = big_type_tag.text.strip()
        type_dict[big_type_name] = []

        small_type_tags = big_type.find(class_="izixun-department-list")

        small_tags = small_type_tags.find_all('a')

        for small_tag in small_tags:
            small_type_name = small_tag.text.strip()
            small_type_url =  small_tag['href']
            type_dict[big_type_name].append({
                'name': small_type_name,
                'url': small_type_url+"?p=",
            })

    print(type_dict)

    return type_dict

def gain_url(directory):

    soup = BeautifulSoup(directory, 'html.parser')

    directory_url=[]

    list_items = soup.find_all('span', class_='fl')

    for item in list_items:
        a_tag = item.find('a')
        url = a_tag.get('href')
        directory_url.append(url)
    print(directory_url)
    return directory_url

def get_html(url):
    response = requests.get(url, headers=headers)
    return response.text

# 获取所有文本
def get_all_text(element):
    text = ''
    for content in element.contents:
        if content.name is None:
            text += content
        else:
            text += get_all_text(content)  # 递归获取子元素的文本
    return text

def parse_html(html):
    soup = BeautifulSoup(html, 'html.parser')

    old_disease_info = soup.find('p', class_='diseaseinfo') #疾病信息
    disease_info=get_all_text(old_disease_info)
    #print(disease_info)

    header_title = soup.find('h1', class_='header-title')
    text = header_title.get_text(strip=True)
    type = text.split('- ')[-1]#问诊类型
    #print(type)

    meta_og_url = soup.find('meta', property='og:url')
    disease_url = meta_og_url.get('content') #病例url
    #print(disease_url)

    a_tag = soup.find('a', attrs={'target': '_blank', 'rel': 'noreferrer'})
    doctor_url = a_tag.get('href')#医生url
    #print(doctor_url)


    card_info_text = soup.find('div', class_='card-info-text')
    doctor_info=get_all_text(card_info_text) #医生简介
    #print(doctor_info)

    speciality_div = soup.select_one('div[ref="specialityBox"]')
    if speciality_div:
        doctor_speciality = get_all_text(speciality_div)  # 医生擅长
    else:
        doctor_speciality='无说明'
    #print(doctor_speciality)

    doctor_card_service = soup.find('div', class_='doctor-card-service clearfix')
    doctor_service = get_all_text(doctor_card_service) #医生服务质量
    #print(doctor_service)

    suggestions_marginLeft0 = soup.find('section', class_='suggestions')
    doctor_suggestions = get_all_text(suggestions_marginLeft0) #医生建议
    #print(doctor_suggestions)

    msgboard_js_msgboard = soup.find('section', class_='msgboard')
    message= get_all_text(msgboard_js_msgboard) #医生与患者交流
    #print(message)

    return disease_info,type,disease_url,doctor_url,doctor_info,doctor_speciality,doctor_service,doctor_suggestions,message

def create_execl(name):
    wb = Workbook()
    ws = wb.active
    ws.title = name
    excel_headers = ["疾病信息", "问诊类型", "病例url", "医生url", "医生简介", "医生擅长", "医生服务质量", "医生建议", "医生与患者交流"]
    ws.append(excel_headers)
    wb.save(name+".xlsx")

def write_back_execl(data, name):
    #wb = Workbook()
    wb = load_workbook(name+".xlsx")
    ws = wb.active
    ws.append(data)
    wb.save(name+".xlsx")

def directory_pachong(url, name):
    create_execl(name)
    for i in range(1, 11):
        turl = url
        turl = "https:"+ turl + str(i)
        print(url)
        directory = get_html(turl)
        directory_url = gain_url(directory)
        z = 0
        for d_url in directory_url:
            html = get_html(d_url)
            data = parse_html(html)
            write_back_execl(data,name)
            z = z + 1
            l = (i - 1) * 90 + z
            print(l)



if __name__ == "__main__":
    #directory_pachong()
    xurl = "https://www.haodf.com/bingcheng/list.html"
    url_html=get_html(xurl)
    all_type=gain_typeurl(url_html)
    for big_type, small_types in all_type.items():
        print(f"大类: {big_type}")
        for small_type in small_types:
            print(f"\t小类: {small_type['name']} - 链接: {small_type['url']}")
            small_name=small_type['name']
            small_url=small_type['url']
            directory_pachong(small_url,small_name)

存在缺陷

目前好大夫需要登录后才能查看,我之前一个师兄给了有一个vip账号,但是每天只能爬200条十分鸡肋。(就是来跟大家交流学习的作用而已)

一言两语

明天再战科目三了,十分紧张,一定得过啊。

标签:doctor,为例,url,text,get,爬虫,type,取好,name
From: https://www.cnblogs.com/l-xx123/p/18669663

相关文章

  • 一篇文章带你入门爬虫
    前言本篇引用的很多代码出自猿人学和帅彬老仙,算是把自己的学习笔记发上来了,有些不完善的地方还会继续完善~!http协议:目前互联网上%90的网络传输都是基于http协议,但是弹幕可能采用的是websocket协议,http协议是基于TCP/IP通信协议来传输数据的,http请求流程我们日常用浏览......
  • 你有自己写过爬虫的程序吗?说说你对爬虫和反爬虫的理解?
    是的,我曾经写过一些简单的爬虫程序,主要用于从网站上抓取特定信息,例如新闻数据、商品价格等。这些爬虫程序帮助我自动化地收集数据,节省了大量手动查找和整理的时间。对于爬虫,我的理解是它是一种自动化程序,能够模拟人类在互联网上的浏览行为,按照一定的规则和策略,自动地抓取、解析并......
  • 计算机毕业设计Python+CNN卷积神经网络考研院校推荐系统 考研分数线预测 考研推荐系统
    温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO......
  • 计算机毕业设计Python+Django农产品推荐系统 农产品爬虫 农产品商城 农产品大数据 农
    温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!温馨提示:文末有CSDN平台官方提供的学长联系方式的名片!作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO......
  • 【行空板K10】第三方库在行空板K10显示不可用怎么办?以CodeBlock为例
    目录引言问题用户库的修改测试 本文首发与DFRobot论坛:第三方库在行空板K10显示不可用怎么办?以CodeBlock为例DF创客社区https://mc.dfrobot.com.cn/thread-323692-1-1.html引言试用了一段时间Mind+图形化编程和行空板K10,感觉非常好用。官方的库基本都已经适配行空板K......
  • 利用坦克PWA3快速为应用配置域名:以Gogs为例
    全文概述本文介绍了如何利用坦克PWA3平台快速为Gogs应用配置域名的过程。随着互联网技术的发展,自托管Git服务变得越来越受欢迎,其中Gogs凭借其轻量级和易于安装的特点受到众多开发者的青睐。为提高用户体验,为应用配置一个易记且专业的域名至关重要。文中详细阐述了在坦克PWA3平台......
  • 机器学习算法深度解析与实践案例:以随机森林为例
    机器学习算法深度解析与实践案例:以随机森林为例在当今大数据驱动的时代,机器学习作为人工智能的一个核心分支,正以前所未有的速度改变着各行各业。从金融风控到医疗健康,从自动驾驶到智能推荐系统,机器学习算法的应用无处不在。本文将深入探讨一种广泛应用于分类和回归任务的强......
  • 使用Python爬虫将抓取的数据保存到Excel文件
    在进行Python爬虫开发时,数据的存储是非常重要的一环。随着数据分析需求的不断增长,保存和管理大量的数据变得尤为重要。CSV(Comma-SeparatedValues)格式一直是一个常见的存储格式,但在许多应用场景下,Excel文件作为一种更直观、结构化的方式,具有更多的优势,尤其在数据分析与可视......
  • 动态代理IP池管理:避免爬虫被封禁的高效策略
    在进行大规模数据抓取时,反爬虫机制经常成为爬虫开发者的一大难题。许多网站通过监测请求频率、User-Agent、IP地址等信息来识别并封禁爬虫。为了防止这种情况,动态代理IP池的管理变得尤为重要。通过使用代理IP池,并定期更换IP,可以有效避开基于IP的封禁策略。本篇博客将深入......
  • 使用MapReduce处理爬虫数据:Python与大数据分析的完美结合
    引言随着互联网信息量的爆炸式增长,爬虫技术被广泛应用于从网页上抓取海量数据。这些数据通常需要进一步处理和分析,以提取有价值的信息。然而,随着数据量的增大,传统的单机处理方式已无法满足需求。MapReduce作为一种流行的分布式计算模型,在大规模数据集的处理上发挥了巨大的......