python药材数据可视化分析系统 中药数据分析 医药数据分析 Django框架 Echarts可视化 requests爬虫 大数据 毕业设计✅

博主介绍:✌全网粉丝50W+,前互联网大厂软件研发、集结硕博英豪成立软件开发工作室,专注于计算机相关专业项目实战6年之久,累计开发项目作品上万套。凭借丰富的经验与专业实力,已帮助成千上万的学生顺利毕业,选择我们,就是选择放心、选择安心毕业✌
> 🍅想要获取完整文章或者源码,或者代做,拉到文章底部即可与我联系了。🍅

点击查看作者主页,了解更多项目!

🍅感兴趣的可以先收藏起来,点赞、关注不迷路,大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助同学们顺利毕业 。🍅

1、毕业设计:2025年计算机专业毕业设计选题汇总(建议收藏)✅

2、最全计算机专业毕业设计选题大全(建议收藏)✅

1、项目介绍

技术栈:
Python语言、Django框架、Echarts可视化、requests爬虫、HTML、MySQL数据库
药材数据可视化、中药数据可视化

药材:枸杞、黄芪、金银花、当归、陈皮、柴胡、升麻
中药材天地网 https://www.zyctd.com/

2、项目界面

(1)药材产地占比饼图分析

在这里插入图片描述

(2)词云图分析
在这里插入图片描述

(3)药材价格柱状图分析

在这里插入图片描述

(4)药材成分分析
在这里插入图片描述

(5)历史价格分析
在这里插入图片描述

(6)后台数据管理

在这里插入图片描述

(7)注册登录

在这里插入图片描述

(8)数据采集

在这里插入图片描述

3、项目说明

功能模块介绍

(1)药材产地占比饼图分析
  • 功能描述
    • 通过饼图展示不同产地的药材在市场中的占比情况。
    • 帮助用户了解哪些地区是主要的药材产地,以及各产地药材的市场贡献比例。
  • 技术实现
    • 使用 ECharts 的饼图组件进行可视化展示。
    • 数据通过爬虫从中药材天地网等渠道采集,存储到 MySQL 数据库中。
    • Django 后端负责从数据库中提取数据,并传递到前端页面。
(2)词云图分析
  • 功能描述
    • 生成与药材相关的高频词汇的词云图。
    • 帮助用户快速了解当前市场中热门的药材品种、产地、功效等关键词。
  • 技术实现
    • 使用 Python 的 wordcloud 库生成词云图。
    • 数据来源可以是中药材天地网的新闻、论坛帖子、用户搜索记录等。
    • Django 后端将生成的词云图传递到前端页面展示。
(3)药材价格柱状图分析
  • 功能描述
    • 展示不同药材在当前市场中的价格分布情况。
    • 通过柱状图直观地比较不同药材的价格高低,帮助用户了解市场行情。
  • 技术实现
    • 使用 ECharts 的柱状图组件进行可视化展示。
    • 数据通过爬虫从中药材天地网等渠道采集,存储到 MySQL 数据库中。
    • Django 后端负责从数据库中提取数据,并传递到前端页面。
(4)药材成分分析
  • 功能描述
    • 提供药材的主要成分分析,帮助用户了解药材的药用价值。
    • 可能包括药材中不同化学成分的含量及其功效说明。
  • 技术实现
    • 使用 HTML 和 CSS 构建成分分析页面。
    • 数据可以来源于中药材天地网的药材介绍页面或其他专业资料。
    • Django 后端负责从数据库中提取数据,并传递到前端页面。
(5)历史价格分析
  • 功能描述
    • 展示药材在不同时间段内的历史价格走势。
    • 帮助用户了解药材价格的波动趋势,预测未来价格变化。
  • 技术实现
    • 使用 ECharts 的折线图组件进行可视化展示。
    • 数据通过爬虫从中药材天地网等渠道采集,存储到 MySQL 数据库中。
    • Django 后端负责从数据库中提取数据,并传递到前端页面。
(6)后台数据管理
  • 功能描述
    • 提供管理员对药材数据的管理功能,包括数据录入、更新、删除等操作。
    • 确保数据库中存储的药材数据的准确性和完整性。
  • 技术实现
    • 使用 Django 框架构建后台管理系统。
    • 数据存储在 MySQL 数据库中,通过 Django 后端进行数据操作。
    • 提供用户认证和权限管理功能,确保只有管理员可以访问后台管理系统。
(7)注册登录
  • 功能描述
    • 提供用户注册和登录功能。
    • 用户可以通过用户名和密码登录系统,访问个人中心和其他功能模块。
  • 技术实现
    • 使用 Django 的用户认证模块(如 Django-Auth)实现用户登录功能。
    • 用户信息存储在 MySQL 数据库中,通过 Django 后端进行数据验证和管理。
(8)数据采集
  • 功能描述
    • 使用 Python 的 requests 库和爬虫技术从中药材天地网等渠道采集药材数据。
    • 定期更新数据库中的药材信息,确保数据的时效性。
  • 技术实现
    • 编写爬虫脚本,使用 requests 库发送 HTTP 请求,获取网页内容。
    • 使用正则表达式或 HTML 解析库(如 BeautifulSoup)提取网页中的药材数据。
    • 将采集到的数据存储到 MySQL 数据库中,供其他模块使用。

4、核心代码

import requests
from bs4 import BeautifulSoup
import re
import jieba
import pandas as pd
import time
import collections
import pymysql
from sqlalchemy import create_engine

#爬虫获取产品ID
def get_cpid (keyword):
    url=f'http://www.zyctd.com/Search/Index?keyword={keyword}'
    #获取网页数据
    res=requests.get(url)
    #编码
    res.encoding = 'utf-8'
    #解析网页数据
    # print(res.text)
    print("爬取网页数据成功!")
    soup = BeautifulSoup(res.text, 'lxml')
    print("解析网页成功!")


    #通过正则表达式返回要的数据
    # reg=re.compile('(?<=gongxiao).*?(?=.html)')
    # print("正则表达式提取数据成功!")
    # print(reg)

    # 找到所有class为'cloud-data'的<a>标签
    links = soup.find_all('a', class_='cloud-data')


    for link in links:
        href = link['href']
        match = re.search(r'id=(\d+)', href)
        if match:
            cpid=match.group(1)
            print(cpid)  # 输出: 75
    #对返回值进行数据提取。拿到产品ID
    # cpid = reg.findall(str(soup.find('li','hover')))[0]
    print("拿到产品ID了!")
    # print(f"产品ID为:{cpid}")
    return cpid

def get_yf_fun(cpid,ys=0):
    # 药方: https://www.zyctd.com/data/zzjf.html?id=75

    # 请求地址
    url = 'https://www.zyctd.com/api/data-service/api/v1/product/getTcmPrescriptionPage'
    # 设置tcmid=cpid,设置药方数量每次为100个,
    j = {"init": 0, "tcmId": cpid, "nameAndIndications": '', "years": "0",
         "pageRequest": {"pageNumber": ys+1, "pageSize": 100}}

    # 得到链接的内容
    res = requests.post(url, json=j, headers=headers)
    # 编码
    res.encoding = 'utf-8'
    # 将返回值转化为元组,方便提取
    return eval(res.text)

def get_yf_totalRows(cpid):
    result=get_yf_fun(cpid,1)
    if result['code']==0:
        totalRows=result['data']['totalRows']
        print(f"共有{totalRows}个药方")
        return totalRows
    else:
        print('获取药方数量失败')
        
# 获取药方清单  
def get_yf_list(cpid,totalRows,keyword):
    datas = {
        'uid': [],
        'name': [],
        'recipe': [],
        'dosage': [],
        'excerpt': [],
        'indications': [],
        'note': [],
        'processing':[],
        'tcmName': [],
        'recipe_pz': [],
    }
    counts = {}
    print(f"系统将分成{totalRows // 100 + 1}页获取药方")
    # 去除一些语气词和没有意义的词
    del_words = ['的', ' ', '克', '两', 'g', '千克', '钱', '斤','毫升','浸一宿','两钱','各克']
    # 除100(每次取100个药方)向下取整然后+1,遍历所有药方清单
    for row_i in range(totalRows // 100 + 1):
        print(f'开始获取第{row_i+1}页药方')
        result=get_yf_fun(cpid,row_i)
        for res in result['data']['pageContent']:
            if ('克' in res['recipe']) or ('g' in res['recipe']) or('钱' in res['recipe']) or('斤' in res['recipe'])or('两' in res['recipe']):
                datas['uid'].append(res['id'])
                datas['dosage'].append(res['dosage'])
                datas['excerpt'].append(res['excerpt'])
                datas['indications'].append(res['indications'])
                datas['name'].append(res['name'])
                datas['note'].append(res['note'])
                datas['processing'].append(res['processing'])
                datas['recipe'].append(res['recipe'])
                datas['tcmName'].append(res['tcmName'])
                # 对药方进行处理
                # 去掉标点符号
                all_quotes = re.sub(r"[0-9\s+\.\!\/_,$%^*()?;;:-【】+\"\']+|[+——!,;:。?、~@#¥%……&*()]+", "", res['recipe'])
                # 结巴分词自动切割,得到每个药方有什么药材
                words = jieba.lcut(all_quotes)
                words_final = []
                # 如果词不在即将去除的内容中,就添加
                for word in words:
                    if word not in del_words and len(word)>1:
                        words_final.append(word)
                        counts[word] = counts.get(word, 0) + 1
                datas['recipe_pz'].append(words_final)
        #把药方药材存到excel
        pd_datas=pd.DataFrame(datas)
        pd_datas.to_excel(f'./data/{keyword}药方.xlsx',index=None)

    print(f"经过排除后,共获取到{len(datas['uid'])}个药方")


#     # 获取药材市场价格
def get_yc_scjg(keyword,cpid):
    url=f'https://www.zyctd.com/jh{cpid}.html'
    # 根据要求构造请求头文件

    # 得到链接的内容
    res = requests.get(url, headers=headers)
    # 编码
    res.encoding = 'utf-8'
    # 解码
    soup = BeautifulSoup(res.text, 'lxml')
    # print(soup)
    tbody_s = soup.find('table', class_='full center price').find('tbody').find_all('tr')  # 寻找 zixun-item 类型的类
    # tbody_s = soup.find('table', class_='tableBase').find('tbody').find_all('tr')  # 寻找 zixun-item 类型的类   #原始代码


    print("已经拿到了tbody_s")
    print(tbody_s)

    cd_s=[]  #产地
    jg_s=[]  #价格
    for tbody in tbody_s:
        td_s=tbody.find_all('td')
        cd=td_s[1].text
        jg=td_s[2].text.replace('¥','')
        cd_s.append(cd)
        jg_s.append(float(jg))

    # 保存 产地价格
    with open("./data/{}产地价格.csv".format(keyword),'w+',encoding='utf-8') as fp:
        fp.write("keyword\torigin\tprice\n")
        for idx in range(len(cd_s)):
            fp.write(keyword+'\t'+cd_s[idx]+"\t"+str(jg_s[idx])+"\n")


    #  获取历史价格   (取 产地价格 最后一行数据作为“历史价格”)
    print("获取历史价格开始--------------")
    mid = jg_s[-1]    # 使用-1作为索引来获取列表的最后一个元素
    # print(jg_s)
    # mid = jg_s
    print(mid)


    #原始代码:  通过正则表达式返回要的数据
    # reg=re.compile('(?<=historyPriceMID = parseInt\(\").*?(?=\"\);)')
    # mid = reg.findall(str(soup))[0]

    #这个mid在获取历史价格的时候需要
    return  mid


    from datetime import datetime
    # 如果你只想要日期部分(格式化的字符串)
    formatted_updateTime_date_only = datetime.now().strftime('%Y-%m-%d')
    print(formatted_updateTime_date_only)

    keyword=ycmc
    updateTime=formatted_updateTime_date_only
    price=mid

    print(keyword,updateTime,price)

    # 使用with语句打开文件,确保正确关闭,并且以追加模式打开
    with open('./data/{}历史价格.csv'.format(keyword), 'a', encoding='utf-8', newline='') as fp:
        # 写入一行数据,每个字段之间用制表符(\t)分隔
        fp.write("{}\t{}\t{}\n".format(keyword, updateTime, price))

    # with open('./data/{}历史价格.csv'.format(keyword),'w+',encoding='utf-8') as fp:
    #     fp.write("keyword\tupdateTime\tprice\n")
    #     # 写入数据行,注意每个字段之间用制表符(\t)分隔
    #     fp.write("{}\t{}\t{}\n".format(keyword, updateTime, price))

        # for idx in range(len(x)):
        #     fp.write(keyword+'\t'+x[idx]+'\t'+str(y[idx])+'\n')
        #
def get_yc_cd_url(cpid,ys):
    url=f'https://www.zyctd.com/gqgy/{cpid}-0-p{ys}.html'
    print(f'正在获取第{ys}页药材供应内容数据')
    # 根据要求构造请求头文件
    # 得到链接的内容
    res = requests.get(url, headers=headers)
    # 编码
    res.encoding = 'utf-8'
    return res.text 

#获得药材产地
def get_yc_cd(keyword,cpid):
    # url  : get_yc_cd_url函数      url=f'https://www.zyctd.com/gqgy/{cpid}-0-p{ys}.html'   ys是页数

    sl_s=[]
    kcd_s=[]
    cd_s=[]
    #获取前10页药材供应内容。每页10个产品
    for i in range(10):
        res_data=get_yc_cd_url(cpid,i+1)
        # 解码
        soup = BeautifulSoup(res_data, 'lxml')
        div_name_list = soup.find_all('div', class_='supply_list')  # 寻找 supply_list 类型的类
        for div_name in div_name_list:
            #数量
            sl=div_name.find_all('li')[1].find('span').text
            #排除供应数量少于吨的
            if '吨' not  in sl:
                continue
            sl_s.append(sl.replace('吨',''))
            #库存地
            kcd=div_name.find_all('li')[2].find('span').text
            kcd_s.append(kcd)
            #产地
            cd=div_name.find_all('li')[3].find('span').text
            cd_s.append(cd)
    #准备数据
    cd_arr=[]
    cd_cd_sl_arr=[]
    for cd_s_i in range(len(cd_s)):
        cd_sl=0
        for cd_s_j in range(cd_s_i+1,len(cd_s)):
            if cd_s[cd_s_i] not in cd_arr and cd_s[cd_s_i]==cd_s[cd_s_j]:
                cd_sl+=int(sl_s[cd_s_j])
        if cd_s[cd_s_i] not in cd_arr:
            cd_arr.append(cd_s[cd_s_i])
            cd_sl+=int(sl_s[cd_s_i])
            cd_cd_sl_arr.append((cd_s[cd_s_i],cd_sl))

    result_sort = sorted(cd_cd_sl_arr, key=lambda x: x[1], reverse=True)  # 排序
    result_sort = collections.OrderedDict(result_sort)
    othervalue = 0
    for i in range(5, len(cd_cd_sl_arr)):
        othervalue += list(result_sort.values())[i]
    values = []
    labels = []
    for i in range(5):
        values.append(list(result_sort.values())[i])
        labels.append(list(result_sort.keys())[i])
    values.append(othervalue)
    labels.append('其他产地')
    print(keyword,labels,values)


    with open('./data/{}药材供应产地.csv'.format(keyword),'w+',encoding='utf-8') as fp:
        fp.write("keyword\torigin\tcount\n")
        for idx in range(len(values)):
            fp.write(keyword+'\t'+labels[idx]+'\t'+str(values[idx])+'\n')

def get_yc_sczixun_url(cpid,ys):
    url = f'https://www.zyctd.com/zixun/202/pz{cpid}-{ys}.html'
    print(f'正在获取第{ys}页数据')
    # 根据要求构造请求头文件

    # 得到链接的内容
    res = requests.get(url, headers=headers)
    # 编码
    res.encoding = 'utf-8'
    return res.text
    print(res.text)


#  市场资讯
def  get_yc_sczixun(keyword,cpid):
    # 爬取:get_yc_sczixun_url函数  https://www.zyctd.com/zixun/202/pz{cpid}-{ys}.html
    # 例如: https://www.zyctd.com/zixun/202/pz75-1.html

    zx_title=[]
    zx_content=[]
    #获取前3页药材市场资讯。每页10个资讯
    for i in range(3):
        # print("调用get_yc_sczixun_url开始")
        res_data=get_yc_sczixun_url(cpid,i+1)
        print("调用get_yc_sczixun_url结束")

        # 解码
        soup = BeautifulSoup(res_data, 'lxml')
        print("解码完成")
        # print(soup)




        # 定位<div class="zixun-list">的内容(但这里我们通常只是用它来定位,不直接用它的内容)
        # 遍历所有<div class="zixun-item-box">元素(因为它们是包含所需信息的容器)
        item_boxes = soup.find_all('div', class_='zixun-item-box')

        # 提取每个item-box的标题和内容
        for item_box in item_boxes:
            # 提取标题
            title = item_box.find('div', class_='zixun-item-title').find('span').text.strip()
            # 提取描述
            content = item_box.find('div', class_='zixun-item-desc').find('div', class_='lay3').find('p').text.strip()
            # 打印结果
            print(f"标题: {title}")
            print(f"描述: {content}\n")

            zx_title.append(title)
            zx_content.append(content)
            # print(zx_title,zx_content)


    print("已完成:获取前3页药材市场资讯")
    print("---------------------------------------------------")


    with open('./data/{}药材市场资讯.csv'.format(keyword),'w+',encoding='utf-8') as fp:
        fp.write("keyword\ttitle\tcontent\n")
        for i in range(len(zx_title)):
            title = zx_title[i]
            content = zx_content[i]
            print(title,type(title))
            print(content,type(content))
            if not title:
                continue
            elif not content:
                continue
            elif len(content) < 50:
                continue
            elif "BORDER-BOTTOM" in content:
                continue
            elif "spanstyle" in content:
                continue
            else:
                s = keyword+'\t'+title+'\t'+content+'\n'
                if len(s) < 50:
                    continue
                else:
                    fp.write(s)
    print("---------------------------------------------------")
    print("药材市场资讯已写入.csv文件!")

def writeData(keyword):
    engine = create_engine("mysql+pymysql://root:123456@localhost:3306/materialsDB?charset=utf8")

    df = pd.read_excel('./data/{}药方.xlsx'.format(keyword))
    df.to_sql('prescript', con=engine, if_exists='append', index=False)

    df = pd.read_csv('./data/{}产地价格.csv'.format(keyword),sep='\t')
    df.to_sql('originprice', con=engine, if_exists='append', index=False)

    df = pd.read_csv('./data/{}历史价格.csv'.format(keyword),sep='\t')
    df.to_sql('historyprice', con=engine, if_exists='append', index=False)

    df = pd.read_csv('./data/{}药材供应产地.csv'.format(keyword),sep='\t')
    df.to_sql('originstatistics', con=engine, if_exists='append', index=False)

    df = pd.read_csv('./data/{}药材市场资讯.csv'.format(keyword),sep='\t')
    df.dropna(axis=0, how='any', inplace=True)
    df.to_sql('info', con=engine, if_exists='append', index=False)
    print("已写入MySQL数据库!")


if __name__ == '__main__':
    keyword=input('请输入您要搜索什么药材(例如:柴胡、枸杞、升麻...):')
    # 获取药材ID   √
    cpid=get_cpid(keyword)

    # # 获取药方数量  √
    totalRows=get_yf_totalRows(cpid)
    # # 获取药方清单   √
    get_yf_list(cpid,totalRows,keyword)

    # # 获取药材市场价格  √
    mid=get_yc_scjg(keyword,cpid)
    # # 获得药材的价格 √
    get_yc_jg(keyword,cpid,mid)

    # # 获取药材市场资讯  √
    get_yc_sczixun(keyword,cpid)

    # 写入MySQL数据库,只写入该【关键词】的数据   √
    writeData(keyword)

🍅✌感兴趣的可以先收藏起来,点赞关注不迷路,想学习更多项目可以查看主页,大家在毕设选题,项目编程以及论文编写等相关问题都可以给我留言咨询,希望可以帮助同学们顺利毕业!🍅✌

5、源码获取方式

🍅由于篇幅限制,获取完整文章或源码、代做项目的,拉到文章底部即可看到个人联系方式。🍅

点赞、收藏、关注,不迷路,下方查看👇🏻获取联系方式👇🏻

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值