Browse Source

fix:优化红桃3的代码,将参数放在前面,方便后续根据客户不同而调整

Roc 9 months ago
parent
commit
8dc868f725
1 changed files with 174 additions and 85 deletions
  1. 174 85
      rpa_hongtao3_refresh.py

+ 174 - 85
rpa_hongtao3_refresh.py

@@ -9,9 +9,52 @@ 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)
@@ -31,41 +74,41 @@ def getText(hwnd):
 
 
 # 检验卓创的登录失效按钮
-def checkLoginInvalid():
-    # 登录失效的弹框(类名: Button)
-    pointX = 1047
-    pointY = 604
-    hwnd = win32gui.WindowFromPoint((pointX, pointY))
-    # print("检验卓创的登录失效按钮:", hwnd)
-    if hwnd != 0:
-        print("检验卓创的登录失效按钮:processName:", getProcessName(hwnd), ",类名:", getClassName(hwnd))
-        if getProcessName(hwnd) == "EXCEL.EXE" and getClassName(hwnd) == "Button":
-            print("好吧,登录失效了")
-            pyautogui.moveTo(pointX, pointY, 0.5)
-            pyautogui.click()
-            time.sleep(1)
-            return True
-        else:
-            return False
-    else:
-        return False
+# 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)
-    pointX = 1042
-    pointY = 564
-    hwnd = win32gui.WindowFromPoint((pointX, pointY))
+    # 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) == "EXCEL.EXE" and className != "Button":
+        if getProcessName(hwnd) == excelProcessName and className == hongTao3LoginButtonName:
             print("开始卓创登录")
-            pyautogui.moveTo(pointX, pointY, 0.5)
+            pyautogui.moveTo(loginButtonPointX, loginButtonPointY, 0.5)
             pyautogui.click()
             time.sleep(1)
             return True
@@ -79,32 +122,51 @@ def checkHongtaoLoginButton():
 def checkRefreshEnd():
     # 登录失效的弹框(类名: Button)
     # 完成了,点击结束
-    pointX = 1072
-    pointY = 605
 
+    # 等2秒吧
+    time.sleep(2)
     i = 1
     n = 1
+
+    # hwnd为0的次数,如果超过5次,那么就终止
+    hwndN = 0
     while i < 2:
-        hwnd = win32gui.WindowFromPoint((pointX, pointY))
+        # 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) == "EXCEL.EXE" and getClassName(hwnd) == "Button":
+            if getProcessName(hwnd) == excelProcessName and getClassName(hwnd) == refreshEndButtonName:
                 print("ok,刷新完成了")
-                pyautogui.moveTo(pointX, pointY, 0.5)
+                pyautogui.moveTo(refreshEndPointX, refreshEndPointY, 0.5)
                 pyautogui.click()
                 time.sleep(1)
                 return True
-            else:
-                ## 不用n=2的原因,是因为那个遮罩层可能没那么快出来,万一真实很快就被刷出来了,那么超时500s后,就超时关闭吧
-                if n >= 500 and getClassName(hwnd) == "EXCEL7":
-                    print("ok,应该是很快就刷新完成了")
-                    return True
-                time.sleep(1)
+
+            # 不用n=2的原因,是因为那个遮罩层可能没那么快出来,万一真实很快就被刷出来了,那么超时500s后,就超时关闭吧
+            if n > 500:
+                print("超时500s,默认执行完成吧")
+                return True
+
+            if getProcessName(hwnd) != excelProcessName:
+                print("目前活动窗口与实际不符,终止执行")
+                return False
+
+            # 等待1s执行
+            time.sleep(1)
         else:
-            return
+            # hwnd为0的次数,如果超过5次,那么就终止
+            if hwndN > 5:
+                return False
+
+            hwndN = hwndN + 1
+            # 等待2s执行
+            time.sleep(2)
 
 
 @hug.get('/hongtao/server')
@@ -115,23 +177,30 @@ def mysteel_chemical_server():
 @hug.get('/hongtao/refresh')
 def mysteel_chemical_refresh(FilePath):
     pyautogui.FAILSAFE = False
-    # FilePath = urllib.parse.unquote(FilePath)
-    FilePath = FilePath.replace('"', '')
+    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:
-        fileFullPath = FilePath
-        print("fileFullPath start")
-        print(fileFullPath)
+        file_path = urllib.parse.unquote(file_path)
+        fileFullPath = file_path
 
-        fileFullPath = fileFullPath.replace(r"\\", "\\")
-        # fileFullPath = fileFullPath.replace("\\\\", "\\")
+        # print("full_path start")
+        fileFullPath = fileFullPath.replace("\\\\", "\\")
 
-        # print("fileFullPath:", fileFullPath)
+        print("文件路径:", fileFullPath)
 
-        if os.path.exists(fileFullPath) == False:
+        if not os.path.exists(fileFullPath):
+            print("文件不存在")
             return
 
         # app = xw.App(visible=True, add_book=False)
@@ -141,43 +210,69 @@ def mysteel_chemical_refresh(FilePath):
         if os.path.exists(fileFullPath) and ".xlsx" in fileFullPath \
                 and fileFullPath.find("~$") < 0 \
                 and fileFullPath.find("template") < 0:
-
-            ## 鼠标移动到左下角,开始搜索文件
-            # moveX = 22
-            # moveY = 1058
-            # pyautogui.moveTo(moveX, moveY, 0.5)
-            # pyautogui.click(moveX, moveY)
-            # time.sleep(2)
-            # pyautogui.typewrite(fileFullPath, 0.1)
-            # # print("open file:" + fileFullPath)
-            # # wb = app.books.open(fileFullPath)
-            # pyautogui.keyDown('enter')
-            # pyautogui.keyUp('enter')
-            # pyautogui.keyDown('enter')
-            # pyautogui.keyUp('enter')
-
-            # 打开文件
-            pythoncom.CoInitialize()
-            # openStatus = os.system("start " + fileFullPath.strip())
-            openStatus = os.system('start "" "{}"'.format(fileFullPath))
-            # 在上面的代码中,使用双引号将文件名引用为一个整体,这可以确保 Windows 命令行正确解释带有空格的文件路径。os.system()函数将启动一个新的命令行窗口来运行命令,然后等待命令完成。在这种情况下,"start " 命令告诉 Windows 打开文件,并使用双引号将文件名引用为一个整体。
-
-            # print("openStatus:", openStatus)
-            if openStatus == 1:
-                return False
+            # 获取文件名和扩展名
+            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)
+            # 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(511, 1745)
-                pointY = random.randint(282, 791)
+                pointX = random.randint(minPointX, maxPointX)
+                pointY = random.randint(minPointY, maxPointY)
                 print("随机点击", i + 1, "下")
                 pyautogui.moveTo(pointX, pointY, 0.5)
                 pyautogui.click()
@@ -187,29 +282,21 @@ def mysteel_chemical_refresh(FilePath):
             time.sleep(r)
 
             ##点击 红桃3 按钮
-            # pointX = 641
-            # pointX = 590
-            pointX = 521
-            pointY = 42
-            pyautogui.moveTo(pointX, pointY, 0.5)
+            pyautogui.moveTo(hongTao3PointX, hongTao3PointY, 0.5)
             pyautogui.click()
             time.sleep(1)
             ##点击 数据刷新 按钮
-            pointX = 199
-            pointY = 78
-            pyautogui.moveTo(pointX, pointY, 0.5)
+            pyautogui.moveTo(refreshButtonPointX, refreshButtonPointY, 0.5)
             pyautogui.click()
             time.sleep(1)
             ##点击 刷新工作簿 按钮
             print("开始刷新了")
-            pointX = 226
-            pointY = 169
-            pyautogui.moveTo(pointX, pointY, 0.5)
+            pyautogui.moveTo(refreshSheetPointX, refreshSheetPointY, 0.5)
             pyautogui.click()
             time.sleep(0.5)
 
             ## 校验登录失效
-            checkLoginInvalid()
+            # checkLoginInvalid()
 
             ## 校验重新登录
             checkHongtaoLoginButton()
@@ -247,4 +334,6 @@ def mysteel_chemical_refresh(FilePath):
 
 if __name__ == "__main__":
     app = __hug__.http.server()
-    run(app=app, reloader=True, port=7007)
+    # 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