import hug from bottle import route, run import pyautogui import random import time import os import pythoncom import win32gui, win32con, win32process import psutil import urllib.parse import subprocess import autoit import datetime hug.API(__name__).http.output_format = hug.output_format.json # exePath = r"C:\Program Files\Microsoft Office\root\Office16\EXCEL.EXE" exePath = r"C:\Program Files\Microsoft Office\Office16\EXCEL.EXE" # 红桃3选项卡位置 hongTao3PointX = 497 hongTao3PointY = 47 # 数据刷新按钮 refreshButtonPointX = 247 refreshButtonPointY = 102 # 刷新工作簿按钮 refreshSheetPointX = 274 refreshSheetPointY = 174 # 弹框的登录按钮位置 loginButtonPointX = 518 loginButtonPointY = 437 # 刷新完成按钮 refreshEndPointX = 747 refreshEndPointY = 451 # 用来随机的最大最小x、y坐标 minPointX = 511 maxPointX = 1000 minPointY = 282 maxPointY = 600 # excel在进程中的名称 excelProcessName = "EXCEL.EXE" # 登录提示框 # hongTao3LoginButtonName = "WindowsForms10.Window.8.app.0.182b0e9_r56_ad2" hongTao3LoginButtonName = "WindowsForms10.Window.8.app.0.182b0e9_r55_ad2" # 刷新中的按钮名称 refreshIngButtonName = "WindowsForms10.Window.8.app.0.182b0e9_r57_ad2" # 刷新完成的按钮名称 refreshEndButtonName = "#32770" def getProcessName(hwnd): tid, pid = win32process.GetWindowThreadProcessId(hwnd) processName = psutil.Process(pid).name() return processName def getClassName(hwnd): className = win32gui.GetClassName(hwnd) return className ## 获取窗口标题 def getText(hwnd): text = win32gui.GetWindowText(hwnd) return text # 检验卓创的登录失效按钮 # def checkLoginInvalid(): # # 登录失效的弹框(类名: Button) # # pointX = 1047 # # pointY = 604 # # hwnd = win32gui.WindowFromPoint((pointX, pointY)) # hwnd = win32gui.GetForegroundWindow() # # print("检验卓创的登录失效按钮:", hwnd) # if hwnd != 0: # print("检验卓创的登录失效按钮:processName:", getProcessName(hwnd), ",类名:", getClassName(hwnd)) # if getProcessName(hwnd) == excelProcessName and getClassName(hwnd) == hongTao3LoginButtonName: # print("好吧,登录失效了") # pyautogui.moveTo(loginButtonPointX, loginButtonPointY, 0.5) # pyautogui.click() # time.sleep(1) # return True # else: # return False # else: # return False # 检验卓创的登录按钮 def checkHongtaoLoginButton(): # 卓创登录的弹框(类名: WindowsForms10.BUTTON.app.0.182b0e9_r93_ad2) # hwnd = win32gui.WindowFromPoint((loginButtonPointX, loginButtonPointY)) hwnd = win32gui.GetForegroundWindow() # print("检验卓创的登录按钮:", hwnd) if hwnd != 0: className = getClassName(hwnd) print("检验卓创的登录按钮:processName:", getProcessName(hwnd), ",类名:", className) lenClassName = len(className) # if getProcessName(hwnd) == "EXCEL.EXE" and getClassName(hwnd) == "WindowsForms10.BUTTON.app.0.182b0e9_r93_ad2": if getProcessName(hwnd) == excelProcessName and className == hongTao3LoginButtonName: print("开始卓创登录") pyautogui.moveTo(loginButtonPointX, loginButtonPointY, 0.5) pyautogui.click() time.sleep(1) return True else: return False else: return False # 检验卓创的数据刷新组件 def checkRefreshEnd(): # 登录失效的弹框(类名: Button) # 完成了,点击结束 # 等2秒吧 time.sleep(2) i = 1 n = 1 # hwnd为0的次数,如果超过5次,那么就终止 hwndN = 0 while i < 2: # hwnd = win32gui.WindowFromPoint((refreshEndPointX, refreshEndPointY)) hwnd = win32gui.GetForegroundWindow() # print("检验卓创的数据刷新组件:", hwnd) print("第", n, "次检测") n = n + 1 print("hwnd:", hwnd) if hwnd != 0: # hwnd为0的次数置空 hwndN = 0 print("检验卓创的数据刷新组件:processName:", getProcessName(hwnd), ",类名:", getClassName(hwnd)) if getProcessName(hwnd) == excelProcessName and getClassName(hwnd) == refreshEndButtonName: print("ok,刷新完成了") pyautogui.moveTo(refreshEndPointX, refreshEndPointY, 0.5) pyautogui.click() time.sleep(1) return True # 不用n=2的原因,是因为那个遮罩层可能没那么快出来,万一真实很快就被刷出来了,那么超时500s后,就超时关闭吧 if n > 500: print("超时500s,默认执行完成吧") return True if getProcessName(hwnd) != excelProcessName: print("目前活动窗口与实际不符,终止执行") return False # 等待1s执行 time.sleep(1) else: # hwnd为0的次数,如果超过5次,那么就终止 if hwndN > 5: return False hwndN = hwndN + 1 # 等待2s执行 time.sleep(2) @hug.get('/hongtao/server') def mysteel_chemical_server(): return 1 @hug.get('/hongtao/refresh') def mysteel_chemical_refresh(FilePath): pyautogui.FAILSAFE = False file_path = FilePath print(FilePath) screen_width, screen_height = pyautogui.size() print("当前时间:{};当前屏幕分辨率:{} x {}".format(datetime.datetime.now(), screen_width, screen_height)) pyautogui.FAILSAFE = False file_path = file_path.replace('"', '') # 显示桌面 pyautogui.hotkey('win', 'd') # return "a" try: file_path = urllib.parse.unquote(file_path) fileFullPath = file_path # print("full_path start") fileFullPath = fileFullPath.replace("\\\\", "\\") print("文件路径:", fileFullPath) if not os.path.exists(fileFullPath): print("文件不存在") return # app = xw.App(visible=True, add_book=False) # app.display_alerts = False # app.screen_updating = True # print("init app") if os.path.exists(fileFullPath) and ".xlsx" in fileFullPath \ and fileFullPath.find("~$") < 0 \ and fileFullPath.find("template") < 0: # 获取文件名和扩展名 file_name, file_ext = os.path.splitext(os.path.basename(fileFullPath)) file_name_ext = file_name + file_ext time.sleep(3) try: # 启动程序 code = exePath + " " + fileFullPath # print(code) autoit.run(code) autoit.win_wait_active(file_name_ext, timeout=20) # 等待窗口激活 autoit.win_move(file_name_ext, 0, 0, 1024, 768) # autoit.win_move(file_name_ext, 0, 0, 1920, 1080) # print("监听成功了") except Exception as e: print("监听", fileFullPath, "失败:", e) ## 失败的话,截图记录下原因 screenshot = pyautogui.screenshot() imgPath = datetime.datetime.now().strftime("%Y%m%d%H%M%S") + "_screenshot_img.png" screenshot.save(imgPath) hwnd = win32gui.GetForegroundWindow() found_title = win32gui.GetWindowText(hwnd) print("当前窗口名称:", found_title) if found_title == "": print("窗口未打开") return # 遍历异常名称列表去校验,如果匹配上了,那么就要退出excel并打开 for err_windows_name in err_windows_name_list: if found_title.startswith(err_windows_name): # 获取与窗口句柄关联的进程ID process_id = win32process.GetWindowThreadProcessId(hwnd)[1] # 根据进程ID获取进程对象并尝试优雅地终止进程 target_process = psutil.Process(process_id) target_process.terminate() print("可能是EXCEL崩溃导致,优雅退出EXCEL") return # 如果是office的,那么就是要将file_name_ext变更为 file_name;因为office没有后缀 if found_title.startswith(file_name_ext) == False: print("当前窗口与excel不一致,当前窗口:", found_title, ";excel:", file_name_ext) return autoit.win_move_by_handle(hwnd, 0, 0, 1024, 768) ## 屏幕最大化 # open full screen # hwnd = win32gui.GetForegroundWindow() # win32gui.ShowWindow(hwnd, win32con.SW_MAXIMIZE) # time.sleep(1) # 停留一秒,让屏幕改变到正常大小 time.sleep(1) ### 随机2-3次点击 单元格区域 r = random.randint(2, 3) for i in range(r): pointX = random.randint(minPointX, maxPointX) pointY = random.randint(minPointY, maxPointY) print("随机点击", i + 1, "下") pyautogui.moveTo(pointX, pointY, 0.5) pyautogui.click() ## 随机停留几秒 r = random.randint(1, 2) time.sleep(r) ##点击 红桃3 按钮 pyautogui.moveTo(hongTao3PointX, hongTao3PointY, 0.5) pyautogui.click() time.sleep(1) ##点击 数据刷新 按钮 pyautogui.moveTo(refreshButtonPointX, refreshButtonPointY, 0.5) pyautogui.click() time.sleep(1) ##点击 刷新工作簿 按钮 print("开始刷新了") pyautogui.moveTo(refreshSheetPointX, refreshSheetPointY, 0.5) pyautogui.click() time.sleep(0.5) ## 校验登录失效 # checkLoginInvalid() ## 校验重新登录 checkHongtaoLoginButton() # 点击完刷新按钮后,移开鼠标 pyautogui.moveTo(622, 300, 0.5) # 等待刷新结束 # time.sleep(15) checkRefreshEnd() # # 完成了,点击结束 # pointX = 1072 # pointY = 605 # pyautogui.moveTo(pointX, pointY, 0.5) # pyautogui.click() # time.sleep(0.5) # 保存 pyautogui.hotkey('ctrl', 's') time.sleep(1) # 关闭当前excel pyautogui.hotkey('ctrl', 'w') return True else: print("ext err:" + fileFullPath) # app.kill() return True except Exception as e: print("Exception:") print(str(e)) return False if __name__ == "__main__": app = __hug__.http.server() # server="waitress" 这个是因为有些windows的主机名有中文,需要换个服务器适配器 run(app=app, host="0.0.0.0", reloader=True, port=7007, server="waitress") # http://127.0.0.1:7007/hongtao/refresh?FilePath=D:/eta/data/hongtao3_data/卓创数据统计.xlsx