当前位置: 首页 > news >正文

【愚公系列】《Python网络爬虫从入门到精通》063-项目实战电商数据侦探(主窗体的数据展示)

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟

📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主!

👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"挖山不止"的毅力为开发者们搬开知识道路上的重重阻碍!

💎【行业认证·权威头衔】
✔ 华为云天团核心成员:特约编辑/云享专家/开发者专家/产品云测专家
✔ 开发者社区全满贯:CSDN博客&商业化双料专家/阿里云签约作者/腾讯云内容共创官/掘金&亚马逊&51CTO顶级博主
✔ 技术生态共建先锋:横跨鸿蒙、云计算、AI等前沿领域的技术布道者

🏆【荣誉殿堂】
🎖 连续三年蝉联"华为云十佳博主"(2022-2024)
🎖 双冠加冕CSDN"年度博客之星TOP2"(2022&2023)
🎖 十余个技术社区年度杰出贡献奖得主

📚【知识宝库】
覆盖全栈技术矩阵:
◾ 编程语言:.NET/Java/Python/Go/Node…
◾ 移动生态:HarmonyOS/iOS/Android/小程序
◾ 前沿领域:物联网/网络安全/大数据/AI/元宇宙
◾ 游戏开发:Unity3D引擎深度解析
每日更新硬核教程+实战案例,助你打通技术任督二脉!

💌【特别邀请】
正在构建技术人脉圈的你:
👍 如果这篇推文让你收获满满,点击"在看"传递技术火炬
💬 在评论区留下你最想学习的技术方向
⭐ 点击"收藏"建立你的私人知识库
🔔 关注公众号获取独家技术内参
✨与其仰望大神,不如成为大神!关注"愚公搬代码",让坚持的力量带你穿越技术迷雾,见证从量变到质变的奇迹!✨ |

文章目录

  • 🚀前言
  • 🚀一、主窗体的数据展示
    • 🔎1.显示前10名热卖榜图文信息
      • 🦋1.1 步骤概述
      • 🦋1.2 具体步骤
        • ☀️(1) 导入自定义模块并创建对象
        • ☀️(2) 获取热卖排行榜信息并插入数据库
        • ☀️(3) 创建 `show_top10()` 方法显示图文信息
        • ☀️(4) 创建用于显示商品图片的 `QLabel` 控件
        • ☀️(5) 创建用于显示好评率的 `QLabel` 控件
        • ☀️(6) 创建用于显示商品名称的 `QLabel` 控件
        • ☀️(7) 创建用于显示商品价格的 `QLabel` 控件
        • ☀️(8) 创建关注商品按钮 `QPushButton`
        • ☀️(9) 将动态创建的布局添加到网格布局
        • ☀️(10) 在主程序入口调用 `show_top10()` 方法
      • 🦋1.3 运行效果
    • 🔎2.显示关注商品列表
      • 🦋2.1 确认关注
      • 🦋2.2 取消关注
    • 🔎3.显示商品分类比例饼图
      • 🦋3.1 创建 `chart.py` 文件
      • 🦋3.2 创建 `pie_chart()` 方法显示饼图
      • 🦋3.3 在 `show_window.py` 中导入自定义饼图类
      • 🦋3.4 排除重复商品名称并计算分类比例
      • 🦋3.5 计算其他商品分类的占比
      • 🦋3.6 创建饼图并显示
      • 🦋3.7 调用 `show_classification()` 方法显示饼图
      • 🦋3.8 运行并显示饼图


🚀前言

在之前的内容中,我们已经完成了电商数据侦探项目的多个环节,包括需求分析、系统设计、UI设计以及数据的爬取与存储。现在,我们进入了项目的下一阶段——主窗体的数据展示

数据展示是爬虫项目中至关重要的一步,因为它直接影响到用户如何理解和利用爬取到的数据。一个清晰、直观的数据展示界面不仅能提升用户体验,还能帮助用户更有效地分析和决策。在本篇文章中,我们将重点讨论如何将爬取到的电商数据呈现给用户,并为后续的数据分析提供方便。

具体内容包括:

  1. 数据展示的设计原则:如何设计一个直观的界面,确保用户可以清晰地看到爬取的数据,避免信息过载。
  2. 商品信息展示:将商品的关键信息(如名称、价格、评分、销量等)通过表格、列表或图形化的方式展示,确保用户能够轻松浏览。
  3. 价格走势图展示:通过图表的方式展示商品的价格波动情况,帮助用户分析商品价格的走势和规律。
  4. 用户评价展示:展示商品的用户评论,包括评分、评论内容等,便于用户了解其他消费者的购买体验。
  5. 交互与更新:实现动态数据展示,支持用户刷新、筛选或排序数据,以便于用户根据不同需求查看信息。
  6. 数据的可视化展示:使用图表或图形方式进一步呈现数据趋势,例如价格变化趋势图、热销商品排名图等,提升数据分析的可视化效果。

通过本篇文章的学习,你将学会如何将爬取到的电商数据通过精心设计的主窗体展现给用户,使数据不仅仅是冷冰冰的数字,而是充满价值的信息和见解。这将大大提升你爬虫项目的实用性和商业价值。

🚀一、主窗体的数据展示

在实现主窗体数据展示时,需要考虑到主窗体中有三个区域:

  1. 显示前10名热卖榜图文信息
  2. 显示关注商品列表
  3. 显示商品分类饼图

首先,我们需要动态创建“显示前10名热卖榜图文信息”的布局,并实现商品的关注功能。接着,我们将单独创建一个图表文件来显示商品分类比例的饼图。最后,使用数据库操作文件将所有数据显示在主窗体中。

🔎1.显示前10名热卖榜图文信息

🦋1.1 步骤概述

  1. 导入相关自定义模块:首先,需要导入自定义数据库操作类和爬虫类。
  2. 获取热卖榜信息并插入数据库:爬取热卖榜信息并将其保存至数据库中。
  3. 从数据库中提取数据:从数据库中提取前10名热卖榜信息。
  4. 动态创建布局:根据提取的数据显示图文信息。
  5. 显示热卖榜图文信息:将图文信息展示在主窗体上。

🦋1.2 具体步骤

☀️(1) 导入自定义模块并创建对象

首先,在 show_window.py 文件中导入数据库操作类和爬虫类,并创建相应的对象。代码如下:

from mysql import MySQL
from crawl import Crawlmycrawl = Crawl()  # 创建爬虫类对象
mysql = MySQL()    # 创建数据库对象# 连接数据库
sql = mysql.connection_sql()# 创建数据库游标
cur = sql.cursor()
☀️(2) 获取热卖排行榜信息并插入数据库

Main 类的 __init__() 方法中,获取热卖排行榜信息与商品价格,并将数据保存到数据库中。代码如下:

# 获取热卖排行榜信息
id_str = mycrawl.get_rankings_json('https://ch.jd.com/hotsale2?cateid=686')
rankings_list = mycrawl.get_price(id_str)  # 获取价格,然后在该方法中将所有数据保存至列表并返回
mysql.insert_ranking(cur, rankings_list, 'jd_ranking')  # 将数据插入数据库
☀️(3) 创建 show_top10() 方法显示图文信息

Main 类中,创建 show_top10() 方法来显示前10名热卖榜图文信息。在该方法中,首先创建外层布局 QWidget 控件。代码如下:

def show_top10(self):top_10_info = mysql.query_top10_info(cur)  # 查询排行数据表前10名商品名称,价格,好评率# 行数标记i = -1for n in range(10):# x 确定每行显示的个数 0,1,2 每行2个x = n % 2# 当x为0的时候设置换行 行数+1if x == 0:i += 1# 创建布局self.widget = QtWidgets.QWidget()# 给布局命名self.widget.setObjectName("widget" + str(n))# 设置布局样式self.widget.setStyleSheet('QWidget#' + "widget" + str(n) + "{border:2px solid rgb(175, 175, 175);background-color: rgb(255, 255, 255);}")
☀️(4) 创建用于显示商品图片的 QLabel 控件

依次添加代码,在 QWidget 控件中创建用于显示商品图片的 QLabel 控件。代码如下:

# 创建个Qlabel控件用于显示图片 设置控件在QWidget中
self.label = QtWidgets.QLabel(self.widget)
# 设置大小
self.label.setGeometry(QtCore.QRect(15, 15, 160, 160))
# 设置要显示的图片
self.label.setPixmap(QtGui.QPixmap('img_download/' + str(n) + '.jpg'))
# 图片显示方式 让图片适应QLabel的大小
self.label.setScaledContents(True)
# 给显示图片的label控件命名
self.label.setObjectName("img_download" + str(n))
# 设置控件样式
self.label.setStyleSheet('border:2px solid rgb(175, 175, 175);')
☀️(5) 创建用于显示好评率的 QLabel 控件

添加代码,在 QWidget 控件中创建用于显示好评率的 QLabel 控件。代码如下:

# 显示好评的Label控件
self.label_good = QtWidgets.QLabel(self.widget)
# 给好评率控件命名
self.label_good.setObjectName("good" + str(n))
self.label_good.setGeometry(QtCore.QRect(24, 180, 141, 40))  # 设置控件位置及大小
# 设置控件样式,边框与颜色
self.label_good.setStyleSheet("border: 2px solid rgb(255, 148, 61);color: rgb(255, 148, 61);")
self.label_good.setAlignment(QtCore.Qt.AlignCenter)  # 控件内文字居中显示
self.label_good.setText('好评率' + top_10_info[n][2])  # 显示好评率的文字
font = QtGui.QFont()    # 创建字体对象
font.setPointSize(18)   # 设置字体大小
font.setBold(True)     # 开启粗体属性
font.setWeight(75)     # 设置文字粗细
self.label_good.setFont(font) # 设置字体
☀️(6) 创建用于显示商品名称的 QLabel 控件

依次添加代码,在 QWidget 控件中创建用于显示商品名称的 QLabel 控件。代码如下:

# 显示名称的Label控件
self.label_name = QtWidgets.QLabel(self.widget)
# 给显示名称控件命名
self.label_name.setObjectName("good" + str(n))
# 设置控件位置及大小
self.label_name.setGeometry(QtCore.QRect(185, 30, 228, 80))
self.label_name.setText(top_10_info[n][0])  # 设置显示名称的文字
# 左上角为主显示文字
self.label_name.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
self.label_name.setWordWrap(True)  # 设置文字自动换行
font = QtGui.QFont()  # 创建字体对象
font.setPointSize(9)  # 设置字体大小
font.setBold(True)    # 开启粗体属性
font.setWeight(75)    # 设置文字粗细
self.label_name.setFont(font)   # 设置字体
☀️(7) 创建用于显示商品价格的 QLabel 控件

依次添加代码,在 QWidget 控件中创建用于显示商品价格的 QLabel 控件。代码如下:

# 显示价格的Label控件
self.label_price = QtWidgets.QLabel(self.widget)
# 给显示价格控件命名
self.label_price.setObjectName("price" + str(n))
# 设置控件位置及大小
self.label_price.setGeometry(QtCore.QRect(200, 80, 228, 80))
# 设置控件样式
self.label_price.setStyleSheet("color: rgb(255, 0, 0);")
self.label_price.setText('¥' + top_10_info[n][1])  # 设置显示的价格文字
font = QtGui.QFont()    # 创建字体对象
font.setPointSize(20)   # 设置字体大小
font.setBold(True)     # 开启粗体属性
font.setWeight(75)     # 设置文字粗细
self.label_price.setFont(font)   # 设置字体
☀️(8) 创建关注商品按钮 QPushButton

依次添加代码,在 QWidget 控件中创建用于显示关注商品的 QPushButton 控件。代码如下:

# 显示关注按钮控件
self.pushButton = QtWidgets.QPushButton(self.widget)
# 给显示价格控件命名
self.pushButton.setObjectName(str(n))
# 设置控件位置及大小
self.pushButton.setGeometry(QtCore.QRect(300, 160, 100, 50))
font = QtGui.QFont()     # 创建字体对象
font.setFamily("楷体")   # 设置字体
font.setPointSize(18)    # 设置字体大小
font.setBold(True)      # 开启粗体属性
font.setWeight(75)      # 设置文字粗细
self.pushButton.setFont(font)   # 设置字体
# 设置关注按钮控件样式
self.pushButton.setStyleSheet("background-color: rgb(223, 48, 51);color: rgb(255, 255, 255);")
self.pushButton.setText('关注')   # 设置关注按钮显示的文字
# 注册关注按钮信号槽
self.pushButton.clicked.connect(self.attention_btn)
☀️(9) 将动态创建的布局添加到网格布局

将动态创建的 widget 布局添加到网格布局中,并设置滚动条的高度为动态高度。代码如下:

    # 把动态创建的widegt布局添加到gridLayout中 i,x分别代表:行数以及每行的个数self.gridLayout.addWidget(self.widget, i, x)# 设置高度为动态高度根据 行数确定高度 每行300
self.scrollAreaWidgetContents.setMinimumHeight((i+1) * 240)
# 设置网格布局控件动态高度
self.gridLayoutWidget.setGeometry(QtCore.QRect(0, 0, 850, ((i+1) * 240)))
☀️(10) 在主程序入口调用 show_top10() 方法

最后,在主程序入口显示主窗体时,调用 show_top10() 方法。代码如下:

main.show_top10()

🦋1.3 运行效果

运行 show_window.py 文件后,主窗体会显示热卖商品前10名的图文信息,如图所示。由于热卖商品排行榜数据会自动更新,主窗体每次显示的信息可能会有所变化。
在这里插入图片描述

🔎2.显示关注商品列表

在实现显示关注商品列表时,需要首先实现热卖商品的关注功能。关注按钮需要设置关注事件,单击商品的关注按钮时会弹出一个确认关注的小窗体,以避免误操作。确认关注后,需要将商品信息保存至数据库,并将关注的商品名称显示在关注商品列表中。同时,取消关注功能也需要实现,单击关注商品列表中的商品名称时,会弹出确认取消关注的小窗体进行确认。

🦋2.1 确认关注

  1. 窗体设计

    • 打开Qt Designer工具,设置窗体的最大尺寸与最小尺寸为400x200,并移除默认的状态栏和菜单栏。
    • 在窗体中拖入一个QLineEdit控件用于显示需要关注商品的名称,拖入两个QPushButton控件分别用于确认关注与取消关注。
    • 窗体设计完成后,保存为attention_window.ui文件,使用pyuic工具将其转换为attention_window.py文件。
      在这里插入图片描述
  2. 代码实现

    • attention_window.py文件中,将默认生成的Ui_MainWindow类修改为Attention_MainWindow
    • 打开show_window.py文件,导入关注窗体文件中的UI类,并定义显示提示对话框的方法:
    from attention_window import Attention_MainWindow  # 导入关注窗体文件中的UI类
    attention_info = ''  # 关注商品信息
    def messageDialog(title, message):msg_box = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, title, message)msg_box.exec()
    
  3. 关注按钮事件

    • 在Main类中,创建attention_btn()方法处理关注按钮的事件:
    # 关注按钮事件
    def attention_btn(self):# 获取信号源 点击的按钮sender = self.gridLayout.sender()global attention_info# 因为创建关注按钮对象名称是以0为起始,最后一个关注按钮为9,# 所以用单击按钮的对象名称+1作为数据库中的idattention_info = mysql.query_id_info(cur, int(sender.objectName()) + 1)# 将商品名称显示在关注窗体的编辑框内attention.lineEdit.setText(attention_info[0])attention.open()  # 显示关注窗体
    
  4. 显示关注商品名称列表

    • 创建show_attention_name()方法来显示已关注商品的名称列表:
    def show_attention_name(self):self.name_list = []row, column, results = mysql.query_evaluate_info(cur, 'attention')if row != 0:for index, i in enumerate(results):self.name_list.append('关注商品' + str(index + 1) + ':\n' + i[1])font = QtGui.QFont()font.setPointSize(12)self.listView.setFont(font)self.listView.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)self.listView.setWordWrap(True)model = QtCore.QStringListModel()model.setStringList(self.name_list)self.listView.setModel(model)else:model = QtCore.QStringListModel()model.setStringList(self.name_list)self.listView.setModel(model)
    
  5. 初始化关注窗体

    • 创建Attention类,并通过__init__()方法初始化关注窗体:
    class Attention(QMainWindow, Attention_MainWindow):def __init__(self):super(Attention, self).__init__()self.setupUi(self)# 开启自动填充背景self.centralwidget.setAutoFillBackground(True)palette = QtGui.QPalette()  # 调色板类palette.setBrush(QtGui.QPalette.Background, QtGui.QBrush(QtGui.QPixmap('img_resources/attention_bg.png')))  # 设置背景图片self.centralwidget.setPalette(palette)  # 为控件设置对应的调色板即可# 设置背景透明self.pushButton_yes.setStyleSheet("background-color:rgba(0,0,0,0)")# 设置确认关注按钮的背景图片self.pushButton_yes.setIcon(QtGui.QIcon('img_resources/yes_btn.png'))# 设置按钮背景图大小self.pushButton_yes.setIconSize(QtCore.QSize(100, 50))# 设置背景透明self.pushButton_no.setStyleSheet("background-color:rgba(0,0,0,0)")# 设置确认关注按钮的背景图片self.pushButton_no.setIcon(QtGui.QIcon('img_resources/no_btn.png'))# 设置按钮背景图大小self.pushButton_no.setIconSize(QtCore.QSize(100, 50))
    
  6. 插入关注商品信息到数据库

    • 创建insert_attention_message()方法,将商品信息插入数据库:
        # 打开关注窗体def open(self):self.show()def insert_attention_message(self, attention_info):is_identical = mysql.query_is_name(cur, attention_info[0])  # 判断数据库中是否已经关注了该商品if is_identical == 0:middle_time = mycrawl.get_evaluation(2, attention_info[2])poor_time = mycrawl.get_evaluation(1, attention_info[2])# 判断信息状态if middle_time != None and poor_time != None:attention_info = attention_info + (middle_time, poor_time)  # 将评价时间添加至商品数据中mysql.insert_attention(cur, [attention_info], 'attention')  # 插入关注信息messageDialog('提示!', '已关注' + attention_info[0])  # 提示attention.close()  # 关闭关注对话框main.show_attention_name() # 显示关注商品的名称else:print('无法获取评价时间!')else:messageDialog('警告!', '不可以关注相同的商品!')attention.close()
    
  7. 设置按钮事件

    • 在主程序的主入口处,创建关注窗体对象并设置按钮事件:
    attention = Attention()
    attention.pushButton_yes.clicked.connect(lambda: attention.insert_attention_message(attention_info))
    attention.pushButton_no.clicked.connect(attention.close)
    main.show_attention_name()
    
  8. 注册关注按钮信号槽

    • show_top10()方法中,注册关注按钮的信号槽:
    self.pushButton.clicked.connect(self.attention_btn)
    
  9. 运行并测试

    • 运行show_window.py文件,单击商品的“关注”按钮后,将弹出确认关注窗体,确认后会显示提示框并更新关注商品列表。

在这里插入图片描述
在这里插入图片描述

🦋2.2 取消关注

取消关注的小窗体与确认关注的小窗体相似,唯一不同的是背景图片和文字。以下是实现步骤:

class Cancel_Attention(QMainWindow, Attention_MainWindow):def __init__(self):super(Cancel_Attention, self).__init__()self.setupUi(self)# 开启自动填充背景self.centralwidget.setAutoFillBackground(True)palette = QtGui.QPalette()  # 调色板类palette.setBrush(QtGui.QPalette.Background, QtGui.QBrush(QtGui.QPixmap('img_resources/cancel_attention_bg.png')))  # 设置背景图片self.centralwidget.setPalette(palette)  # 为控件设置对应的调色板即可# 设置背景透明self.pushButton_yes.setStyleSheet("background-color:rgba(0,0,0,0)")# 设置确认关注按钮的背景图片self.pushButton_yes.setIcon(QtGui.QIcon('img_resources/yes_btn.png'))# 设置按钮背景图大小self.pushButton_yes.setIconSize(QtCore.QSize(100, 50))# 设置背景透明self.pushButton_no.setStyleSheet("background-color:rgba(0,0,0,0)")# 设置确认关注按钮的背景图片self.pushButton_no.setIcon(QtGui.QIcon('img_resources/no_btn.png'))# 设置按钮背景图大小self.pushButton_no.setIconSize(QtCore.QSize(100, 50))# 显示取消关注的窗体def open(self,qModeIndex):# 在关注商品名称列表中,获取单击了哪一个商品的名称name = main.name_list[qModeIndex.row()].lstrip('关注商品'+str(qModeIndex.row()+1)+':\n')# 将商品名称显示在关注窗体的编辑框内cancel_attention.lineEdit.setText(name)cancel_attention.show()  # 显示关注窗体#  取消关注的方法def unfollow(self):# 获取编辑框内的商品名称name = cancel_attention.lineEdit.text()mysql.delete_attention(cur,name)main.show_attention_name()     # 显示关注商品名称列表cancel_attention.close()       # 关掉取消关注的窗体

程序启动文件如下:

cancel_attention = Cancel_Attention()
# 指定显示关注商品名称列表事件
main.listView.clicked.connect(cancel_attention.open)
# 指定取消关注窗体按钮(是)单击事件处理方法
cancel_attention.pushButton_yes.clicked.connect(cancel_attention.unfollow)
# 指定取消关注窗体按钮(否)单击事件处理方法
cancel_attention.pushButton_no.clicked.connect(cancel_attention.close)

这样,整个关注与取消关注功能就完成了。
在这里插入图片描述
在这里插入图片描述

🔎3.显示商品分类比例饼图

在实现显示商品分类比例饼图时,首先需要创建一个图表文件,接着在该文件中创建用于显示饼图的方法。然后,将计算出的商品分类比例作为参数传递给该方法,最终将饼图显示在主窗体中。具体步骤如下:

🦋3.1 创建 chart.py 文件

首先,在项目文件夹中创建 chart.py 文件,并导入图表相关的模块。接着,创建 PlotCanvas 类,并在该类中通过 __init__() 方法进行初始化工作。代码如下:

# 图形画布
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib  # 导入图表模块
import matplotlib.pyplot as plt  # 导入绘图模块class PlotCanvas(FigureCanvas):def __init__(self, parent=None, width=0, height=0, dpi=100):# 避免中文乱码matplotlib.rcParams['font.sans-serif'] = ['SimHei']matplotlib.rcParams['axes.unicode_minus'] = Falsefig = plt.figure(figsize=(width, height), dpi=dpi)  # 创建图形FigureCanvas.__init__(self, fig)self.setParent(parent)  # 设置父类

🦋3.2 创建 pie_chart() 方法显示饼图

PlotCanvas 类中,创建 pie_chart() 方法,用于显示商品分类的饼图。代码如下:

# 显示商品分类饼图
def pie_chart(self, size):# 绘制饼图explode = (0.1, 0, 0, 0, 0)  # 设置各部分突出label_list = ['鼠标', '键盘', 'U盘', '移动硬盘', '其他']  # 各部分标签plt.pie(size, labels=label_list, labeldistance=1.1, autopct="%1.1f%%", shadow=False, startangle=30, pctdistance=0.6)plt.axis("equal")  # 设置横轴和纵轴大小相等,这样饼才是圆的

🦋3.3 在 show_window.py 中导入自定义饼图类

show_window.py 文件中导入 PlotCanvas 类,并在 Main 类中创建 show_classification() 方法。该方法的功能是获取商品排名和数量,并统计商品分类比例。代码如下:

# 导入自定义饼图类
from chart import PlotCanvas# 显示商品分类比例饼图
def show_classification(self):name_all = mysql.query_rankings_name(cur, 'jd_ranking')  # 获取排行榜中所有商品名称name_number = len(name_all)  # 获取商品总数量number = 0  # 定义统计分类数量的变量remove_list = []  # 保存需要移除的商品名称class_list = []  # 保存所有分类比例数据的列表

🦋3.4 排除重复商品名称并计算分类比例

为避免统计重复的商品名称(如“鼠标垫”和“鼠标”相似),首先移除这些商品,然后计算不同分类的占比。代码如下:

# 因为鼠标垫与鼠标名称接近,所以先移除鼠标垫
for name in name_all:if '鼠标垫' in name:remove_list.append(name)# 循环移除鼠标垫相关商品
for r_name in remove_list:name_all.remove(r_name)# 获取鼠标分类占有比例
for name in name_all:if '鼠标' in name:number += 1
mouse_ratio = float('%.1f' % ((number / name_number) * 100))  # 计算鼠标百分比
class_list.append(mouse_ratio)  # 向分类比例列表添加鼠标百分比数据

🦋3.5 计算其他商品分类的占比

依次计算键盘、U盘、移动硬盘和其他类别的占比。代码如下:

# 获取键盘占有比例
number = 0
for name in name_all:if '键盘' in name:number += 1
keyboard_ratio = float("%.1f" % ((number / name_number) * 100))
class_list.append(keyboard_ratio)# 获取U盘占有比例
number = 0
for name in name_all:if 'U盘' in name or 'u盘' in name:number += 1
u_ratio = float('%.1f' % ((number / name_number) * 100))
class_list.append(u_ratio)# 获取移动硬盘占有比例
number = 0
for name in name_all:if '移动硬盘' in name:number += 1
move_ratio = float('%.1f' % ((number / name_number) * 100))
class_list.append(move_ratio)# 计算其他百分比
other_ratio = float('%.1f' % (100 - (mouse_ratio + keyboard_ratio + u_ratio + move_ratio)))
class_list.append(other_ratio)

🦋3.6 创建饼图并显示

创建 PlotCanvas 类对象,并调用 pie_chart() 方法将饼图添加到主窗体的布局中。代码如下:

# 创建饼图类对象
pie = PlotCanvas()# 调用显示饼图的方法
pie.pie_chart(class_list)# 将饼图添加到主窗体的水平布局中
self.horizontalLayout.addWidget(pie)

🦋3.7 调用 show_classification() 方法显示饼图

在主程序入口中,调用 show_classification() 方法来显示商品分类比例饼图。代码如下:

# 显示商品分类比例饼图
main.show_classification()

🦋3.8 运行并显示饼图

运行 show_window.py 文件时,主窗体的左上角将显示商品分类比例的饼图。

在这里插入图片描述

相关文章:

【愚公系列】《Python网络爬虫从入门到精通》063-项目实战电商数据侦探(主窗体的数据展示)

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! &#x1f…...

DAPP(去中心化应用程序)开发全解析:构建去中心化应用的流程

去中心化应用(DApp)凭借其透明性、抗审查性和用户数据主权,正重塑金融、游戏、社交等领域。本文基于2025年最新开发实践,系统梳理DApp从需求规划到部署运维的全流程,并融入经济模型设计、安全加固等核心要点&#xff0…...

Spark与Hadoop之间有什么样的对比和联系

一、什么是Spark Spark 是一个快速、通用且可扩展的大数据处理框架,最初由加州大学伯克利分校的AMPLab于2009年开发,并于2010年开源。它在2013年成为Apache软件基金会的顶级项目,是大数据领域的重要工具之一。 Spark 的优势在于其速度和灵活…...

spark和Hadoop之间的对比和联系

Spark 诞生主要是为了解决 Hadoop MapReduce 在迭代计算以及交互式数据处理时面临的性能瓶颈问题。 一,spark的框架 Hadoop MR 框架 从数据源获取数据,经过分析计算后,将结果输出到指定位置,核心是一次计算,不适合迭…...

LeetCode 第 262 题全解析:从 SQL 到 Swift 的数据分析实战

文章目录 摘要描述题解答案(SQL)Swift 题解代码分析代码示例(可运行 Demo)示例测试及结果时间复杂度分析空间复杂度分析总结未来展望 摘要 在实际业务中,打车平台要监控行程的取消率,及时识别服务质量的问…...

“融合Python与机器学习的多光谱遥感技术:数据处理、智能分类及跨领域应用”​

随着遥感技术的快速发展,多光谱数据凭借其多波段信息获取能力,成为地质、农业及环境监测等领域的重要工具。相较于高光谱数据,Landsat、哨兵-2号等免费中分辨率卫星数据具有长时间序列、广覆盖的优势,而无人机平台的兴起进一步补充…...

JavaScript的JSON处理Map的弊端

直接使用 Map 会遇到的问题及解决方案 直接使用 Map 会导致数据丢失,因为 JSON.stringify 无法序列化 Map。以下是详细分析及解决方法: 问题复现 // 示例代码 const myMap new Map(); myMap.set(user1, { name: Alice }); myMap.set(user2, { name: B…...

python的深拷贝浅拷贝(copy /deepcopy )

先说结论: 浅拷贝: 浅拷贝对在第一层的操作都是新建,不改变原对象。 浅拷贝对于原拷贝对象中的嵌套的可变对象是引用,对原拷贝对象中的嵌套的不可变对象是新建。 对新建的对象操作不会影响原被拷贝对象。 对引用对象操作会影…...

新能源汽车充电桩:多元化运营模式助力低碳出行

摘 要:以新能源汽车民用充电桩为研究对象,在分析充电桩建设运营的政府推动模式、电网企业推动模式、汽车厂商推动模式等三种模式利弊的基础上,结合我国的实际情况,提出我国现阶段应实行汽车厂商与电网企业联盟建设充电桩的模式。建立一个考虑…...

Python 设计模式:享元模式

1. 什么是享元模式? 享元模式是一种结构型设计模式,旨在通过共享对象来减少内存使用和提高性能。它特别适用于需要大量相似对象的场景,通过共享相同的对象来避免重复创建,从而节省内存和提高效率。 享元模式的核心思想是将对象的…...

文献×汽车 | 基于 ANSYS 的多级抛物线板簧系统分析

板簧系统是用于减弱或吸收动态系统中发生的应力、应变、偏转和变形等破坏性因素的机械结构。板簧系统可能对外力产生不同的响应,具体取决于其几何结构和材料特性。板簧系统的计算机辅助分析对于高精度确定系统的变形特性和结构特性至关重要。 在这项工作中&#xff…...

Element UI、Element Plus 里的表单验证的required必填的属性不能动态响应?

一 问题背景 想要实现: 新增/修改对话框中(同一个),修改时“备注”字段非必填,新增时"备注"字段必填 结果发现直接写不生效-初始化一次性 edit: [{ required: true, message: "请输入备注", trigger: "blur" }…...

【架构】ANSI/IEEE 1471-2000标准深度解析:软件密集型系统架构描述推荐实践

引言 在软件工程领域,架构设计是确保系统成功的关键因素之一。随着软件系统日益复杂化,如何有效描述和沟通系统架构成为了一个亟待解决的问题。ANSI/IEEE 1471-2000(正式名称为"推荐软件密集型系统架构描述实践")应运而…...

深度学习中的“重参数化”总结

深度学习中的重参数化(Reparameterization)是一种数学技巧,主要用于解决模型训练过程中随机性操作(如采样)导致的梯度不可导问题。其核心思想是将随机变量的生成过程分解为确定性和随机性两部分,使得反向传…...

为TA开发人员介绍具有最新改进的Kinibi-610a

安全之安全(security)博客目录导读 目录 一、引言 二、密码学改进 三、可信应用(TA)的多线程支持 四、C 标准库支持 五、简化的支持与集成 六、参考资料 一、引言 Trustonic 推出的 Kinibi-610a 进行了多项底层优化,以实现更深度的系统集成,并更好地适应不断演进的…...

通信与推理的协同冲突与架构解耦路径

在大规模无人机集群中,AI决策系统依赖实时通信完成状态共享与策略传播,但通信带宽、延迟、信息一致性等问题正在成为系统性能的瓶颈。尤其是在山区、城市低空或信号遮蔽等通信不稳定区域,AI推理系统往往面临状态更新延迟,难以及时…...

《AI大模型应知应会100篇》第32篇:大模型与医疗健康:辅助诊断的可能性与风险

第32篇:大模型与医疗健康:辅助诊断的可能性与风险 摘要 当AI开始读懂CT影像中的细微阴影,当算法能从百万份病历中发现诊断规律,医疗健康领域正经历着一场静默的革命。本文通过技术解构与案例分析,揭示大模型如何重塑临…...

c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第七式】程序的编译

c语言修炼秘籍 - - 禁(进)忌(阶)秘(技)术(巧)【第七式】程序的编译 【心法】 【第零章】c语言概述 【第一章】分支与循环语句 【第二章】函数 【第三章】数组 【第四章】操作符 【第五章】指针 【第六章】结构体 【第七章】const与c语言中一些错误代码 【禁忌秘术】 【第一式】…...

[创业之路-377]:企业法务 - 有限责任公司与股份有限公司的优缺点对比

有限责任公司(简称“有限公司”)与股份有限公司(简称“股份公司”)是我国《公司法》规定的两种主要公司形式,二者在设立条件、治理结构、股东权利义务等方面存在显著差异。以下从核心特征、设立条件、治理结构、股东权…...

PowerBi中REMOVEFILTERS怎么使用?

在 Power BI 的 DAX 中,REMOVEFILTERS() 是一个非常重要的函数,常用于取消某个字段或表的筛选上下文(Filter Context),从而让你的计算不受切片器(Slicer)、筛选器或视觉对象的限制。 ✅ 一、REM…...

stat判断路径

int stat(const char *pathname, struct stat *buf); pathname:用于指定一个需要查看属性的文件路径。 buf:struct stat 类型指针,用于指向一个 struct stat 结构体变量。调用 stat 函数的时候需要传入一个 struct stat 变量的指针&#xff0…...

智能指针之设计模式4

前面的文章介绍了使用工厂模式来封装智能指针对象的创建过程&#xff0c;下面介绍一下工厂类 enable_shared_from_this的实现方案。 4、模板方法模式 在前面的文章分析过&#xff0c;enable_shared_from_this<T>类是一个工厂基类&#xff0c;提供的工厂方法是shared_f…...

Linux信号的产生

Linux系列 文章目录 Linux系列一、信号的产生1.1 异常1.2 alarm()系统调用 二 、信号的默认行为 一、信号的产生 上篇文章我们已经介绍了信号的三种产生方式&#xff0c;这部分是对上篇文章的补充 1.1 异常 在编写程序时&#xff0c;我们的程序经常会出现如&#xff1a;除零…...

FPGA设计 时空变换

1、时空变换基本概念 1.1、时空概念简介 时钟速度决定完成任务需要的时间&#xff0c;规模的大小决定完成任务所需要的空间&#xff08;资源&#xff09;&#xff0c;因此速度和规模就是FPGA中时间和空间的体现。 如果要提高FPGA的时钟&#xff0c;每个clk内组合逻辑所能做的事…...

客户端本地搭建

connect函数 主要用于客户端套接字向服务器发起连接请求。 头文件 #include <sys/socket.h> #include <arpa/inet.h> 函数原型 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);参数解释 sockfd&#xff1a;客户端文件描述符。 addr…...

广东食品销售初级考试主要考什么

广东省食品销售初级考试主要考察从业人员对食品安全法律法规、行业规范及基础操作技能的掌握程度&#xff0c;内容涵盖以下几个方面&#xff1a; 1. 食品安全法律法规 考试重点包括《食品安全法》《广东省食品安全条例》等核心法规&#xff0c;要求考生熟悉食品经营许可、从业…...

[盈达科技】GEO(生成式引擎优化)实战指南:从认知重构、技术落地到内容突围的三维战略

GEO&#xff08;生成式引擎优化&#xff09;实战指南&#xff1a;从认知重构、技术落地到内容突围的三维战略 引言&#xff1a;AI搜索重构规则&#xff0c;GEO成为企业新护城河 在生成式AI主导的搜索时代&#xff0c;传统SEO的“关键词游戏”已失效。Google数据显示&#xff0…...

Linux ACL访问控制权限解析:超越传统权限的精细化管理

Linux ACL权限管理示意图 标准输出&#xff1a;Linux文件权限结构&#xff08;支持ACL&#xff09; ├── 传统权限 │ ├── 所有者(user): rwx │ ├── 所属组(group): r-x │ └── 其他用户(other): r-- │ └── ACL扩展权限├── 用户条目│ ├── user…...

全面介绍AVFilter 的添加和使用

author: hjjdebug date: 2025年 04月 22日 星期二 13:48:19 CST description: 全面介绍AVFilter 的添加和使用 文章目录 1.两个重要的编码思想1. 写代码不再是我们调用别人&#xff0c;而是别人调用我们!2. 面向对象的编程方法. 2. AVFilter 开发流程2.1 编写AVFilter 文件2.1.…...

复刻低成本机械臂 SO-ARM100 3D 打印篇

视频讲解&#xff1a; 复刻低成本机械臂 SO-ARM100 3D 打印篇 清理了下许久不用的3D打印机&#xff0c;挤出机也裂了&#xff0c;更换了喷嘴和挤出机夹具&#xff0c;终于恢复了正常工作的状态&#xff0c;接下来还是要用起来&#xff0c;不然吃灰生锈了&#xff0c;于是乎想起…...

基于微信小程序的走失儿童帮助系统-项目分享

基于微信小程序的走失儿童帮助系统-项目分享 项目介绍项目摘要管理员功能图用户功能图系统功能图项目预览首页走失儿童个人中心走失儿童管理 最后 项目介绍 使用者&#xff1a;管理员、用户 开发技术&#xff1a;MySQLJavaSpringBootVue 项目摘要 本系统采用微信小程序进行开…...

C++23 中 static_assert 和 if constexpr 的窄化布尔转换

文章目录 背景与动机C23 的改进限制与例外总结 C23 引入了一项重要的语言特性变更&#xff0c;即在 static_assert 和 if constexpr 中允许窄化按语境转换为 bool。这一特性由 Andrzej Krzemieński 提出的 P1401R5 论文推动&#xff0c;旨在使编译器的行为与标准保持一致&a…...

服务网格在DevOps中的落地:如何让微服务更智能、更稳定?

服务网格在DevOps中的落地:如何让微服务更智能、更稳定? 近年来,DevOps在企业IT架构中变得至关重要,而微服务架构的广泛应用更是加速了这一趋势。然而,随着微服务数量不断增长,我们发现自己掉入了一个运维“泥潭”: 服务之间的流量调控变得复杂可观测性不足,出现问题时…...

el-table表格既出现横向滚动条,又出现纵向滚动条?

横向滚动条 自然出现&#xff1f; 当表格所有列的宽度总和超过表格容器宽度时&#xff0c;el-table会默认出现横向滚动条。 比如&#xff0c;给每个<el-table-column>设置固定宽度&#xff0c;且他们相加超过了<el-table>宽度 就会触发 强制出现&#xff1f; 设…...

STL常用算法——C++

1.概述 2.常用遍历算法 1.简介 2.for_each 方式一&#xff1a;传入普通函数&#xff08;printf1&#xff09; #include<stdio.h> using namespace std; #include<string> #include<vector> #include<functional> #include<algorithm> #include…...

基于国产 FPGA+ 龙芯2K1000处理器+翼辉国产操作系统继电保护装置测试装备解决方案

0 引言 近年来&#xff0c;我国自主可控芯片在国家政策和政 府的支持下发展迅速&#xff0c;并在电力、军工、机械、 通信、电子、医疗等领域掀起了国产化替代之 风&#xff0c;但在芯片自主可控和国产化替代方面还有明 显的不足之处。 2022年我国集成电路进口量多 达 5 3…...

1.3 本书结构概览:从理论基础到实践案例的系统阐述

本书采用由浅入深、理论联系实践的结构设计&#xff0c;旨在为读者提供一个关于大模型与智能代理(Agent)技术的全面认知框架与实施路径。全书共分为十章&#xff0c;系统性地覆盖了从技术基础到企业落地的完整知识链条&#xff0c;现概述如下&#xff1a; 首先&#xff0c;第一…...

【FPGA开发】Vivado开发中的LUTRAM占用LUT资源吗

LUTRAM在Vivado资源报告中的解释 LUTRAM的本质与实现原理&#xff1a; LUTRAM不是一种独立的物理资源&#xff0c;而是LUT&#xff08;Look-Up Table&#xff09;的一种特殊使用方式。在Xilinx FPGA架构中&#xff0c;部分LUT单元可以被配置为小型分布式RAM&#xff08;也称为…...

【动手学强化学习】番外8-IPPO应用框架学习与复现

文章目录 一、待解决问题1.1 问题描述1.2 解决方法 二、方法详述2.1 必要说明&#xff08;1&#xff09;MAPPO 与 IPPO 算法的区别在于什么地方&#xff1f;&#xff08;2&#xff09;IPPO 算法应用框架主要参考来源 2.2 应用步骤2.2.1 搭建基础环境2.2.2 IPPO 算法实例复现&am…...

C++ 的 输入输出流(I/O Streams)

什么是输入输出流 C 的输入输出操作是通过 流&#xff08;stream&#xff09; 机制实现的。 流——就是数据的流动通道&#xff0c;比如&#xff1a; 输入流&#xff1a;从设备&#xff08;如键盘、文件&#xff09;读取数据 → 程序 输出流&#xff1a;程序将数据写入设备&…...

Java 安全:如何防止 SQL 注入与 XSS 攻击?

Java 安全&#xff1a;如何防止 SQL 注入与 XSS 攻击&#xff1f; 在 Java 开发领域&#xff0c;安全问题至关重要&#xff0c;而 SQL 注入和 XSS 攻击是两种常见的安全威胁。本文将深入探讨如何有效防止这两种攻击&#xff0c;通过详细代码实例为您呈现解决方案。 一、SQL 注…...

leetcode day36 01背包问题 494

494 目标和 给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 或 - &#xff0c;然后串联起所有整数&#xff0c;可以构造一个 表达式 &#xff1a; 例如&#xff0c;nums [2, 1] &#xff0c;可以在 2 之前添加 &#xff0c;在 1 之前添加 - &…...

31Calico网络插件的简单使用

环境准备&#xff1a; 1、删除Flannel 2、集群所有node节点拉取所需镜像&#xff08;具体版本可以依据calico.yaml文件中&#xff09;&#xff1a; docker pull calico/cni:v3.25.0 docker pull calico/node:v3.25.0 docker pull calico/kube-controllers:v3.25.0一、安装Cali…...

进阶篇 第 5 篇:现代预测方法 - Prophet 与机器学习特征工程

进阶篇 第 5 篇&#xff1a;现代预测方法 - Prophet 与机器学习特征工程 (图片来源: ThisIsEngineering RAEng on Pexels) 在前几篇中&#xff0c;我们深入研究了经典的时间序列统计模型&#xff0c;如 ETS 和强大的 SARIMA 家族。它们在理论上成熟且应用广泛&#xff0c;但有…...

实用生活c语言脚本

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <time.h> // 清理临时文件目录 void clean_temp_directory() { const char* temp_dir "/tmp"; // 可自定义需要清理的目录 char command[1024]; …...

从零开始构建微博爬虫与数据分析系统

从零开始构建微博爬虫与数据分析系统 引言 社交媒体平台蕴含着海量的信息和数据&#xff0c;通过对这些数据的收集和分析&#xff0c;我们可以挖掘出有价值的见解。本文将详细介绍如何构建一个完整的微博爬虫和数据分析系统&#xff0c;从数据爬取、清洗、到多维度分析与可视…...

417. 太平洋大西洋水流问题

题目 有一个 m n 的矩形岛屿&#xff0c;与 太平洋 和 大西洋 相邻。 “太平洋” 处于大陆的左边界和上边界&#xff0c;而 “大西洋” 处于大陆的右边界和下边界。 这个岛被分割成一个由若干方形单元格组成的网格。给定一个 m x n 的整数矩阵 heights &#xff0c; heights…...

chili3d调试笔记8 打印零件属性

无效&#xff0c; 返回的是节点不是坐标啥的&#xff0c; 找他的属性 把document和selectednote&#xff08;空集&#xff09;传给handleshowproperty方法 怎么获得selectnotes和selectnotes的property值 有selectnotes运行这段就行了 明天再搞...

uniapp Vue2升级到Vue3,并发布到微信小程序的快捷方法

目录 前言&#xff1a;升级项目的两种方式步骤一、新建项目 【选择-默认模版】二、修改-pages.json三、补充-缺少的文件四、修改-Main.js按照 [官方文档-vue2升级vue3迁移指南](https://uniapp.dcloud.net.cn/tutorial/migration-to-vue3.html) 修改 五、升级-uni-ui扩展组件的…...

火山RTC 5 转推CDN 布局合成规则

实时音视频房间&#xff0c;转推CDN&#xff0c;文档&#xff1a; 转推直播--实时音视频-火山引擎 一、转推CDN 0、前提 * 在调用该接口前&#xff0c;你需要在[控制台](https://console.volcengine.com/rtc/workplaceRTC)开启转推直播功能。<br> * 调…...