【Python高级应用课程设计】——腾讯课堂爬虫数据可视化

发布时间 2023-12-30 15:32:51作者: 陈圳平

一、选题背景
随着互联网的快速发展,在线教育已经成为越来越多人获取知识和技能的重要途径。其中,腾讯课堂作为国内知名的在线教育平台之一,提供了丰富的课程资源和学习机会。然而,对于广大学习者来说,如何快速有效地获取和筛选这些课程信息是一个重要的问题。此外,对于教育机构和课程提供者,如何对课程数据进行深入分析,以了解用户需求和行为模式,进而优化课程内容和推广策略,也是一个值得探讨的问题。
基于上述背景,本课题旨在使用PyQt5库编写一个Python GUI应用程序,以爬取腾讯课堂上的课程信息,并在此基础上提供一些相关的功能,如显示时间、生成词云图、生成可视化统计图等。通过这个应用程序,用户可以方便地获取和筛选腾讯课堂上的课程信息,同时教育机构和课程提供者也可以利用该程序对课程数据进行深入分析,以优化课程内容和推广策略。
二、设计分析
1.数据来源
本文档的数据来源链接:https://ke.qq.com/course/list
2.项目运行过程

可通过输入关键词,查找所需查找的课程

通过综合、好评率、人气、价格进行爬取数据



爬出的数据可生成词云图

对数据进行生成可视化统计图

可通过输入课程名称打开视频链接


3.完整代码

1. from PyQt5.QtWidgets import QApplication, QHeaderView, QTableWidgetItem, QButtonGroup, QRadioButton
2. from PyQt5 import uic
3. from PyQt5.QtCore import QTime, QTimer
4. from PyQt5.QtGui import QPalette, QBrush, QPixmap, QColor
5. from urllib import request, parse
6. from lxml import etree
7. import re
8. from time import sleep
9. from random import random
10. import openpyxl
11. import os
12. import webbrowser
13. from pyecharts.charts import Line, Bar
14. from pyecharts.options import AxisOpts, LabelOpts, TitleOpts, LegendOpts, ToolboxOpts, VisualMapOpts
15. import wordcloud


18. class CourseTool:
19.     def __init__(self):
20.         # 动态加载ui文件
21.         self.ui = uic.loadUi('tencent_course.ui')
22.         self.url = "https://ke.qq.com/course/list/{}"
23.         # 模拟用户访问浏览器headers
24.         self.headers = {
25.             'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 SLBrowser/9.0.0.10191 SLBChan/105',
26.             'cookie': 'RK=Fv9MC/qwYK; ptcz=96beef5a24642338700a2cd8bdde3b00ad696ebb7d2160740e53ebdd928f2fc2; pgv_pvid=8304149714; tvfe_boss_uuid=6175bf55bb40affd; logTrackKey=b4d44ec94d2141919dda8efdefcbdf4e; LW_sid=21R6t841O9W1A7V3Z1k3W9K0J3; LW_uid=V1s6e851c9M1d7F3x1A3M9t036; eas_sid=41k6r8m1z9u1q7o3c1V3K9s1i9; ts_uid=4471845940; Hm_lvt_0c196c536f609d373a16d246a117fd44=1681969609; fqm_pvqid=868386a8-1fce-4cb7-8e52-25995454a5b1; qq_domain_video_guid_verify=5d1032a41bff629b; _qimei_uuid42=17c05141b0f100f4e40cb2520a73dc0fbbb229f0bf; _qimei_fingerprint=8030ec9908440546fcb0126c751fa21e; _qimei_q36=; _qimei_h38=2db8a824e40cb2520a73dc0f02000004a17c05; ptui_loginuin=1652058273; pac_uid=0_a80bbd2346dce; iip=0; tdw_data_new_2={"auin":"-","sourcetype":"","sourcefrom":"","ver9":"","uin":"","visitor_id":"5977218902822812","ver10":"","url_page":"","url_module":"","url_position":""}; tdw_data_testid=; tdw_data_flowid=',
27.             'upgrade-insecure-requests': '1',
28.             'sec-ch-ua': '"Chromium";v="9", "Not?A_Brand";v="8"',
29.             'sec-ch-ua-mobile': '?0',
30.             'sec-ch-ua-platform': '"Windows"',
31.             'sec-fetch-dest': 'document',
32.             'sec-fetch-mode': 'navigate',
33.             'sec-fetch-site': 'same-origin',
34.             'sec-fetch-user': '?1'
35.         }

37.         # 为窗口加上北京
38.         self.palette = QPalette()
39.         self.palette.setBrush(QPalette.Background, QBrush(QPixmap("000.jpg").scaled(self.ui.width(), self.ui.height())))
40.         self.ui.setPalette(self.palette)

42.         # 设置表格控件的颜色
43.         table_palette = self.ui.course_table.palette()
44.         table_palette.setColor(QPalette.Base, QColor(205, 192, 176))
45.         self.ui.course_table.setPalette(table_palette)

47.         # 设置表格控件的样式
48.         self.ui.course_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)

50.         # 时间小组件
51.         self.timer = QTimer()
52.         self.timer.timeout.connect(self.show_time)
53.         # 每一秒刷新一次
54.         self.timer.start(1000)

56.         # 把按钮和功能函数绑定一起
57.         self.ui.courseButton.clicked.connect(self.course)
58.         self.ui.photobutton1.clicked.connect(self.wordcloud_photo)
59.         self.ui.photobutton2.clicked.connect(self.open_photo)
60.         self.ui.echartsbutton1.clicked.connect(self.pyecharts_photo)
61.         self.ui.echartsbutton2.clicked.connect(self.open_charts)
62.         self.ui.course_button.clicked.connect(self.open_course)

64.     def show_time(self):
65.         # 时间函数
66.         current_time = QTime.currentTime()
67.         label_time = current_time.toString('hh:mm:ss')
68.         self.ui.time_label.setText(label_time)

70.     def course(self):
71.         # 爬取课程功能函数
72.         keyword = self.ui.keyEdit.text()
73.         sorted_type = self.ui.sortBox.currentText()
74.         print(keyword, sorted_type)
75.         all_course = self.spider_course(keyword, sorted_type)
76.         print('课程爬取成功')

78.         # 生成workbook对象,保存数据为xlsx文件
79.         course_xlsx = openpyxl.Workbook()
80.         sheet = course_xlsx.active
81.         sheet.append(['课程名称', '价格', '课程时长', '报名人数', '课程标签', '课程网址'])
82.         for one_course in all_course:
83.             sheet.append(one_course)
84.         course_xlsx.save('course_data.xlsx')
85.         print('已保存表格文件')

87.         # 清空表格里的数据,防止上个类型的课程影响
88.         self.ui.course_table.clearContents()
89.         # 写入刚爬取的课程
90.         for r in range(len(all_course)):
91.             self.ui.course_table.insertRow(r)
92.         for r in range(len(all_course)):
93.             for c in range(len(all_course[0])):
94.                 item = QTableWidgetItem(str(all_course[r][c]))
95.                 self.ui.course_table.setItem(r, c, item)

97.     def spider_course(self, key, sort_type):
98.         # 根据条件调用爬取课程函数
99.         sort_dict = {'好评率': '?sort=5',
100.                      '人气': '?sort=7',
101.                      '价格(升序)': '?sort=2',
102.                      '价格(降序)': '?sort=102'
103.                      }
104.         search_url = ""
105.         if sort_type == "综合":
106.             search_url = self.url.format(parse.quote(key))
107.         elif sort_type == "好评率":
108.             search_url = self.url.format(parse.quote(key)) + sort_dict[sort_type]
109.         elif sort_type == "人气":
110.             search_url = self.url.format(parse.quote(key)) + sort_dict[sort_type]
111.         elif sort_type == "价格(升序)":
112.             search_url = self.url.format(parse.quote(key)) + sort_dict[sort_type]
113.         elif sort_type == "价格(降序)":
114.             search_url = self.url.format(parse.quote(key)) + sort_dict[sort_type]
115.         all_course = []
116.         all_course, total = self.parse_data(search_url, all_course)
117.         pg = 1
118.         # 用判断循环结构把所有数据都爬完全
119.         if total <= 24:
120.             pass
121.         elif total % 24 != 0:
122.             pg = total // 24 + 1
123.         elif total % 24 == 0:
124.             pg = total // 24
125.         if pg == 1:
126.             pass
127.         else:
128.             for page in range(2, pg + 1):
129.                 if sort_type == "综合":
130.                     search_url1 = search_url + f'?page={page}'
131.                 else:
132.                     search_url1 = search_url + f'&page={page}'
133.                 all_course, total = self.parse_data(search_url1, all_course)
134.         return all_course

136.     def parse_data(self, search_url, all_course):
137.         # 爬取课程函数
138.         response = request.Request(url=search_url, headers=self.headers)
139.         response = request.urlopen(response)
140.         html = response.read().decode('utf-8')
141.         sleep(random())
142.         html = etree.HTML(html)
143.         total_num = html.xpath('//em[@class="result__count"]/text()')[0]
144.         total_num = int(re.findall(r'\d+', total_num)[0])
145.         course_list = html.xpath('//div[@class="course-list"]/div')
146.         for course in course_list:
147.             one_list = []
148.             title_list = course.xpath('.//h3[@class="kc-course-card-name"]//text()')
149.             title = "".join(title_list)
150.             one_list.append(title)
151.             price = course.xpath('.//span[@class="kc-course-card-price"]//text()')
152.             price = "".join(price)
153.             one_list.append(price)
154.             course_num = course.xpath('.//div[@class="kc-course-card-cover-course-num---tapHtg"]/text()')[0]
155.             one_list.append(course_num)
156.             people = course.xpath('.//span[@class="kc-course-card-student-apply-num---KvJiqW"]/text()')[0]
157.             one_list.append(people)
158.             tag_list = course.xpath('.//span[@class="kc-course-card-labels-item---euyKYQ"]/text()')
159.             tags = ','.join(tag_list)
160.             one_list.append(tags)
161.             course_url = course.xpath('.//a[@data-report-module="middle-course"]/@href')[0]
162.             course_url = 'https://ke.qq.com' + course_url
163.             one_list.append(course_url)
164.             print(one_list)
165.             all_course.append([title, price, course_num, people, tags, course_url])
166.         return all_course, total_num

168.     def wordcloud_photo(self):
169.         # 生成词云图
170.         course_xlsx = openpyxl.load_workbook('course_data.xlsx')
171.         sheet = course_xlsx.active
172.         all_data = []
173.         # 从2开始循环,因为要跳过表头
174.         for row in range(2, sheet.max_row + 1):
175.             one_row_data = []
176.             for column in range(1, sheet.max_column + 1):
177.                 one_row_data.append(sheet.cell(row=row, column=column).value)
178.             all_data.append(one_row_data)

180.         # 获取QGroupBox对象的选择文本
181.         button_group = QButtonGroup()
182.         for button in self.ui.groupBox.findChildren(QRadioButton):
183.             button_group.addButton(button)
184.         selected_button = button_group.checkedButton()
185.         selected_radio = ""
186.         if selected_button:
187.             selected_radio = selected_button.text()
188.             print(selected_radio)
189.         # 根据选择文本筛选数据
190.         radio_dict = {'课程名称': 0, '课程标签': 4}
191.         cloud_text = [x[radio_dict[selected_radio]] for x in all_data]
192.         # 创建词云图对象,设置字体颜色,字体,背景颜色,图片大小
193.         cloud = wordcloud.WordCloud(width=2000, height=2000, background_color='white',
194.                                     font_path='C:/Windows/Fonts/simsun.ttc', colormap="cool")
195.         # 从文本生成词云
196.         cloud.generate(" ".join(cloud_text))
197.         cloud.to_file('course_cloud.png')
198.         print('词云图已生成')

200.     def open_photo(self):
201.         # 打开词云图函数
202.         # os库打开本地文件,用startfile函数
203.         os.startfile('course_cloud.png')
204.         print('词云图已打开')

206.     def pyecharts_photo(self):
207.         # 生成可视化统计图
208.         course_xlsx = openpyxl.load_workbook('course_data.xlsx')
209.         sheet = course_xlsx.active
210.         all_data = []
211.         for row in range(2, sheet.max_row + 1):
212.             one_row_data = []
213.             for column in range(1, sheet.max_column + 1):
214.                 one_row_data.append(sheet.cell(row=row, column=column).value)
215.             all_data.append(one_row_data)

217.         title_data = [x[0] for x in all_data]
218.         echarts_select = self.ui.echarts_box.currentText()
219.         if echarts_select == "课程时长":
220.             time_data = [x[2] for x in all_data]
221.             # map算子处理列表
222.             time_data = list(map(lambda x: int(x[:-1]), time_data))
223.             # 创建一个折线图对象
224.             line = Line()
225.             # 添加x轴数据
226.             line.add_xaxis(title_data)
227.             # 添加y轴数据和名称
228.             line.add_yaxis(echarts_select, time_data)
229.             line.set_global_opts(
230.                 title_opts=TitleOpts(title=echarts_select + "折线图", pos_left="center", pos_top='5%'),
231.                 xaxis_opts=AxisOpts(name="课程名称", axislabel_opts=LabelOpts(rotate=90)),
232.                 yaxis_opts=AxisOpts(name=echarts_select),
233.                 legend_opts=LegendOpts(is_show=True),
234.                 toolbox_opts=ToolboxOpts(is_show=True),
235.                 visualmap_opts=VisualMapOpts(is_show=True)
236.             )
237.             # 生成折线图对象
238.             line.render('课程时长折线图.html')
239.             print('已生成课程时长折线图')
240.         elif echarts_select == "报名人数":
241.             people_origin_data = [x[3] for x in all_data]
242.             people_data = []
243.             # 将有万的数据转换为整数
244.             for one in people_origin_data:
245.                 if "万" in one:
246.                     people_data.append(int(one[:-4]) * 10000)
247.                 else:
248.                     people_data.append(int(one[:-3]))
249.             bar = Bar()
250.             bar.add_xaxis(title_data)
251.             bar.add_yaxis(echarts_select, people_data, label_opts=LabelOpts(is_show=False))
252.             bar.set_global_opts(
253.                 title_opts=TitleOpts(title=echarts_select + "柱状图", pos_left="center", pos_top='5%'),
254.                 xaxis_opts=AxisOpts(name="课程名称", axislabel_opts=LabelOpts(rotate=90)),
255.                 yaxis_opts=AxisOpts(name=echarts_select),
256.                 legend_opts=LegendOpts(is_show=True),
257.                 toolbox_opts=ToolboxOpts(is_show=True),
258.                 visualmap_opts=VisualMapOpts(is_show=True)
259.             )
260.             bar.render('报名人数柱状图.html')
261.             print('已生成报名人数柱状图')

263.     def open_charts(self):
264.         # 打开统计图
265.         # 获得echarts_box的选择文本
266.         echarts_select = self.ui.echarts_box.currentText()
267.         if echarts_select == "课程时长":
268.             webbrowser.open('课程时长折线图.html')
269.             print('已打开课程时长折线图')
270.         elif echarts_select == "报名人数":
271.             webbrowser.open('报名人数柱状图.html')
272.             print('已打开报名人数柱状图')

274.     def open_course(self):
275.         # 根据输入课程名称打开课程
276.         course_xlsx = openpyxl.load_workbook('course_data.xlsx')
277.         sheet = course_xlsx.active
278.         all_data = []
279.         for row in range(2, sheet.max_row + 1):
280.             one_row_data = []
281.             for column in range(1, sheet.max_column + 1):
282.                 one_row_data.append(sheet.cell(row=row, column=column).value)
283.             all_data.append(one_row_data)

285.         course_url = None
286.         # 获得url_edit的文本,得到该课程的网址
287.         course_name = self.ui.url_edit.text()
288.         for one_data in all_data:
289.             if one_data[0] == course_name:
290.                 course_url = one_data[-1]
291.                 print('课程网址为', course_url)
292.             else:
293.                 pass
294.         # webbrowser打开网页和html的方法
295.         webbrowser.open(course_url)
296.         print('已经打开课程网页')


299. # 创建一个QApplication对象
300. app = QApplication([])
301. tencent_course = CourseTool()
302. # 调用QMainWindow对象的show方法,展示界面
303. tencent_course.ui.show()
304. # exec_方法让程序一直运行
305. app.exec_()

界面代码

1. <?xml version="1.0" encoding="UTF-8"?>
2. <ui version="4.0">
3.  <class>Form</class>
4.  <widget class="QWidget" name="Form">
5.   <property name="geometry">
6.    <rect>
7.     <x>0</x>
8.     <y>0</y>
9.     <width>710</width>
10.     <height>633</height>
11.    </rect>
12.   </property>
13.   <property name="sizePolicy">
14.    <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
15.     <horstretch>0</horstretch>
16.     <verstretch>0</verstretch>
17.    </sizepolicy>
18.   </property>
19.   <property name="font">
20.    <font>
21.     <pointsize>9</pointsize>
22.    </font>
23.   </property>
24.   <property name="windowTitle">
25.    <string>Tencent_course</string>
26.   </property>
27.   <layout class="QVBoxLayout" name="verticalLayout">
28.    <item>
29.     <layout class="QHBoxLayout" name="horizontalLayout_5">
30.      <item>
31.       <widget class="QLabel" name="time_label">
32.        <property name="sizePolicy">
33.         <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
34.          <horstretch>0</horstretch>
35.          <verstretch>0</verstretch>
36.         </sizepolicy>
37.        </property>
38.        <property name="font">
39.         <font>
40.          <pointsize>16</pointsize>
41.         </font>
42.        </property>
43.        <property name="text">
44.         <string>00:00:00</string>
45.        </property>
46.       </widget>
47.      </item>
48.     </layout>
49.    </item>
50.    <item>
51.     <widget class="Line" name="line_3">
52.      <property name="orientation">
53.       <enum>Qt::Horizontal</enum>
54.      </property>
55.     </widget>
56.    </item>
57.    <item>
58.     <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1,1,1,1">
59.      <item>
60.       <widget class="QLabel" name="label">
61.        <property name="font">
62.         <font>
63.          <pointsize>10</pointsize>
64.         </font>
65.        </property>
66.        <property name="text">
67.         <string>输入关键词</string>
68.        </property>
69.       </widget>
70.      </item>
71.      <item>
72.       <widget class="QLineEdit" name="keyEdit">
73.        <property name="font">
74.         <font>
75.          <pointsize>10</pointsize>
76.         </font>
77.        </property>
78.        <property name="placeholderText">
79.         <string>关键词</string>
80.        </property>
81.       </widget>
82.      </item>
83.      <item>
84.       <spacer name="horizontalSpacer">
85.        <property name="orientation">
86.         <enum>Qt::Horizontal</enum>
87.        </property>
88.        <property name="sizeHint" stdset="0">
89.         <size>
90.          <width>40</width>
91.          <height>20</height>
92.         </size>
93.        </property>
94.       </spacer>
95.      </item>
96.      <item>
97.       <widget class="QLabel" name="label_2">
98.        <property name="font">
99.         <font>
100.          <pointsize>10</pointsize>
101.         </font>
102.        </property>
103.        <property name="text">
104.         <string>排序方式</string>
105.        </property>
106.       </widget>
107.      </item>
108.      <item>
109.       <widget class="QComboBox" name="sortBox">
110.        <property name="font">
111.         <font>
112.          <pointsize>10</pointsize>
113.         </font>
114.        </property>
115.        <item>
116.         <property name="text">
117.          <string>综合</string>
118.         </property>
119.        </item>
120.        <item>
121.         <property name="text">
122.          <string>好评率</string>
123.         </property>
124.        </item>
125.        <item>
126.         <property name="text">
127.          <string>人气</string>
128.         </property>
129.        </item>
130.        <item>
131.         <property name="text">
132.          <string>价格(升序)</string>
133.         </property>
134.        </item>
135.        <item>
136.         <property name="text">
137.          <string>价格(降序)</string>
138.         </property>
139.        </item>
140.       </widget>
141.      </item>
142.     </layout>
143.    </item>
144.    <item>
145.     <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="1">
146.      <item>
147.       <widget class="QPushButton" name="courseButton">
148.        <property name="sizePolicy">
149.         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
150.          <horstretch>0</horstretch>
151.          <verstretch>0</verstretch>
152.         </sizepolicy>
153.        </property>
154.        <property name="font">
155.         <font>
156.          <pointsize>10</pointsize>
157.         </font>
158.        </property>
159.        <property name="text">
160.         <string>爬取课程</string>
161.        </property>
162.       </widget>
163.      </item>
164.     </layout>
165.    </item>
166.    <item>
167.     <widget class="QTableWidget" name="course_table">
168.      <column>
169.       <property name="text">
170.        <string>课程名称</string>
171.       </property>
172.      </column>
173.      <column>
174.       <property name="text">
175.        <string>价格</string>
176.       </property>
177.      </column>
178.      <column>
179.       <property name="text">
180.        <string>课程时长</string>
181.       </property>
182.      </column>
183.      <column>
184.       <property name="text">
185.        <string>报名人数</string>
186.       </property>
187.      </column>
188.      <column>
189.       <property name="text">
190.        <string>课程标签</string>
191.       </property>
192.      </column>
193.      <column>
194.       <property name="text">
195.        <string>课程网址</string>
196.       </property>
197.      </column>
198.     </widget>
199.    </item>
200.    <item>
201.     <layout class="QHBoxLayout" name="horizontalLayout_7">
202.      <item>
203.       <widget class="QLabel" name="label_3">
204.        <property name="sizePolicy">
205.         <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
206.          <horstretch>0</horstretch>
207.          <verstretch>0</verstretch>
208.         </sizepolicy>
209.        </property>
210.        <property name="font">
211.         <font>
212.          <pointsize>11</pointsize>
213.         </font>
214.        </property>
215.        <property name="text">
216.         <string>词云图</string>
217.        </property>
218.       </widget>
219.      </item>
220.     </layout>
221.    </item>
222.    <item>
223.     <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,2,1,1">
224.      <item>
225.       <widget class="QLabel" name="label_4">
226.        <property name="font">
227.         <font>
228.          <pointsize>11</pointsize>
229.         </font>
230.        </property>
231.        <property name="text">
232.         <string>数据选择</string>
233.        </property>
234.       </widget>
235.      </item>
236.      <item>
237.       <widget class="QGroupBox" name="groupBox">
238.        <property name="title">
239.         <string/>
240.        </property>
241.        <widget class="QRadioButton" name="radioButton_2">
242.         <property name="geometry">
243.          <rect>
244.           <x>150</x>
245.           <y>0</y>
246.           <width>111</width>
247.           <height>22</height>
248.          </rect>
249.         </property>
250.         <property name="font">
251.          <font>
252.           <pointsize>11</pointsize>
253.          </font>
254.         </property>
255.         <property name="text">
256.          <string>课程标签</string>
257.         </property>
258.        </widget>
259.        <widget class="QRadioButton" name="radioButton">
260.         <property name="geometry">
261.          <rect>
262.           <x>20</x>
263.           <y>0</y>
264.           <width>101</width>
265.           <height>22</height>
266.          </rect>
267.         </property>
268.         <property name="font">
269.          <font>
270.           <pointsize>11</pointsize>
271.          </font>
272.         </property>
273.         <property name="text">
274.          <string>课程名称</string>
275.         </property>
276.        </widget>
277.       </widget>
278.      </item>
279.      <item>
280.       <widget class="QPushButton" name="photobutton1">
281.        <property name="font">
282.         <font>
283.          <pointsize>11</pointsize>
284.         </font>
285.        </property>
286.        <property name="text">
287.         <string>生成图像</string>
288.        </property>
289.       </widget>
290.      </item>
291.      <item>
292.       <widget class="QPushButton" name="photobutton2">
293.        <property name="font">
294.         <font>
295.          <pointsize>11</pointsize>
296.         </font>
297.        </property>
298.        <property name="text">
299.         <string>打开图像</string>
300.        </property>
301.       </widget>
302.      </item>
303.     </layout>
304.    </item>
305.    <item>
306.     <widget class="Line" name="line">
307.      <property name="orientation">
308.       <enum>Qt::Horizontal</enum>
309.      </property>
310.     </widget>
311.    </item>
312.    <item>
313.     <layout class="QHBoxLayout" name="horizontalLayout_8">
314.      <item>
315.       <widget class="QLabel" name="label_5">
316.        <property name="sizePolicy">
317.         <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
318.          <horstretch>0</horstretch>
319.          <verstretch>0</verstretch>
320.         </sizepolicy>
321.        </property>
322.        <property name="font">
323.         <font>
324.          <pointsize>10</pointsize>
325.         </font>
326.        </property>
327.        <property name="text">
328.         <string>统计图</string>
329.        </property>
330.       </widget>
331.      </item>
332.     </layout>
333.    </item>
334.    <item>
335.     <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,2,1,1">
336.      <item>
337.       <widget class="QLabel" name="label_6">
338.        <property name="font">
339.         <font>
340.          <pointsize>11</pointsize>
341.         </font>
342.        </property>
343.        <property name="text">
344.         <string>数据选择</string>
345.        </property>
346.       </widget>
347.      </item>
348.      <item>
349.       <widget class="QComboBox" name="echarts_box">
350.        <property name="font">
351.         <font>
352.          <pointsize>10</pointsize>
353.         </font>
354.        </property>
355.        <item>
356.         <property name="text">
357.          <string>课程时长</string>
358.         </property>
359.        </item>
360.        <item>
361.         <property name="text">
362.          <string>报名人数</string>
363.         </property>
364.        </item>
365.       </widget>
366.      </item>
367.      <item>
368.       <widget class="QPushButton" name="echartsbutton1">
369.        <property name="font">
370.         <font>
371.          <pointsize>11</pointsize>
372.         </font>
373.        </property>
374.        <property name="text">
375.         <string>生成图像</string>
376.        </property>
377.       </widget>
378.      </item>
379.      <item>
380.       <widget class="QPushButton" name="echartsbutton2">
381.        <property name="font">
382.         <font>
383.          <pointsize>11</pointsize>
384.         </font>
385.        </property>
386.        <property name="text">
387.         <string>打开图像</string>
388.        </property>
389.       </widget>
390.      </item>
391.     </layout>
392.    </item>
393.    <item>
394.     <widget class="Line" name="line_2">
395.      <property name="orientation">
396.       <enum>Qt::Horizontal</enum>
397.      </property>
398.     </widget>
399.    </item>
400.    <item>
401.     <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="3,1,1">
402.      <item>
403.       <widget class="QLineEdit" name="url_edit">
404.        <property name="font">
405.         <font>
406.          <pointsize>10</pointsize>
407.         </font>
408.        </property>
409.        <property name="placeholderText">
410.         <string>请输入课程名称:</string>
411.        </property>
412.       </widget>
413.      </item>
414.      <item>
415.       <spacer name="horizontalSpacer_4">
416.        <property name="orientation">
417.         <enum>Qt::Horizontal</enum>
418.        </property>
419.        <property name="sizeHint" stdset="0">
420.         <size>
421.          <width>40</width>
422.          <height>20</height>
423.         </size>
424.        </property>
425.       </spacer>
426.      </item>
427.      <item>
428.       <widget class="QPushButton" name="course_button">
429.        <property name="font">
430.         <font>
431.          <pointsize>10</pointsize>
432.         </font>
433.        </property>
434.        <property name="text">
435.         <string>打开视频</string>
436.        </property>
437.       </widget>
438.      </item>
439.     </layout>
440.    </item>
441.   </layout>
442.  </widget>
443.  <resources/>
444.  <connections/>
445. </ui>

界面图片:

三、总结
本次课程设计主要是通过PyQt5对腾讯课堂进行爬虫数据可视化,对数据进行一些一定的分析,使用户通过程序对自己想学习的课程内容有一定的了解,让用户可以选择适合自己的课程。通过这个应用程序,用户可以方便地获取和筛选腾讯课堂上的课程信息,同时教育机构和课程提供者也可以利用该程序对课程数据进行深入分析,以优化课程内容和推广策略。
在这次课程设计中,我收获颇丰。以下是对这些收获的总结:
1.技能提升:通过编写爬虫和数据处理代码,我对Python和相关库的使用更加熟练。这不仅增强了我的编程能力,也提高了我在网络爬取和数据处理方面的专业素养。
2.问题解决能力:在爬取腾讯课堂数据的过程中,我遇到了各种预料之外的问题,如反爬策略、数据结构变化等。通过不断地尝试和调整,我锻炼了自己的问题解决能力,也学到了如何处理不确定性和变化。
3.数据分析技能:在数据清洗和整理阶段,增强了我对数据处理流程的理解,也让我掌握了更多的数据分析技能。通过对数据的可视化,我能够更直观地理解数据,从而更好地进行总结和解读。
4.遵守规则与道德:在进行网络爬虫的过程中,我深刻认识到遵守目标网站的规则和道德标准的重要性。尊重网站的权益,避免对服务器造成过大压力,是每个网络爬虫者应尽的责任。
5.实际应用与理论结合:通过这次课程设计,我不仅将理论知识应用于实践中,也从实践中加深了对理论知识的理解。网络爬虫、数据分析等技术在现实生活中的用途广泛,这次设计让我对这些技术的应用有了更直观的认识。
总的来说,这次课程设计让我在技能、实践经验和问题解决能力等方面都有了显著的提高。我相信这些经验将对我未来的学习和工作产生积极的影响。