本地房產(chǎn)交易信息網(wǎng)人員優(yōu)化方案
這里寫目錄標(biāo)題
- 滑動驗證觸發(fā)條件:
- 失敗條件:
- 解決方法:
- 清除cooKie
- 滑動驗證
- 方式一:win32 api獲取窗口句柄,選擇固定位置 成功率高
- 方式二: 原自動化滑動,成功率中
- 案例
先談理論,淘寶 taobao.com 的所有登陸系統(tǒng),都是基于sso來實現(xiàn)的,基本大同小異
滑動驗證觸發(fā)條件:
- 此賬戶多次異常失敗
- 該賬戶在多種ip環(huán)境下登陸
- 被系統(tǒng)檢測到自動化
失敗條件:
- 失敗一次后,繼續(xù)使用當(dāng)前cookies
- 滑動速度太慢
- 網(wǎng)絡(luò)太忙 ( 滑動成功,但是存在無效cookie)
解決方法:
每次登陸前,必須保證,當(dāng)前異常cookie,每次登陸前清除一次即可
清除cooKie
由于playwright清理當(dāng)前cookies不干凈,所以采用瀏覽器強制清除cookies
def clear_cookie(handle: int, point, point2, point3, point4):win32gui.SetForegroundWindow(handle)win32gui.ShowWindow(handle, 3) # 窗口最大化# left, top, right, bottom = win32gui.GetWindowRect(handle)# width = right - left# height = bottom - top# # # 計算指定檢查點的坐標(biāo)# x = left + int(point[0] * width)# y = top + int(point[1] * height)x = point[0]y = point[1]win32api.SetCursorPos(point)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x, y, 0, 0) # 鼠標(biāo)左鍵按下win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x, y, 0, 0) # 鼠標(biāo)左鍵抬起x = point2[0]y = point2[1]win32api.SetCursorPos(point2)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x, y, 0, 0) # 鼠標(biāo)左鍵按下win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x, y, 0, 0) # 鼠標(biāo)左鍵抬起x = point3[0]y = point3[1]win32api.SetCursorPos(point3)time.sleep(0.1)for i in range(15):win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x, y, 0, 0) # 鼠標(biāo)左鍵按下win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x, y, 0, 0) # 鼠標(biāo)左鍵抬起x = point4[0]y = point4[1]win32api.SetCursorPos(point4)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x, y, 0, 0) # 鼠標(biāo)左鍵按下win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x, y, 0, 0) # 鼠標(biāo)左鍵抬起time.sleep(0.1)win32api.keybd_event(0x0D, 0, 0, 0)win32api.keybd_event(0x0D, 0, win32con.KEYEVENTF_KEYUP, 0)def findTitle(window_title):'''查找指定標(biāo)題窗口句柄@param window_title: 標(biāo)題名@return: 窗口句柄'''hWndList = []# 函數(shù)功能:該函數(shù)枚舉所有屏幕上的頂層窗口,辦法是先將句柄傳給每一個窗口,然后再傳送給應(yīng)用程序定義的回調(diào)函數(shù)。win32gui.EnumWindows(lambda hWnd, param: param.append(hWnd), hWndList)for hwnd in hWndList:# 函數(shù)功能:該函數(shù)獲得指定窗口所屬的類的類名。# clsname = win32gui.GetClassName(hwnd)# 函數(shù)功能:該函數(shù)將指定窗口的標(biāo)題條文本(如果存在)拷貝到一個緩存區(qū)內(nèi)title = win32gui.GetWindowText(hwnd)if (window_title in title):return title, hwndreturn ()def del_cookies(self, window_title):logger.info("清空cookies中")try:self.context.clear_cookies()hwnd = findTitle(window_title)if global_config.active == "prod":clear_cookie(hwnd[1], (144, 53), (192, 173), (624, 558), (900, 549)) # 生產(chǎn)else:clear_cookie(hwnd[1], (3032, 51), (3128, 174), (3736, 548), (4006, 554))except Exception as e:logger.error(f"清除cookie異常, {str(e)}")
滑動驗證
方式一:win32 api獲取窗口句柄,選擇固定位置 成功率高
需要提前錄制當(dāng)前桌面的鼠標(biāo)軌跡
def move(handle: int, point: tuple[int], move_point: tuple[int]):"""后臺移動鼠標(biāo)"""try:# 激活窗口刀前臺win32gui.SetForegroundWindow(handle)win32gui.ShowWindow(handle, 3) # 窗口最大化left, top, right, bottom = win32gui.GetWindowRect(handle)width = right - leftheight = bottom - top# # 計算指定檢查點的坐標(biāo)x = left + int(point[0] * width)y = top + int(point[1] * height)x1 = left + int(point[0] * width) + random.randint(1, 20)y1 = top + int(point[1] * height)# x = point[0]# y = point[1]# 移動鼠標(biāo)指針win32api.SetCursorPos(point)win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x, y, 0, 0) # 鼠標(biāo)左鍵按下# time.sleep(0.5)# win32api.SetCursorPos(move_point)for i in range(x, x1):win32api.mouse_event(win32con.MOUSE_MOVED, i, y1, 0, 0) # 鼠標(biāo)左鍵按下win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x1, y1, 0, 0) # 鼠標(biāo)左鍵抬起except Exception as e:pass
方式二: 原自動化滑動,成功率中
def un_login_lock(self, distance: int, locator: Locator) -> None:locator.blur()box = locator.bounding_box()tracks = get_track(distance)x = int(box["x"] + box["width"] / 2)y = int(box["y"] + box["height"] / 2)locator.hover()self.page.mouse.down()self.page.mouse.move(x, y + random.randint(10, 20), steps=12)for track in tracks:self.page.mouse.move(track + x, y + random.randint(10, 20), steps=9)x = x + trackself.page.mouse.up()self.page.wait_for_timeout(random.randint(2200, 3200))
附錄:繞過Webdriver檢測可增加瀏覽器反識別概率,可選不加
def webdriver(self):# 繞過Webdriver檢測js = """Object.defineProperties(navigator, {webdriver:{get:()=>undefined}});"""self.page.add_init_script(js)
案例
if locator := self.is_lock(punish[0]):logger.info(f"正在進行滑動驗證,{locator.bounding_box()}")hwnd = findTitle(window_title)conf = {"start":[[4077, 583],[4079, 582],[4078,595]], # 鼠標(biāo)開始的軌跡數(shù)組"end":[[4823, 623],[4923, 699],[4518,578]] # 鼠標(biāo)結(jié)束的軌跡數(shù)組}points = eval(conf.get("config_value"))starts = points.get("start")ends = points.get("end")# 隨機選擇一個move(hwnd[1], starts[random.randint(0, len(starts) - 1)], ends[random.randint(0, len(ends) - 1)])# self.un_login_lock(500, locator)
雖然小概率出現(xiàn)異常,加入重試機制后,基本沒出現(xiàn)過問題