From f137321a1f75c1a0788181472f7dd4345ff3a9a4 Mon Sep 17 00:00:00 2001 From: work Date: Tue, 27 May 2025 10:33:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90m=E7=AB=AF=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spider/task.py | 93 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 75 insertions(+), 18 deletions(-) diff --git a/spider/task.py b/spider/task.py index 0da4dda..196ecc9 100644 --- a/spider/task.py +++ b/spider/task.py @@ -796,16 +796,28 @@ def parse_cookies(cookies): return cookies -def check_freeze_account(uid): - # 检查是否冻结 +def check_freeze_account(uid, max_retries=3, retry_delay=2, timeout=5): + """ + 检查账号是否被冻结,超时自动重试 + """ headers = { 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36', } url = f"https://graph.facebook.com/{uid}/picture?type=normal" - response = requests.get(url, headers=headers, allow_redirects=False, verify=False) - if response.status_code == 302: - if response.headers.get('Location') == 'https://static.xx.fbcdn.net/rsrc.php/v1/yh/r/C5yt7Cqf3zU.jpg': - raise AuthException('该账号已被冻结', 'frozen') + for attempt in range(max_retries): + try: + response = requests.get(url, headers=headers, allow_redirects=False, verify=False, timeout=timeout) + if response.status_code == 302: + if response.headers.get('Location') == 'https://static.xx.fbcdn.net/rsrc.php/v1/yh/r/C5yt7Cqf3zU.jpg': + raise AuthException('该账号已被冻结', 'frozen') + # 正常返回就 break + break + except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e: + print(f"请求超时或连接错误,第{attempt + 1}次重试: {e}") + if attempt < max_retries - 1: + time.sleep(retry_delay) + else: + raise OperationFailed("验证账号冻结失败") # 最后一次失败则抛出异常 def check_account_status(page, cookies): @@ -1325,7 +1337,7 @@ def playwright_m_login(username, password, code_2fa=None): logger.info(f"登录账号{username}") # 检查是否冻结 check_freeze_account(username) - + logger.info(f"账号{username} 未冻结") path = os.path.join(BASE_PATH, 'chrome', '130-0008', 'chrome.exe') with lock: with sync_playwright() as playwright: @@ -1352,17 +1364,31 @@ def playwright_m_login(username, password, code_2fa=None): page = context.new_page() url = 'https://m.facebook.com/login' retry_goto(page, url) - page.locator('//input[@id="m_login_email"]').type(username, delay=30) - time.sleep(random.randint(1, 3)) - page.locator('//input[@id="m_login_password"]').type(password, delay=30) - time.sleep(random.randint(1, 3)) - page.click('//div[@aria-label="Log in"]') - time.sleep(random.randint(3, 5)) + # 概率会跳到首页 + have_account = 'div[role="button"][aria-label="I already have an account"]' + # 用户名输入框框 + input_email = "input#m_login_email" - success_login_selector = '//span[text()="Check your notifications on another device"]' - failed_login_selector = '//div[@data-bloks-name="bk.components.dialog.Dialog"]/div[@aria-label="Wrong Credentials"]/div[1]' + try: + page.wait_for_selector(f'{have_account}, {input_email}', timeout=60000) + except Exception as e: + logger.error(f"页面加载异常, 未定位到按钮", exc_info=True) + raise OperationFailed("系统异常") + + hava_account_btn = page.query_selector(have_account) + if hava_account_btn: + hava_account_btn.click() + + page.wait_for_selector(f'{input_email}', timeout=60000).type(username, delay=30) + time.sleep(1) + page.wait_for_selector(f'//input[@id="m_login_password"]', timeout=60000).type(password, delay=30) + time.sleep(1) + page.click('div[aria-label="Log in"]') + + success_login_selector = 'span:has-text("Check your notifications on another device")' + failed_login_selector = 'div[data-bloks-name="bk.components.dialog.Dialog"] > div[aria-label="Wrong Credentials"] > div:nth-child(1)' # 等成功或失败两个选择的其中一个 - page.wait_for_selector(f'{success_login_selector} | {failed_login_selector}', timeout=60000) + page.wait_for_selector(f'{success_login_selector}, {failed_login_selector}', timeout=60000) # 判断是否失败 failed_login = page.query_selector(failed_login_selector) @@ -1371,9 +1397,40 @@ def playwright_m_login(username, password, code_2fa=None): logger.info(f"用户名:{username} 密码错误 {failed_login.text_content()}") raise OperationFailed(failed_login.text_content()) + # 点击尝试另一种方式验证账号 + page.query_selector('div[role="button"][aria-label="Try another way"]').click() + + # 点击选择app验证 + page.wait_for_selector( + 'span[data-bloks-name="bk.components.TextSpan"]:has-text("Authentication app")').click() + + # 点击继续 + page.query_selector('div[role="button"][aria-label="Continue"]').click() + + # 等待页面 + page.wait_for_selector('span:has-text("Go to your authentication app")') + + # 输入2faCode + auth_code = pyotp.TOTP(code_2fa).now() + page.wait_for_selector('input[aria-label="Code"][type="text"]', timeout=60000).fill(auth_code) + + # 点击继续 + page.query_selector('div[role="button"][aria-label="Continue"]').click() + + # 等待登录成功 + page.wait_for_selector('span:has-text("Save your login info?")', timeout=60000) + + # 成功 logger.info(f"用户名:{username} 账号密码正确") - time.sleep(3) - raise OperationFailed("终止任务") + + c = {i['name']: i['value'] for i in context.cookies()} + if c["c_user"] is None: + raise OperationFailed("操作失败") + logger.info(f"登录账号{username} 登录成功") + + context.close() + browser.close() + return {'cookies': json.dumps(c)} if __name__ == '__main__':