import pandas as pd
import tkinter as tk
from tkinter import filedialog, messagebox, ttk#ttk是tkinter中的一个模块,提供主题控件,filedialog是用于路径选择功能
import os
import threading
import time
import queue
import pandas
import time,random
import requests
import urllib3,json
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
def save_cookies(driver,filename):
cookies = driver.get_cookies()
with open(filename,'w') as f:
json.dump(cookies,f)
def load_cookies(driver,filename,domain):
driver.get(f'https://{domain}')
with open(filename,'r') as f:
cookies = json.load(f)
for cookie in cookies:
if domain in cookie['domain']:
driver.add_cookie(cookie)
class FileProcessorApp:
def __init__(self, root):
self.root = root
self.root.title("Test-Nick")
self.root.geometry("700x500")
self.root.resizable(True, True)#允许窗口调整大小(高度和宽度)
self.processing_paused =False
# 创建一个线程安全的队列,用于线程间通信
self.message_queue = queue.Queue()
self.create_widgets()#创建应用的各种GUI部件
self.check_queue()#开始定期检查队列(用于更新GUI)
def create_widgets(self):
main_frame = ttk.Frame(self.root, padding=10) # 主框架容器
main_frame.pack(fill=tk.BOTH, expand=True)#填充整个窗口并允许扩展
# 路径选择区域,框架容器
path_frame = ttk.LabelFrame(main_frame, text="文件路径", padding=10)
path_frame.pack(fill=tk.X, pady=(0, 10))
self.path_var = tk.StringVar()#存储路径的字符串
ttk.Entry(path_frame, textvariable=self.path_var, width=50).pack(
side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 5))#创建路径输入框并绑定到路径变量,这个输入框可以直接输入数字,也可以点击浏览按钮后,调用select_folder函数,将选择的路径的值赋值给path_var,然后这个输入框显示的内容设置为path_var即可
# 将路径输入框控件和浏览按钮都放在同一个Labelframe(即pathframe),是一个非常好的习惯,它可以清晰的表示他们属于同一功能模块
ttk.Button(path_frame, text="浏览...", command=self.select_folder).pack(side=tk.RIGHT)
# 功能按钮区域
btn_frame = ttk.Frame(main_frame)
btn_frame.pack(fill=tk.X, pady=(0, 10))
ttk.Button(btn_frame, text="开始处理", command=self.start_processing).pack(
side=tk.LEFT, padx=(0, 5))
self.pause_button = ttk.Button(btn_frame, text="暂停", command=self.pause_processing)
self.pause_button.pack(side=tk.LEFT, padx=5)
ttk.Button(btn_frame, text="重置", command=self.reset_all).pack(
side=tk.LEFT, padx=5)
ttk.Button(btn_frame, text="退出", command=self.root.destroy).pack(#self.root.destroy会关闭整个Tkinter主窗口,并结束主循环
side=tk.RIGHT)
# 进度条
self.progress = ttk.Progressbar(main_frame, orient=tk.HORIZONTAL,
length=100, mode='determinate')
self.progress.pack(fill=tk.X, pady=(0, 10))
# 状态标签
self.status_var = tk.StringVar(value="就绪")
ttk.Label(main_frame, textvariable=self.status_var).pack(anchor=tk.W)
# 结果文本框
result_frame = ttk.LabelFrame(main_frame, text="处理结果", padding=10)
result_frame.pack(fill=tk.BOTH, expand=True)
self.result_text = tk.Text(result_frame, height=15)
self.result_text.pack(fill=tk.BOTH, expand=True)
scrollbar = ttk.Scrollbar(self.result_text, command=self.result_text.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.result_text.config(yscrollcommand=scrollbar.set)
# 日志记录区域
log_frame = ttk.LabelFrame(main_frame, text="处理日志", padding=10)
log_frame.pack(fill=tk.X, pady=(10, 0))
self.log_text = tk.Text(log_frame, height=4)
self.log_text.pack(fill=tk.X)
self.log_text.config(state=tk.DISABLED) # 初始禁用编辑
def select_folder(self):
"""选择文件并更新路径"""
folder_path = filedialog.askopenfilename(title="选择excel文件",initialdir="f:",
filetypes=[("Excel文件","*.xlsx")])
if folder_path:
self.path_var.set(folder_path)#如果用户输入文件并点击确定,那会将self的path_var变量的值设置为folder_path
self.log_message(f"已选择文件: {folder_path}")
def log_message(self, message):
"""在日志区域显示消息"""
self.log_text.config(state=tk.NORMAL)#启用文本部件以进行编辑
self.log_text.insert(tk.END, message + "\n")#在文本末尾插入消息,并换行
self.log_text.see(tk.END) # 滚动到底部
self.log_text.config(state=tk.DISABLED)#禁用文本部件,防止用户编辑
def start_processing(self):
"""启动处理线程"""
folder_path = self.path_var.get()
if not folder_path:
messagebox.showerror("错误", "请选择有效的文件路径")
return
# 禁用开始按钮避免重复启动
self.status_var.set("处理中...")
# # 创建并启动处理线程
self.processing_thread = threading.Thread(#使用threading.Thread创建一个新的线程对象
target=self.process_files_thread,#指定线程要执行的函数,而不是立即调用(因为没有括号)
args=(folder_path,),#是一个元组,用于传递给target参数
daemon=True#表示该线程为守护线程,常用于执行后台任务,表示主线程退出时后台线程也立即结束
)
self.processing_thread.start()
def pause_processing(self):
"""暂停/恢复处理"""
if hasattr(self, 'processing_paused'):
self.processing_paused = not self.processing_paused
self.status_var.set("处理暂停..." if self.processing_paused else "处理中...")
if self.processing_paused:
self.log_message(f"处理手动暂停------")
self.pause_button.config(text="继续")
else:
self.log_message(f"处理手动继续------")
self.pause_button.config(text="暂停")
else:
messagebox.showinfo("提示", "没有正在进行的处理")
def reset_all(self):
"""重置应用程序状态"""
self.path_var.set("")
self.result_text.delete(1.0, tk.END)
self.log_text.config(state=tk.NORMAL)
self.log_text.delete(1.0, tk.END)
self.log_text.config(state=tk.DISABLED)
self.progress['value'] = 0
self.status_var.set("就绪")
self.log_message("已重置所有内容")
def process_files_thread(self, folder_path):
"""文件处理线程函数 - 在实际任务中运行"""
# try:
# 嵌套函数示例 - 实际应用中替换为您的处理逻辑
def nested_file_processor(file_path):
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
url_gouwudang = r"https://tool.manmanbuy.com/HistoryLowest.aspx?url="
# url_gouwudang = r"https://www.gwdang.com/"
headers = {
r'User-Agent': r"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0"}
options = Options()
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_experimental_option("excludeSwitches", ["enable-automation", "enable-logging"])
options.add_experimental_option("useAutomationExtension", False)
user_agents = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0"
]
options.add_argument(f"user-agent={random.choice(user_agents)}")
options.add_argument(f"--window-size={random.randint(1200, 1920)},{random.randint(800, 1080)}")
service = Service(executable_path="./edgedriver/msedgedriver.exe")
driver = webdriver.Edge(service=service, options=options)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
Object.defineProperty(navigator, 'plugins', {
get: () => [1, 2, 3]
});
Object.defineProperty(navigator, 'languages', {
get: () => ['zh-CN', 'zh', 'en']
});
"""
})
driver.get(url=url_gouwudang)
time.sleep(2)
try:
clock_but = driver.find_element(By.XPATH, '//div[@class="box2022618"]/div[@class="wrap"]/a[2]/img')
clock_but.click()
except:
pass
cookies_file = 'gwdang_cookies.json'
save_cookies(driver, cookies_file) # 登录成功后保存
# 加载 Cookies 免登录
# load_cookies(driver, cookies_file, 'www.gwdang.com')
# driver.refresh()
# print('123')
time.sleep(1)
input_label = driver.find_element(By.XPATH, r'//a[@href="javascript:;"]')
input_label.click()
time.sleep(1)
iframe = driver.find_element(By.XPATH,
'//iframe[@src="https://home.manmanbuy.com/dist/login.html?url=https%3A%2F%2Ftool.manmanbuy.com%2FHistoryLowest.aspx%3Furl%3D¶meter=login"]')
driver.switch_to.frame(iframe)
input2 = driver.find_element(By.XPATH, '//img[@id="WXAPP"]')
input2.click()
time.sleep(1)
input_username = driver.find_element(By.XPATH, '//input[@class="user"]')
input_username.send_keys('15269869702')
input_password = driver.find_element(By.XPATH, '//input[@class="password"]')
input_password.send_keys('melody117')
login_buttom = driver.find_element(By.XPATH, '//button[@class="logon"]')
login_buttom.click()
time.sleep(1)
driver.switch_to.default_content()
try:
clock_but = driver.find_element(By.XPATH, '//div[@class="box2022618"]/div[@class="wrap"]/a[2]/img')
clock_but.click()
except:
pass
# search_buttom = driver.find_element(By.XPATH,'//input[@id="searchHistory"]')
# input3 = driver.find_element(By.XPATH,'//input[@id="historykey"]')
def start_search(path):
time.sleep(1)
search_buttom = driver.find_element(By.XPATH, '//input[@id="searchHistory"]')
input3 = driver.find_element(By.XPATH, '//input[@id="historykey"]')
input3.clear()
input3.send_keys(path)
time.sleep(1)
search_buttom.click()
time.sleep(1)
# driver.refresh()
# iframe = driver.find_element(By.XPATH,'//iframe[@src="sse2.html?spbh=10|642057931085&preId=C9B51AF508099EE0240A4DB968E444D2OBAU"]')
# driver.switch_to.frame(iframe)
list_time = driver.find_elements(By.XPATH,
'//div[@class="content-box"]/div[2]/div[1]/ul/li[contains(.,"2025-09")]/div[2]/span')
for li1 in list_time:
print(li1.text.split('¥')[-1])
df = pd.read_excel(file_path,header=0)
for i in df.iloc[:,0]:
if hasattr(self, 'processing_paused') and self.processing_paused:
while self.processing_paused:
time.sleep(0.1)
print(i)#result = nested_file_processor(file_path)
progress_percent=20
result=1
self.message_queue.put({
'type': 'progress',
'value': progress_percent,
'message': result
})
break
# 处理完成
self.message_queue.put({
'type': 'complete',
'message': f"处理完成! 共处理 {10} 个文件"
})
# return f"处理文件: {os.path.basename(file_path)}"
self.log_message(f"开始处理文件: {folder_path}")
nested_file_processor(folder_path)
# # 处理每个文件
# for i, file_path in enumerate(all_files):
# # 检查暂停状态
# if hasattr(self, 'processing_paused') and self.processing_paused:
# while self.processing_paused:
# time.sleep(0.1)
# 调用嵌套函数处理文件
# 更新进度
# processed += 1
# progress_percent = int((i + 1) / total_files * 100)
# 通过队列发送更新消息
# self.message_queue.put({
# 'type': 'progress',
# 'value': progress_percent,
# 'message': result
# })
# # 处理完成
# self.message_queue.put({
# 'type': 'complete',
# 'message': f"处理完成! 共处理 {processed} 个文件"
# })
# except Exception as e:
# self.message_queue.put({
# 'type': 'error',
# 'message': f"处理出错: {str(e)}"
# })
def check_queue(self):
"""定期检查队列并更新UI"""
try:
while not self.message_queue.empty():
message = self.message_queue.get_nowait()
if message['type'] == 'progress':
self.progress['value'] = message['value']
self.result_text.insert(tk.END, message['message'] + "\n")
self.result_text.see(tk.END)
elif message['type'] == 'complete':
self.status_var.set(message['message'])
self.log_message(message['message'])
self.progress['value'] = 100
elif message['type'] == 'error':
self.status_var.set("处理出错!")
self.log_message(message['message'])
messagebox.showerror("错误", message['message'])
except queue.Empty:
pass
# 每100毫秒检查一次队列
self.root.after(100, self.check_queue)
# 启动应用程序
if __name__ == "__main__":
root = tk.Tk()
app = FileProcessorApp(root)
root.mainloop()
这是完整代码
最新发布