Python价格检查器无法运行,卡在Requests网络请求步骤
Python价格检查器无法运行,卡在Requests网络请求步骤
看起来你遇到的核心问题是同步网络请求阻塞了GUI主线程,同时代码里还有几个小bug导致功能无法正常工作,我来一步步帮你解决:
1. 核心问题:网络请求阻塞GUI主线程
你的代码在启动GUI主循环root.mainloop()之前,直接调用了get_price()函数,而requests.get(URL)是同步操作——它会一直等待网络响应,期间GUI主线程完全被卡住,根本没机会渲染界面。
解决办法是把网络请求放到子线程里执行,这样GUI主线程能正常运行。我们可以用Python内置的threading模块实现。
2. 其他代码错误修复
除了主线程阻塞问题,你的代码还有几个逻辑错误:
get_price()里的price变量未赋值,且if False:分支永远不会执行,导致数据保存逻辑完全无效load_data()的循环逻辑错误,从最大行号开始遍历还不断递增,会直接越界delete_data()只是清空单元格,不如直接删除行更高效- 页面解析逻辑需要调整,才能正确从Komplett的页面提取价格
修改后的完整代码
from customtkinter import * import openpyxl from bs4 import BeautifulSoup import datetime import requests import threading root = CTk() root.title("Price Checker App") root.iconbitmap("C:/Users/Axelr/PycharmProjects/PC01/main/Self built/Price checker/icon.ico") root.geometry("550x300") set_appearance_mode("dark") set_default_color_theme("green") # 初始化Excel文件(如果不存在先创建) try: workbook = openpyxl.load_workbook(filename="price_data.xlsx") sheet = workbook.active except FileNotFoundError: workbook = openpyxl.Workbook() sheet = workbook.active sheet.append(["Date", "Price"]) workbook.save("price_data.xlsx") URL = "https://www.komplett.no/product/1217710/mobiler-klokker/mobiltelefoner/iphone-14-128gb-blaa" def view_history(): hroot = CTk() hroot.title("Price Checker App - History") hroot.iconbitmap("C:/Users/Axelr/PycharmProjects/PC01/main/Self built/Price checker/icon.ico") hroot.geometry("700x500") set_appearance_mode("dark") set_default_color_theme("dark-blue") def load_data(): # 清空历史页面已有标签 for widget in hroot.winfo_children(): if isinstance(widget, CTkLabel) and widget.cget("text").endswith("Kr"): widget.destroy() # 从第2行开始遍历(第1行是表头) row_count = sheet.max_row for row in range(2, row_count + 1): date = sheet.cell(row, 1).value price = sheet.cell(row, 2).value if date and price: date_price = f"{date}: {price} Kr" CTkLabel(master=hroot, text=date_price, text_font=("Roboto", 18)).pack(padx=10, pady=5) def delete_data(): # 从最后一行删除到第2行(保留表头) row_count = sheet.max_row for row in range(row_count, 1, -1): sheet.delete_rows(row) workbook.save(filename="price_data.xlsx") print("All data deleted!") load_data() # 删除后刷新历史记录 load_data() delete_btn = CTkButton(master=hroot, text="Delete All Data", text_font=("Roboto", 20), command=delete_data) delete_btn.pack(padx=20, pady=20) hroot.mainloop() def get_price(): # 更新GUI价格标签为"加载中..." price_label.configure(text="Price: Loading...") root.update() try: htmlpage = requests.get(URL, timeout=10) # 添加超时避免无限等待 htmlpage.raise_for_status() # 抛出HTTP错误 content = BeautifulSoup(htmlpage.content, "html.parser") # 从页面提取价格(适配Komplett的页面结构) price_element = content.find("span", class_="product-price-now") if price_element: price = price_element.get_text().replace("kr", "").strip().replace(" ", "") price_label.configure(text=f"Price: {price} Kr") else: price_label.configure(text="Price: Failed to fetch") return # 保存数据逻辑 current_datetime = datetime.datetime.now().strftime("%Y-%m-%d") placement = sheet.max_row + 1 # 检查当天是否已保存数据 row_to_check = sheet.max_row latest_date_saved = sheet.cell(row_to_check, 1).value if row_to_check >=2 else None if latest_date_saved != current_datetime: sheet.append([current_datetime, price]) workbook.save(filename="price_data.xlsx") print("Data Saved!") else: print("Data Already Saved!") except Exception as e: price_label.configure(text=f"Price: Error - {str(e)}") print(f"Request error: {str(e)}") def start_price_check(): # 用子线程执行网络请求,避免阻塞GUI threading.Thread(target=get_price, daemon=True).start() # GUI组件 title_label = CTkLabel(master=root, text="Price Checker", text_font=("Roboto", 24)) title_label.pack(padx=20, pady=20) price_label = CTkLabel(master=root, text="Price: ", text_font=("Roboto", 24)) price_label.pack(padx=20, pady=30) # 添加检查价格按钮,点击后启动子线程 check_btn = CTkButton(master=root, text="Check Current Price", text_font=("Roboto", 20), command=start_price_check) check_btn.pack(padx=20, pady=10) history_btn = CTkButton(master=root, text="Open History", text_font=("Roboto", 24), command=view_history) history_btn.pack(padx=20, pady=20) root.mainloop()
关键修改说明
- 线程化网络请求:新增
start_price_check()函数,用threading.Thread把get_price()放到子线程执行,避免阻塞GUI - 添加超时和错误处理:给
requests.get()加了10秒超时,并用try-except捕获网络异常,同时更新GUI提示用户状态 - 修复Excel操作逻辑:
- 处理文件不存在的情况,自动创建带表头的Excel文件
- 修复历史记录加载的循环逻辑,从第2行(表头后)开始遍历
- 优化删除数据的逻辑,直接删除行而非清空单元格
- 完善价格解析:适配Komplett页面的价格元素结构,正确提取价格
- 新增检查按钮:原来的代码自动执行
get_price(),现在改成用户点击按钮触发,更符合GUI交互逻辑
备注:内容来源于stack exchange,提问作者axelrothing
相关产品推荐
相关产品推荐

