20232312 2023-2024-2 《Python程序设计》实验四报告

芝士雪豹- 2024-05-29 23:43:23

课程:《Python程序设计》
班级: 2323
姓名: 李劲源
学号:20232312
实验教师:王志强
实验日期:2024年5月16日
必修/选修: 公选课

1.实验内容

1)实验要求

Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
课代表和各小组负责人收集作业(源代码、视频、综合实践报告)

  • 编写从社交网络爬取数据,实现可视化舆情监控或者情感分析。

  • 利用公开数据集,开展图像分类、恶意软件检测等

  • 利用Python库,基于OCR技术实现自动化提取图片中数据,并填入excel中。

  • 爬取天气数据,实现自动化微信提醒

  • 利用爬虫,实现自动化下载网站视频、文件等。

  • 编写小游戏:坦克大战、贪吃蛇、扫雷等等

注:在Windows/Linux系统上使用VIM、PDB、IDLE、Pycharm等工具编程实现。
(2)本实验聚焦内容

运用python库和python代码,编写一个桌面助手程序,集成:日历与备忘录天气查询快速搜索任务清单视频下载等功能

2.实验过程及结果

实验背景与目的

为了帮助用户在一个平台上快速方便地获取和管理信息,本实验旨在开发一个桌面助手应用程序,提供多种日常使用的功能,包括天气查询、快捷查询、待办事项管理、日历和提醒,以及视频下载功能。受《鲁滨逊漂流记》中那个主人公鲁滨逊的原始人助手兼伙伴星期五的启发,我将本程序命名为**F.R.I.D.A.Y.**,希望它能成为你的计算机小助手~

实验分析

应用涵盖了以下五个主要功能模块:

1. **日历和提醒**:让用户添加和查看日程事件和提醒。
2. **天气预报**:通过 OpenWeatherMap API 获取并显示指定城市的详细天气信息。
3. **快捷查询**:快速在搜索引擎中查询输入的内容,链接浏览器并搜索。
4. **待办事项**:管理日常待办事项,轻松标记已完成任务。
5. **视频下载**:通过 yt-dlp 下载指定 URL 的视频。

设计方案

整体结构

我们使用 tkinter 图形用户界面库来开发桌面助手应用。应用主界面使用 ttk.Notebook 控件创建选项卡,每个选项卡对应一个功能模块。主类 DesktopAssistant 负责初始化和管理各功能模块。

话不多说,先把使用视频摆出来(原理在下文)

导入模块和库

import tkinter as tk  # 导入tkinter库并重命名为tk
from tkinter import ttk, messagebox  # 从tkinter库中导入ttk模块和messagebox模块
from tkcalendar import Calendar, DateEntry  # 从tkcalendar库中导入Calendar和DateEntry小部件
import requests  # 导入requests库,用于发送HTTP请求和处理响应
import webbrowser  # 导入webbrowser库,用于在默认的Web浏览器中打开指定的URL
import yt_dlp  # 导入yt_dlp库,用于下载符合协议的视频(查过官网有好多好多,基本上国内外主流视频网站都能下载)

各功能模块设计

  1. 日历和提醒

    • 使用 tkcalendar 库提供日历显示功能。
    • 可以让用户添加事件,并设定提醒时间。
  2. 天气预报

    • 输入城市名称后,通过 OpenWeatherMap API 获取天气数据。
    • 显示当前温度、体感温度、湿度、风速及详细天气描述。
  3. 快捷查询

    • 用户输入要查询的内容,点击搜索按钮后在浏览器中打开百度搜索结果页面。
  4. 待办事项

    • 输入待办事项并添加到列表。
    • 用户可以标记事项已完成并从列表中删除。
  5. 视频下载

    • 输入视频 URL,利用 yt-dlp 下载视频到本地。

实现过程

主界面实现

我们首先创建主界面,使用 ttk.Notebook 创建各个功能模块的选项卡,并实例化每个功能类。

class DesktopAssistant:
    def __init__(self, root):
        self.root = root
        self.root.title("桌面助手")
        self.tab_control = ttk.Notebook(root)

        self.tab1 = ttk.Frame(self.tab_control)
        self.tab2 = ttk.Frame(self.tab_control)
        self.tab3 = ttk.Frame(self.tab_control)
        self.tab4 = ttk.Frame(self.tab_control)
        self.tab5 = ttk.Frame(self.tab_control)  

        self.tab_control.add(self.tab1, text='日历和提醒')
        self.tab_control.add(self.tab2, text='天气预报')
        self.tab_control.add(self.tab3, text='快捷查询')
        self.tab_control.add(self.tab4, text='待办事项')
        self.tab_control.add(self.tab5, text='视频下载')  

        self.tab_control.pack(expand=1, fill="both")

        self.calendar_app = CalendarApp(self.tab1)
        self.weather_app = WeatherApp(self.tab2)
        self.query_app = QueryApp(self.tab3)
        self.todo_app = TodoApp(self.tab4)
        self.video_downloader_app = VideoDownloaderApp(self.tab5) 

日历和提醒功能模块

class CalendarApp:
    def __init__(self, parent):
        self.parent = parent
        self.calendar = Calendar(parent)
        self.calendar.pack(pady=10)

        self.event_label = tk.Label(parent, text="添加事项")
        self.event_label.pack(pady=5)

        self.event_entry = tk.Entry(parent)
        self.event_entry.pack(pady=5)

        self.reminder_label = tk.Label(parent, text="提醒时间 (时间格式为HH:MM):")
        self.reminder_label.pack(pady=5)

        self.reminder_entry = tk.Entry(parent)
        self.reminder_entry.pack(pady=5)

        self.add_event_button = tk.Button(parent, text="Add Event", command=self.add_event)
        self.add_event_button.pack(pady=10)

        self.events = {}

    def add_event(self):
        date = self.calendar.get_date()
        event = self.event_entry.get()
        reminder = self.reminder_entry.get()

        if not event or not reminder:
            messagebox.showwarning("Missing Information", "Please enter both event and reminder time")
            return

        if date not in self.events:
            self.events[date] = []
        self.events[date].append((event, reminder))
        messagebox.showinfo("Event Added", f"Event '{event}' added on {date} with reminder at {reminder}")

  • 实现结果如图

img

天气预报功能模块

class WeatherApp:
    def __init__(self, parent):
        self.parent = parent

        self.city_label = tk.Label(parent, text="输入城市:")
        self.city_label.pack(pady=5)

        self.city_entry = tk.Entry(parent)
        self.city_entry.pack(pady=5)

        self.get_weather_button = tk.Button(parent, text="查询天气", command=self.get_weather)
        self.get_weather_button.pack(pady=10)

        self.weather_result = tk.Label(parent, text="", justify=tk.LEFT)
        self.weather_result.pack(pady=10)

    def get_weather(self):
        city = self.city_entry.get()
        api_key = 'Your_API_Key'  # 替换为API,这里不把我的放出来了
        url = f'https://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric'

        response = requests.get(url)
        if response.status_code == 200:
            weather_data = response.json()
            temp = weather_data['main']['temp']
            feels_like = weather_data['main']['feels_like']
            humidity = weather_data['main']['humidity']
            wind_speed = weather_data['wind']['speed']
            weather_desc = weather_data['weather'][0]['description']
            weather_main = weather_data['weather'][0]['main']

            self.weather_result.config(
                text=f"当前气温(摄氏度): {temp}°C\n"
                     f"体感温度(摄氏度): {feels_like}°C\n"
                     f"湿度: {humidity}%\n"
                     f"风速: {wind_speed} m/s\n"
                     f"天气: {weather_main} - {weather_desc}\n"
            )
        else:
            self.weather_result.config(text="Could not retrieve weather information.")

  • 实现结果如图

img

快捷查询功能模块

class QueryApp:
    def __init__(self, parent):
        self.parent = parent

        self.query_label = tk.Label(parent, text="输入你想搜索的内容:")
        self.query_label.pack(pady=5)

        self.query_entry = tk.Entry(parent)
        self.query_entry.pack(pady=5)

        self.search_button = tk.Button(parent, text="搜索", command=self.search)
        self.search_button.pack(pady=10)

    def search(self):
        query = self.query_entry.get()
        if not query:
            messagebox.showwarning("Missing Query", "Please enter a query")
            return
        url = f'https://www.baidu.com/s?wd={query}'
        webbrowser.open(url)

  • 实现结果如图

img

待办事项功能模块

class TodoApp:
    def __init__(self, parent):
        self.parent = parent

        self.todo_label = tk.Label(parent, text="输入待办事项:")
        self.todo_label.pack(pady=5)

        self.todo_entry = tk.Entry(parent)
        self.todo_entry.pack(pady=5)

        self.add_todo_button = tk.Button(parent, text="添加", command=self.add_todo)
        self.add_todo_button.pack(pady=10)

        self.todo_listbox = tk.Listbox(parent)
        self.todo_listbox.pack(pady=10)

        self.delete_todo_button = tk.Button(parent, text="已完成", command=self.delete_todo)
        self.delete_todo_button.pack(pady=10)

        self.todos = []

    def add_todo(self):
        todo = self.todo_entry.get()
        if todo:
            self.todos.append(todo)
            self.todo_listbox.insert(tk.END, todo)
            self.todo_entry.delete(0, tk.END)
        else:
            messagebox.showwarning("Missing Todo", "Please enter a todo item")

    def delete_todo(self):
        try:
            selected_idx = self.todo_listbox.curselection()[0]
            self.todo_listbox.delete(selected_idx)
            del self.todos[selected_idx]
        except IndexError:
            messagebox.showwarning("No Selection", "Please select a todo item to delete")

  • 实现结果如图

img

视频下载功能模块

class VideoDownloaderApp:
    def __init__(self, parent):
        self.parent = parent

        self.url_label = tk.Label(parent, text="输入视频网址:")
        self.url_label.pack(pady=5)

        self.url_entry = tk.Entry(parent)
        self.url_entry.pack(pady=5)

        self.download_button = tk.Button(parent, text="下载视频", command=self.download_video)
        self.download_button.pack(pady=10)

        self.status_label = tk.Label(parent, text="", justify=tk.LEFT)
        self.status_label.pack(pady=10)

    def download_video(self):
        url = self.url_entry.get()
        if not url:
            messagebox.showwarning("Missing URL", "Please enter a video URL")
            return

        ydl_opts = {
            'outtmpl': '%(title)s.%(ext)s',  # 视频文件输出路径和文件名
        }

        try:
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                ydl.download([url])
            self.status_label.config(text="下载完成、已保存在同一文件夹下")
        except Exception as e:
            self.status_label.config(text=f"下载失败: {str(e)}")

  • 实现结果如图

img

主应用程序

class VideoDownloaderApp:
    def __init__(self, parent):
        self.parent = parent

        self.url_label = tk.Label(parent, text="输入视频网址:")
        self.url_label.pack(pady=5)

        self.url_entry = tk.Entry(parent)
        self.url_entry.pack(pady=5)

        self.download_button = tk.Button(parent, text="下载视频", command=self.download_video)
        self.download_button.pack(pady=10)

        self.status_label = tk.Label(parent, text="", justify=tk.LEFT)
        self.status_label.pack(pady=10)

    def download_video(self):
        url = self.url_entry.get()
        if not url:
            messagebox.showwarning("Missing URL", "Please enter a video URL")
            return

        ydl_opts = {
            'outtmpl': '%(title)s.%(ext)s',  # 视频文件输出路径和文件名
        }

        try:
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                ydl.download([url])
            self.status_label.config(text="下载完成、已保存在同一文件夹下")
        except Exception as e:
            self.status_label.config(text=f"下载失败: {str(e)}")

3. 实验过程中遇到的问题和解决过程

  • 问题1:在完成下载视频的功能时出现提示

    ERROR: You have requested merging of multiple formats but ffmpeg is not instaled. Aborting due to --abort-on-error
    
  • 问题1解决方案:通过询问ChatGPT,我得知这个错误提示表明 yt-dlp 在尝试将多个不同格式的音视频流合并为单个文件时,发现系统缺少 ffmpeg 这个工具,因此无法进行合并操作。于是我用管理员权限下载了Chocolatey并在powershell中输入

    choco install ffmpeg
    

    添加到计算机的path中(还得用管理员权限)
    安装了ffmpeg、视频得以顺利下载

  • 问题2:在 JSON 数据解析过程中,天气 API 返回的数据格式与预期不符,导致程序无法正确解析数据并更新界面显示。

  • 问题2解决方案:通过登录访问的API官网(OpenWeather)查询有关说明,获取格式内容即可。相比前一个问题较为容易解决。

内心OS部分:

实验四体会:

  • 如果把之前的实验当做单元测试的话,本次实验可以说是一次期末考(好像也确实到了期末hh)——总结了近一学期学的知识点并加以运用:体现在上述程序中运用了老师教的类和对象网络请求异常处理等python知识点。当然不仅如此,为了实现我的目标功能,我还自主学习了有关python其他库的功能,eg.事件驱动编程GUI编程Web浏览器控制等功能,并加以应用。
  • 相较于之前做过的程序设计,本次程序的设计更倾向于功能型。代码并没有很多需要靠逻辑实现的东西,更多来自库函数的引用。我更加熟悉了Python的GUI编程、网络请求、网页打开和下载等方面的知识,并帮助我练习了模块和库的导入和使用。这些都是编写功能丰富的Python程序所必需的技能也算是极大拓展了我的视野,节省了脑力,看着程序可视化地跑起来,觉得还是一次比较不错的编程体验。

关于一些感想、建议:

在完成了一学期的Python程序设计的课程学习后,回首,的确学到了不少东西,亦产生了些许感悟,故于此稍作记录,在偌大的互联网中留点痕迹。

回想起来这也不是我第一次接触Python了。之前在高中时曾在学校的信息技术课上接触过Python语言,这应该算是我接触的第一门高级计算机语言,仍清楚记得用的是IDLE,现在回想起来还是漫游感触的。虽然当时的学习只是停留在一些input,水仙花数、字典元组等较浅的层面,但这也成了我选修这门课程、遇见王老师的契机。

Python语言还是相当简洁干练且高效的。

先前曾听闻“人生苦短、我用Python”这一有意思的说法,而在我怀着一颗敬畏的心、深入学习Python的过程中,我逐渐理解了这一句话的含金量,或者说Python的含金量。王老师善用比喻,于是我想如果把C语言比作只热情但麻烦的二哈的话,Python更像一只机智优雅的边牧。简洁的语法、丰富的标准库、动态数据... 可以说无不扣动着无数码农的心弦。

这一学期的Python课程还是学到了相当多的东西的。

  • 序列
  • 函数
  • 正则表达式
  • ......

这里就不一一例举了。
其中印象最深刻的还是老师讲的“炒饭”和“盖浇饭”。于我而言敲代码其实是一个很极端的体验。虽然在调试bug的时候可谓是满怀悲痛,但当你看着你倾注心血的程序正常运行茁壮成长时,有种孩子终于长大了的喜悦。我其实课外自己完成了许多Python程序的编写。从“全自动骚扰信息发送器”的骚扰信息脚本到“爬死你不偿命”爬虫程序,其实还是很有成就感的。

王老师讲课相当生动有趣,故给人一种极佳的上课体验。所以关于讲课方面我其实没什么太大的建议,但其实老师可以尝试在平时去布置一些练习,给同学们上手操作的机会。如果可行的话,还可以衔接一些有关网络安全内容的东西(例如Python脚本),毕竟我们是干这个的对吧:)

不善言辞,但心存感激不知所言,故于此向王老师致以最诚挚的敬意。

参考资料

...全文
294 回复 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

110

社区成员

发帖
与我相关
我的任务
社区描述
人生苦短,我用Python!
python3.11 高校
社区管理员
  • blackwall0321
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧