晨曦思绪 - 2024年10月
type: channel
link: https://blog.soulxyz.top/2024/10
description: 不要让时代的悲哀 成为你的悲哀
items: 如何修改基于thinter的程序的消息框图标
items: 代码合并小助手
items: 写一个简单的自动签到脚本（基于request.Session）
items: 改造了一下B站CC字幕插件

如何修改基于thinter的程序的消息框图标
type: item
date: 2024-10-30T19:57:00+08:00
description: 最近在研究Python GUI，现在主要在用一个thinter的库。今天遇到一个问题：在我已经设置了主程序图标的情况下，消息框的图标还是Thinter的默认“小羽毛”，有点点不好看……参考了这篇资料change-icon-for-tkinter-messageboxIf you set a custom icon for the root window, then this same icon will be set as the title bar icon for all other child window(s) including the message boxes from messagebox module.如果您为根窗口设置了自定义图标，那么该图标将会被设置为所有其他子窗口（包括 messagebox 模块中的消息框）的标题栏图标。于是我尝试看看是不是所有弹出框都是默认小羽毛图标，然后发现不是这样的：一定是漏了什么。回到这个警告框的定义：诶，对照代码的话，他们似乎没有区别。修改和尝试发现，一个小细节可能会解释这个默认图标的问题：在 tkinter 中，如果消息框是从根窗口 (Tk) 中弹出的，它通常会继承根窗口的图标。但如果消息框是从其他窗口（如 Toplevel）中弹出，tkinter 会将该窗口视为一个独立窗口，所以它不会自动继承根窗口的图标，除非我们在调用消息框时，显式指定其父窗口。我们刚刚看到的默认图标的窗口，是一个Toplevel窗口。那么，如何确保所有弹出的消息框都能显示自定义图标？经过一些调试和查阅资料，总结出以下几种方法：1. 确保主窗口和所有 Toplevel 窗口都有图标首先，在创建根窗口时可以直接设置图标，代码如下：import tkinter as tk from tkinter import messagebox root = tk.Tk() root.iconbitmap("your_icon.ico") # 设置主窗口图标如果你的程序还创建了 Toplevel 窗口（例如登录、注册等独立窗口），也需要为这些窗口单独设置图标，这样就不会出现默认图标的小羽毛。top = tk.Toplevel(root) top.iconbitmap("your_icon.ico") # 设置 Toplevel 窗口图标2. 使用 parent 参数来指定消息框的父窗口当消息框弹出时，通常会继承其“父窗口”的图标。如果不指定 parent，消息框默认关联到根窗口。如果我们在 Toplevel 窗口中调用消息框，则需要在消息框函数中添加 parent 参数，以确保它继承正确的图标（重点！！！）。messagebox.showwarning("警告", "这是一条警告信息", parent=top)这种方法可以确保所有消息框都正确地继承父窗口的图标，避免了默认图标的出现。代码示例为了更直观地展示这些方法，以下是一个完整示例：import tkinter as tk from tkinter import messagebox def open_warning(): if messagebox.askokcancel("退出", "您确定要退出吗？", parent=root): root.destroy() def open_toplevel(): top = tk.Toplevel(root) top.iconbitmap("your_icon.ico") # 设置Toplevel图标 tk.Button(top, text="显示警告", command=lambda: messagebox.showwarning("警告", "在Toplevel中弹出", parent=top)).pack() root = tk.Tk() root.iconbitmap("your_icon.ico") # 设置主窗口图标 tk.Button(root, text="弹出警告", command=open_warning).pack() tk.Button(root, text="打开Toplevel", command=open_toplevel).pack() root.mainloop()在这个示例中，我创建了一个主窗口（Tk）并设置了图标，同时添加了一个 Toplevel 窗口并为其单独设置了图标。这样，无论是主窗口中的消息框，还是在 Toplevel 中弹出的消息框，都会显示自定义图标，避免了默认的“小羽毛”问题。顺利解决：

代码合并小助手
type: item
date: 2024-10-17T21:33:00+08:00
description: ChatGPT o1不支持发送文件，但是有很长的上下文，那么我们可以做一个小工具，合并代码文件和目录，一同发给ChatGPT，并在后文附上问题，免去一个个复制代码内容的麻烦。效果方案选型• PyQt5：用于创建图形用户界面。• clipboard：用于处理剪贴板操作。• chardet：用于检测文件编码。• python-docx：用于生成 Word 文档。• qtmodern：用于美化用户界面。打包使用Pyinstaller，压缩使用UPX，经过UPX压缩后，软件包大小由39MB减小至31MB.主要功能使用 chardet 库自动检测并处理不同编码的文件，确保能够正确读取和合并来自不同平台的代码文件。支持将合并后的内容导出为 Markdown 和 Word 格式。源码及下载源码后续在Github上同步。下载：代码合并小工具

写一个简单的自动签到脚本（基于request.Session）
type: item
date: 2024-10-10T15:23:00+08:00
description: 前言看到舍友最近对爬虫感兴趣，然后尝试写一个自动签到脚本，但是他的方案好麻烦呀，遂写一篇文章分析之。网页分析 - 登录首先，目标是咸鱼单机-单机游戏交流分享平台，我们需要分析他的登录机制。F12打开浏览器的开发者工具，这里有一个小技巧，勾选保留日志，因为登录行为往往伴随页面刷新，如果不勾选保存日志，登录的具体日志就会一闪而过，不利于分析。这登录也忒简单了吧……！没有验证码，非常nice.登录一下看看日志具体是怎么样的。发了一个POST请求，包含明文的username和password,然后从响应中通过“set-cookies”返回cookies信息给浏览器。方案选型这里有两种方法：①我们主动存储cookies信息，然后下一次访问签到API的时候在请求头中带上②使用requests.Session，一套搞定。③使用selenium，模拟浏览器真实操作这里介绍方法②。什么是requests.Session对象？ 在Python的requests库中，requests.Session对象是一个用于发送HTTP请求的实例。与直接使用requests.get()或requests.post()发送单独的请求不同，使用Session对象可以在多个请求之间保留一些状态信息，例如cookies、headers等，从而实现更高效的HTTP通信。说白了就是，它帮我们存储cookies和header这一堆拉杂东西，极大简化代码量。哎，人生苦短，我用Python.代码实现import requests # 模拟登录 session = requests.Session() login_url = "https://www.xianyudanji.net/wp-admin/admin-ajax.php" login_data = { 'action': 'user_login', 'username': '', #用户名 'password': '', #密码 'rememberme': '1' } response = session.post(login_url, data=login_data) #post和get的时候调用前文定义的对象就可以了 if response.status_code == 200 and '"status":"1"' in response.text: print("登录成功") else: print("登录失败") exit()现在，session对象内就已经存有了cookies等一系列信息了，我们只要继续找一下签到的方法，然后下一次继续调用session.post()或者session.get()就好。然后是签到。网页分析 - 签到单击按钮后发起一个POST请求。这里的“nonce”有点意思，大概率是一个动态变化的值，我们检查一下它是怎么来的吧。Ctrl+F激活搜索工具，输入我们刚刚的nonce e91b5f2d29：找到了。代码如下： 今日已签到 我们需要使用bs库来拿到这个动态的nonce值：qiandao_button = soup.find('button', {'class': 'go-user-qiandao'})另外查了一下这个nonce的用途：这是 WordPress 的安全机制之一，称为 "nonce"（数字一次性使用密码），用于防止跨站请求伪造 (CSRF) 攻击。这个值确保请求来自合法用户而非恶意脚本。nonce 值是由服务器生成的，并在页面中通过 JavaScript 提供代码实现from bs4 import BeautifulSoup #...这里就是前文的内容，我省略掉了 # 获取包含签到按钮的页面 user_page = session.get('https://www.xianyudanji.net/user') # 解析页面获取签到按钮的状态和 nonce soup = BeautifulSoup(user_page.text, 'html.parser') qiandao_button = soup.find('button', {'class': 'go-user-qiandao'}) # 检查签到按钮是否被禁用 if 'disabled' in qiandao_button.attrs: print("今日已签到，无法重复签到") else: # 提取 nonce 值 nonce = qiandao_button['data-nonce'] print(f"获取到的 nonce 值: {nonce}") # 构建签到请求 qiandao_url = "https://www.xianyudanji.net/wp-admin/admin-ajax.php" qiandao_…

改造了一下B站CC字幕插件
type: item
date: 2024-10-07T12:44:00+08:00
description: 最近发现了一个名为 “音视频内容 AI 一键总结丨BibiGPT 学习助理” 的网站，感觉非常有趣。这个工具能够直接总结B站、油管的在线视频内容，甚至支持百度网盘的视频。稍微深入研究了一下后，我原本以为它是通过转录视频内容再进行总结，所以我自己动手部署了一下语音转文字服务，使用的是基于fast-whisper的工具（GitHub链接：jianchang512/stt: Voice Recognition to Text Tool）。然而，后来我发现即使使用最小的tiny模型，转录大约20分钟的视频也需要90秒左右，且识别准确率大约在90%以上。如果想要更高的准确率，就需要使用更大的模型。但这样一来，辛辛苦苦地转录还不如直接使用B站的AI字幕！B站的AI字幕准确率估计在98%以上，而且几乎所有视频都配有AI字幕，何乐而不为呢？因此，最初我还编写了一个Python脚本来爬取AI字幕（脚本附在文末），但B站的逻辑有些一言难尽，必须先登录才能获取字幕，否则API里面返回的字幕那部分内容是空的。后来，我发现油猴（Tampermonkey）有现成的字幕下载脚本，这样一来就无需重复造轮子了。接下来，对现有的脚本进行了以下调整：修改快捷键功能：原先的Ctrl+下载键是直接下载字幕，我将其改为直接复制字幕内容。更改下载格式：默认下载格式是SRT，我将其修改为TXT格式，便于后续处理。添加AI总结提示词：在复制字幕内容之前，加入了一段用于引导GPT进行总结的提示词：请阅读以下视频字幕文本，并总结出视频中的所有关键要点。总结应涵盖视频的主要观点、重要信息和核心内容，使读者能够理解获取到视频的全部内容。请按照以下要求进行总结： 1. **结构清晰**：使用分段或项目符号列表，使总结条理分明，易于阅读。 2. **简明扼要**：每个要点应简洁明了，避免冗长的描述。 3. **全面覆盖**：确保不遗漏视频中的重要信息和关键细节。 4. **语言简练**：使用准确且简练的语言表达，保持专业性。 5. **保持原意**：总结内容应忠实于原视频的意思，如果必要可以进行解释，便于理解。 6. **开头添加视频标题及链接**：在总结开头使用Markdown格式，将视频标题作为可点击的链接（去除“哔哩哔哩”字样），便于存档。这样一来，可以平替它的总结功能。附：Python爬取B站AI字幕脚本import requests import json import re import sys import os from datetime import timedelta import browser_cookie3 # 定义Cookies缓存文件路径 COOKIES_CACHE_FILE = 'cookies_cache.json' def load_cached_cookies(): """ 从缓存文件加载Cookies """ if os.path.exists(COOKIES_CACHE_FILE): with open(COOKIES_CACHE_FILE, 'r', encoding='utf-8') as f: try: cookies = json.load(f) print("从缓存加载Cookies。") return cookies except json.JSONDecodeError: print("Cookies缓存文件损坏，忽略缓存。") return None return None def save_cookies_to_cache(cookies_dict): """ 将Cookies保存到缓存文件 """ with open(COOKIES_CACHE_FILE, 'w', encoding='utf-8') as f: json.dump(cookies_dict, f) print("Cookies已保存到缓存。") def extract_cookies(): """ 从浏览器中提取Cookies并保存到缓存 """ print("正在从浏览器中提取Cookies...") cj = browser_cookie3.edge(domain_name='bilibili.com') # 如果使用Firefox，请使用以下行代替： # cj = browser_cookie3.firefox(domain_name='bilibili.com') # 将Cookies转换为字典 cookies_dict = requests.utils.dict_from_cookiejar(cj) # 保存到缓存 save_cookies_to_cache(cookies_dict) return cookies_dict def build_h…