From 08a5cc28080d0218b6604fa72db7141e7bbd3d34 Mon Sep 17 00:00:00 2001 From: PAN Lei Date: Tue, 17 May 2022 13:09:03 +0200 Subject: [PATCH 01/15] try to test record audio --- docs/rdv.html | 254 ++++++++++++++++++++++++++++++++++++++ requirements.txt | 3 +- workers/SolveCaptch.py | 83 +++++++++++++ workers/commandor_page.py | 13 +- 4 files changed, 351 insertions(+), 2 deletions(-) create mode 100644 docs/rdv.html create mode 100644 workers/SolveCaptch.py diff --git a/docs/rdv.html b/docs/rdv.html new file mode 100644 index 0000000..c6d47ee --- /dev/null +++ b/docs/rdv.html @@ -0,0 +1,254 @@ + + + + + reCAPTCHA + + + + + + +
+ + +
+ +
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index b694e4b..da21495 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,5 @@ XlsxWriter~=3.0.3 boto3~=1.21.13 openpyxl==3.0.9 google-cloud-firestore==2.4.0 -PySimpleGUI==4.60.0 \ No newline at end of file +PySimpleGUI==4.60.0 +SpeechRecognition==3.8.1 \ No newline at end of file diff --git a/workers/SolveCaptch.py b/workers/SolveCaptch.py new file mode 100644 index 0000000..ab7dc21 --- /dev/null +++ b/workers/SolveCaptch.py @@ -0,0 +1,83 @@ +import random +# for recaptcha +import urllib +import pydub +from speech_recognition import Recognizer, AudioFile +import random +import os + + +class SolveCaptcha: + def __init__(self, page): + self.page = page + self.main_frame = None + self.recaptcha = None + + def delay(self): + self.page.wait_for_timeout(random.randint(1, 3) * 1000) + + def presetup(self): + name = self.page.locator( + "//iframe[@title='reCAPTCHA']").get_attribute("name") + self.recaptcha = self.page.frame(name=name) + + self.recaptcha.click("//div[@class='recaptcha-checkbox-border']") + self.delay() + s = self.recaptcha.locator("//span[@id='recaptcha-anchor']") + if s.get_attribute("aria-checked") != "false": # solved already + return + + # self.main_frame = self.page.frame(name=self.page.locator( + # "//iframe[contains(@src,'https://www.google.com/recaptcha/api2/bframe?')]").get_attribute("name")) + # self.main_frame.click("id=recaptcha-audio-button") + + def start(self): + print("start to resolve captcha") + self.presetup() + tries = 0 + while (tries <= 5): + self.delay() + try: + self.solve_captcha() + except Exception as e: + print("exception:") + print(e) + self.main_frame.click("id=recaptcha-reload-button") + else: + s = self.recaptcha.locator("//span[@id='recaptcha-anchor']") + if s.get_attribute("aria-checked") != "false": + self.page.click("id=recaptcha-demo-submit") + self.delay() + break + tries += 1 + + def solve_captcha(self): + print("solve_captcha()") + # self.main_frame.click( + # "//button[@aria-labelledby='audio-instructions rc-response-label']") + # href = self.main_frame.locator( + # "//a[@class='rc-audiochallenge-tdownload-link']").get_attribute("href") + # + # print("retrieve mp3 file") + # urllib.request.urlretrieve(href, "audio.mp3") + # + # sound = pydub.AudioSegment.from_mp3( + # "audio.mp3").export("audio.wav", format="wav") + # + # recognizer = Recognizer() + # + # recaptcha_audio = AudioFile("audio.wav") + # with recaptcha_audio as source: + # audio = recognizer.record(source) + # print("recognizer mp3 file") + # + # text = recognizer.recognize_google(audio) + # print("recognized text: " + text) + # self.main_frame.fill("id=audio-response", text) + # self.main_frame.click("id=recaptcha-verify-button") + # self.delay() + + def __del__(self): + pass + # os.remove("audio.mp3") + # os.remove("audio.wav") diff --git a/workers/commandor_page.py b/workers/commandor_page.py index 34a0ed5..6196465 100644 --- a/workers/commandor_page.py +++ b/workers/commandor_page.py @@ -11,6 +11,7 @@ import params from params import PROXY_SERVER, PROXY_PASSWORD from pojo.ReserveResultPojo import ReserveResultPojo, PublishType from pojo.contact_pojo import ContactPojo +from workers.SolveCaptch import SolveCaptcha RDV_URL = "https://rendezvousparis.hermes.com/client/register" @@ -92,6 +93,7 @@ class CommandorPage: self.setIdNumber(self.contact.passport) # self._checkCgu() + self.click_recapcha_checkbox() # wait for sms_code field # self.clickOnValidBtn() self.thread_event = e @@ -157,7 +159,7 @@ class CommandorPage: self.get_errors() def on_document_loaded(self): - print("on_document_loaded called") + self.logger.info("on_document_loaded called") def _setPhoneCountryAndStore(self): try: @@ -261,6 +263,15 @@ class CommandorPage: def clear_app_data(self): pass + + def click_recapcha_checkbox(self): + captcha_solver = SolveCaptcha(self.page) + captcha_solver.start() + del captcha_solver + # checkbox = self.page.wait_for_selector( + # "#recaptcha-anchor") + # checkbox.click() + def fill_otp(self, otp: str): self.page.focus(OTP_FIELD_ID) time.sleep(get_random_wait_time()) From ad822c0b17a643f0575e1a6b04ef0ba28d00e520 Mon Sep 17 00:00:00 2001 From: PAN Lei Date: Tue, 17 May 2022 23:52:21 +0200 Subject: [PATCH 02/15] correction for check_results --- check_results.py | 20 +++++++++----------- db/DbManager.py | 7 +++++++ pojo/ResultEnum.py | 7 +++++++ 3 files changed, 23 insertions(+), 11 deletions(-) create mode 100644 pojo/ResultEnum.py diff --git a/check_results.py b/check_results.py index d3348ee..d1b89a5 100644 --- a/check_results.py +++ b/check_results.py @@ -2,7 +2,6 @@ import logging import random import threading from concurrent.futures import ThreadPoolExecutor -from enum import Enum from typing import Union from playwright.sync_api import sync_playwright @@ -10,19 +9,15 @@ from playwright.sync_api import sync_playwright import params from logs.LogSender import TYPE_EVENT_CHECK_RESULTS, LOG_SUBJECT_EVENT from pojo.ReserveResultPojo import ReserveResultPojo, PublishType +from pojo.ResultEnum import ResultEnum -SORRY_SENTENCE = "nous sommes sincèrement désolés de n'avoir pu vous satisfaire cette fois-ci" +SORRY_SENTENCE_FR = "nous sommes sincèrement désolés de n'avoir pu vous satisfaire cette fois-ci" +SORRY_SENTENCE_EN = "we are extremely sorry that we were not able to fulfill" NOT_AVAILABLE_CONTENT = "For more than 130 years, our House has offered its full expertise to satisfy" PENDING_SENTENCE = "Ce soir, entre 20:00 et 20:30, vous obtiendrez une réponse par e-mail." PENDING_SENTENCE_EN = "This evening between 20:00 and 20:30 you will receive a response by email." -class ResultEnum(Enum): - ACCEPTED = "ACCEPTED" - REFUSED = "REFUSED" - PENDING = "PENDING" - - class TlsPlaywright(threading.local): def __init__(self) -> None: self.playwright = sync_playwright().start() @@ -88,7 +83,10 @@ class ResultChecker: self.browser.close() print("Stopped worker in ", threading.current_thread().name) status = None - if SORRY_SENTENCE in content: + if SORRY_SENTENCE_FR in content: + print("status is REFUSED") + status = ResultEnum.REFUSED + elif SORRY_SENTENCE_EN in content: print("status is REFUSED") status = ResultEnum.REFUSED elif PENDING_SENTENCE in content: @@ -111,7 +109,7 @@ if __name__ == '__main__': # get the list params.oracle_log_sender.send_log(msg="开始检查约会结果", subject=LOG_SUBJECT_EVENT, type=TYPE_EVENT_CHECK_RESULTS) db_manager = params.firebase_store_manager - # collection = db_manager.get_all_successful_items_for_day("2022-05-14", "landd") + # collection = db_manager.get_successful_item_for_day_by_status("2022-05-17", ResultEnum.ACCEPTED) collection = db_manager.get_all_successful_items() count = 0 # result_pojo = ReserveResultPojo(type=PublishType.SUCCESS, phone="0649614591", email="panleicim@gmail.com", @@ -130,7 +128,7 @@ if __name__ == '__main__': with ThreadPoolExecutor(max_workers=5) as executor: for reserve in result_list: count = count + 1 - if reserve.accepted is None or ResultEnum.PENDING.value == reserve.accepted: + if reserve.accepted is None or ResultEnum.ACCEPTED.value == reserve.accepted: executor.submit(ResultChecker().run, reserve, collection) else: print("status is " + reserve.accepted) diff --git a/db/DbManager.py b/db/DbManager.py index c448813..711eb19 100644 --- a/db/DbManager.py +++ b/db/DbManager.py @@ -5,6 +5,7 @@ import firebase_admin from firebase_admin import credentials, firestore import definitions +from pojo import ResultEnum from pojo.MailPojo import MailPojo from pojo.ReserveResultPojo import ReserveResultPojo from pojo.SimInfoPojo import SimInfoPojo @@ -38,6 +39,12 @@ class DataManager: doc_ref.where(u'source_from', u'==', source_from) return doc_ref + def get_successful_item_for_day_by_status(self, day, status: ResultEnum): + doc_ref = self._db.collection(day) + if status is not None: + doc_ref.where(u'accepted', u'==', status.value) + return doc_ref + def save_sim_info(self, sim_info: SimInfoPojo): doc_ref = self._db.collection(SIM_INFOS).document(sim_info.phone) doc_ref.set(sim_info.to_firestore_dict()) diff --git a/pojo/ResultEnum.py b/pojo/ResultEnum.py new file mode 100644 index 0000000..470eaff --- /dev/null +++ b/pojo/ResultEnum.py @@ -0,0 +1,7 @@ +from enum import Enum + + +class ResultEnum(Enum): + ACCEPTED = "ACCEPTED" + REFUSED = "REFUSED" + PENDING = "PENDING" \ No newline at end of file From 2ed2c6d82eb9cb5fbf890b23d723bf78977ec6d9 Mon Sep 17 00:00:00 2001 From: Lei PAN Date: Wed, 18 May 2022 16:03:12 +0200 Subject: [PATCH 03/15] optimize imports --- appointment.spec | 2 +- logs/LogSender.py | 5 +++++ params.py | 5 ++--- workers/commandor_page.py | 4 ++++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/appointment.spec b/appointment.spec index 928f9d5..0ef900d 100644 --- a/appointment.spec +++ b/appointment.spec @@ -52,4 +52,4 @@ import shutil shutil.copyfile('./appointment.json', '{0}/appointment.json'.format(DISTPATH)) shutil.copyfile('./contact_all.xlsx', '{0}/contact_all.xlsx'.format(DISTPATH)) shutil.copyfile('./config.ini', '{0}/config.ini'.format(DISTPATH)) -shutil.copytree('./venv\Lib/site-packages/grpc/_cython/_credentials', '{0}/appointment/grpc/_cython/_credentials'.format(DISTPATH)) \ No newline at end of file +shutil.copytree('./venv/site-packages/grpc/_cython/_credentials', '{0}/appointment/grpc/_cython/_credentials'.format(DISTPATH)) \ No newline at end of file diff --git a/logs/LogSender.py b/logs/LogSender.py index 477cf38..6e4f614 100644 --- a/logs/LogSender.py +++ b/logs/LogSender.py @@ -25,6 +25,7 @@ LOG_ERROR = "ERROR" LOG_TYPE_INFO = "INFO" LOG_ERROR_TYPE_DOUBLE_DATA = "DOUBLE_REQUEST_FOR_SAME_DATA" LOG_ERROR_TOO_MANY_REQUEST_TODAY = "TOO_MANY_REQUEST_TODAY" +LOG_ERROR_CAPTCHA_ERROR_MESSAGE = "CAPTCHA_ERROR" LOG_SUBJECT_ERROR = "ERROR" LOG_APPOINTMENT_ERROR = "APPOINTMENT_ERROR" LOG_APPOINTMENT_TIMEOUT = "TIMEOUT" @@ -78,6 +79,10 @@ class LogSender: error_msg = contact.mail self.send_log(msg=error_msg, type=LOG_ERROR_TOO_MANY_REQUEST_TODAY, subject=LOG_SUBJECT_ERROR) + def send_captcha_error(self, contact: ContactPojo): + error_msg = contact.mail + self.send_log(msg=error_msg, type=LOG_ERROR_CAPTCHA_ERROR_MESSAGE, subject=LOG_SUBJECT_ERROR) + def send_appoint_result(self, result: ReserveResultPojo): if result.type == PublishType.SUCCESS: # get id diff --git a/params.py b/params.py index 0f413bf..a5db2db 100644 --- a/params.py +++ b/params.py @@ -1,9 +1,6 @@ -import configparser import random import string -from playwright.sync_api import sync_playwright - from db.DbManager import DataManager from logs.LogSender import LogSender @@ -14,6 +11,7 @@ oracle_log_sender = LogSender() PROXY_SERVER = "http://gw.ntnt.io:5959" PROXY_PASSWORD = "94sY7zwBG13i" + def get_random_id_number_for_proxy() -> str: S = 8 # number of characters in the string. ran = ''.join(random.choices(string.digits, k=S)) @@ -21,6 +19,7 @@ def get_random_id_number_for_proxy() -> str: print("The randomly generated string is : " + str(ran)) # print the random data return id_number + DEVICES = ['iPad (gen 6)', 'iPad (gen 6) landscape', 'iPad (gen 7)', 'iPad (gen 7) landscape', 'iPad Mini', 'iPad Mini landscape', 'iPad Pro 11', 'iPad Pro 11 landscape', 'iPhone 6', 'iPhone 6 landscape', 'iPhone 6 Plus', 'iPhone 6 Plus landscape', 'iPhone 7', 'iPhone 7 landscape', 'iPhone 7 Plus', diff --git a/workers/commandor_page.py b/workers/commandor_page.py index 6196465..107c88a 100644 --- a/workers/commandor_page.py +++ b/workers/commandor_page.py @@ -25,6 +25,7 @@ MESSAGE_FIELD_CLASS = ".message" CONFIRMED_MESSAGE = "Your request for a Leather Goods appointment has been registered" DOUBLE_REQUEST_ERROR_MESSAGE = "A request with the same data has already been validated today." TOO_MANY_REQUEST_ERROR_MESSAGE = "Due to a large number of requests" +CAPTCHA_ERROR_MESSAGE = "Error verifying captcha, please try again" TIME_OUT = 400000 OTP_TIMEOUT = 240 @@ -220,6 +221,9 @@ class CommandorPage: # close browser time.sleep(2) self.browser.close() + elif CAPTCHA_ERROR_MESSAGE in erro_content: + # this email has been already used + params.oracle_log_sender.send_captcha_error(self.contact) def _set_email(self, email): time.sleep(get_random_wait_time()) From f53db19569158de6a761cbb1487d1808d2a704c6 Mon Sep 17 00:00:00 2001 From: PAN Lei Date: Sat, 21 May 2022 20:44:20 +0200 Subject: [PATCH 04/15] test 2captcha --- workers/commandor_page.py | 43 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/workers/commandor_page.py b/workers/commandor_page.py index d7f74a2..d18ae33 100644 --- a/workers/commandor_page.py +++ b/workers/commandor_page.py @@ -6,6 +6,7 @@ import threading import time from typing import Union +import requests from playwright.sync_api import sync_playwright import params @@ -19,6 +20,8 @@ RDV_URL = "https://rendezvousparis.hermes.com/client/register" # RDV_URL = "file:///Users/lpan/Downloads/test_appointment.html" # RDV_URL = "https://api.ipify.org" # RDV_URL ="https://bot.sannysoft.com/" +REGEX_DATA_SITE_KEY = "data-sitekey=[\"a-z0-9A-Z]+" +CAPCHA_NOT_READY = "CAPCHA_NOT_READY" REGEX_RDV_URL = "https:\/\/rendezvousparis\.hermes\.com\/client\/register\/[A-Z0-9]+" otp_value = None OTP_FIELD_ID = "#sms_code" @@ -92,6 +95,8 @@ class CommandorPage: "password": params.PROXY_PASSWORD } self.fill_fields() + # wait the captha element + self.find_data_sitekey() # wait for sms_code field # self.clickOnValidBtn() self.thread_event = e @@ -288,7 +293,6 @@ class CommandorPage: def clear_app_data(self): pass - def click_recapcha_checkbox(self): captcha_solver = SolveCaptcha(self.page) captcha_solver.start() @@ -319,6 +323,43 @@ class CommandorPage: time.sleep(2) self.browser.close() + def find_data_sitekey(self): + content = self.page.content() + data_sitekey = re.findall(REGEX_DATA_SITE_KEY, content) + self.logger.info(data_sitekey) + if len(data_sitekey) == 1: + key_with_comma = data_sitekey[0].split("=")[-1] + key = key_with_comma.replace("\"", '') + print("key is : " + key) + self.send_to_resolve_captcha(key) + + def send_to_resolve_captcha(self, google_key: str): + url_get = "http://2captcha.com/in.php?key=e7e3cd0977aba2dab49e0ea052ca58b1&method=userrecaptcha&googlekey={}&pageurl={}".format( + google_key, self.page.url) + res = requests.get(url_get) + print(res.text) + results = res.text.split("|") + self.captcha_id = results[-1] + # wait for 15 seconds + time.sleep(15) + # get result of the captcha + url_response = "http://2captcha.com/res.php?key=e7e3cd0977aba2dab49e0ea052ca58b1&action=get&id={}".format( + self.captcha_id) + solution = CAPCHA_NOT_READY + while solution == CAPCHA_NOT_READY: + solution_res = requests.get(url_response) + print(solution_res.text) + solution = solution_res.text + print(solution) + self.fill_captcha_solution(solution.split("|")[-1]) + + def fill_captcha_solution(self, solution): + self.logger.info("wil input solution: " + solution) + self.page.evaluate("""(solution)=>{ + let captcha_response = document.getElementById("g-recaptcha-response"); + captcha_response.innerHTML=solution;}}""", solution) + self.clickOnValidBtn() + def get_random_id_number() -> str: S = 8 # number of characters in the string. From e14ed405fbba5a6f36addc6b11283bc5f1220ac6 Mon Sep 17 00:00:00 2001 From: Lei PAN Date: Mon, 23 May 2022 12:09:32 +0200 Subject: [PATCH 05/15] need to test on mac os --- workers/SolveCaptch.py | 1 - workers/commandor_page.py | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/workers/SolveCaptch.py b/workers/SolveCaptch.py index ab7dc21..ed80168 100644 --- a/workers/SolveCaptch.py +++ b/workers/SolveCaptch.py @@ -1,7 +1,6 @@ import random # for recaptcha import urllib -import pydub from speech_recognition import Recognizer, AudioFile import random import os diff --git a/workers/commandor_page.py b/workers/commandor_page.py index d18ae33..7d6f3e3 100644 --- a/workers/commandor_page.py +++ b/workers/commandor_page.py @@ -349,15 +349,16 @@ class CommandorPage: while solution == CAPCHA_NOT_READY: solution_res = requests.get(url_response) print(solution_res.text) + time.sleep(5) solution = solution_res.text print(solution) self.fill_captcha_solution(solution.split("|")[-1]) def fill_captcha_solution(self, solution): - self.logger.info("wil input solution: " + solution) + self.logger.info("will input solution: " + solution) self.page.evaluate("""(solution)=>{ - let captcha_response = document.getElementById("g-recaptcha-response"); - captcha_response.innerHTML=solution;}}""", solution) + document.getElementById("g-recaptcha-response").innerHTML=solution;}""", solution) + self.logger.info("will click on valid btn") self.clickOnValidBtn() From 380398c76886de7a3775ff8ab2fff11435a1b6d7 Mon Sep 17 00:00:00 2001 From: PAN Lei Date: Mon, 23 May 2022 13:12:55 +0200 Subject: [PATCH 06/15] can resolve captcha with 2captcha --- workers/SolveCaptch.py | 107 ++++++++++++++------------------------ workers/commandor_page.py | 46 ++-------------- 2 files changed, 43 insertions(+), 110 deletions(-) diff --git a/workers/SolveCaptch.py b/workers/SolveCaptch.py index ed80168..9f0a470 100644 --- a/workers/SolveCaptch.py +++ b/workers/SolveCaptch.py @@ -1,82 +1,53 @@ -import random # for recaptcha -import urllib -from speech_recognition import Recognizer, AudioFile +import logging import random -import os +import re +import time + +import requests + +CAPCHA_NOT_READY = "CAPCHA_NOT_READY" +REGEX_DATA_SITE_KEY = "data-sitekey=[\"a-z0-9A-Z]+" class SolveCaptcha: def __init__(self, page): self.page = page + self.logger = logging.getLogger("SolveCaptcha") self.main_frame = None self.recaptcha = None def delay(self): self.page.wait_for_timeout(random.randint(1, 3) * 1000) - def presetup(self): - name = self.page.locator( - "//iframe[@title='reCAPTCHA']").get_attribute("name") - self.recaptcha = self.page.frame(name=name) + def start(self, handle_solution_received): + self.logger.info("start to resolve captcha") + content = self.page.content() + data_sitekey = re.findall(REGEX_DATA_SITE_KEY, content) + self.logger.info(data_sitekey) + if len(data_sitekey) == 1: + key_with_comma = data_sitekey[0].split("=")[-1] + key = key_with_comma.replace("\"", '') + print("key is : " + key) + self.solve_captcha(key, handle_solution_received) - self.recaptcha.click("//div[@class='recaptcha-checkbox-border']") - self.delay() - s = self.recaptcha.locator("//span[@id='recaptcha-anchor']") - if s.get_attribute("aria-checked") != "false": # solved already - return - - # self.main_frame = self.page.frame(name=self.page.locator( - # "//iframe[contains(@src,'https://www.google.com/recaptcha/api2/bframe?')]").get_attribute("name")) - # self.main_frame.click("id=recaptcha-audio-button") - - def start(self): - print("start to resolve captcha") - self.presetup() - tries = 0 - while (tries <= 5): - self.delay() - try: - self.solve_captcha() - except Exception as e: - print("exception:") - print(e) - self.main_frame.click("id=recaptcha-reload-button") - else: - s = self.recaptcha.locator("//span[@id='recaptcha-anchor']") - if s.get_attribute("aria-checked") != "false": - self.page.click("id=recaptcha-demo-submit") - self.delay() - break - tries += 1 - - def solve_captcha(self): - print("solve_captcha()") - # self.main_frame.click( - # "//button[@aria-labelledby='audio-instructions rc-response-label']") - # href = self.main_frame.locator( - # "//a[@class='rc-audiochallenge-tdownload-link']").get_attribute("href") - # - # print("retrieve mp3 file") - # urllib.request.urlretrieve(href, "audio.mp3") - # - # sound = pydub.AudioSegment.from_mp3( - # "audio.mp3").export("audio.wav", format="wav") - # - # recognizer = Recognizer() - # - # recaptcha_audio = AudioFile("audio.wav") - # with recaptcha_audio as source: - # audio = recognizer.record(source) - # print("recognizer mp3 file") - # - # text = recognizer.recognize_google(audio) - # print("recognized text: " + text) - # self.main_frame.fill("id=audio-response", text) - # self.main_frame.click("id=recaptcha-verify-button") - # self.delay() - - def __del__(self): - pass - # os.remove("audio.mp3") - # os.remove("audio.wav") + def solve_captcha(self, google_key: str, handle_solution_received): + self.logger.info("solve_captcha()") + url_get = "http://2captcha.com/in.php?key=e7e3cd0977aba2dab49e0ea052ca58b1&method=userrecaptcha&googlekey={}&pageurl={}".format( + google_key, self.page.url) + res = requests.get(url_get) + print(res.text) + results = res.text.split("|") + self.captcha_id = results[-1] + # wait for 15 seconds + time.sleep(15) + # get result of the captcha + url_response = "http://2captcha.com/res.php?key=e7e3cd0977aba2dab49e0ea052ca58b1&action=get&id={}".format( + self.captcha_id) + solution = CAPCHA_NOT_READY + while solution == CAPCHA_NOT_READY: + solution_res = requests.get(url_response) + time.sleep(5) + solution = solution_res.text + print(solution) + handle_solution_received(solution.split("|")[-1]) diff --git a/workers/commandor_page.py b/workers/commandor_page.py index 7d6f3e3..f2bbed4 100644 --- a/workers/commandor_page.py +++ b/workers/commandor_page.py @@ -6,7 +6,6 @@ import threading import time from typing import Union -import requests from playwright.sync_api import sync_playwright import params @@ -20,8 +19,6 @@ RDV_URL = "https://rendezvousparis.hermes.com/client/register" # RDV_URL = "file:///Users/lpan/Downloads/test_appointment.html" # RDV_URL = "https://api.ipify.org" # RDV_URL ="https://bot.sannysoft.com/" -REGEX_DATA_SITE_KEY = "data-sitekey=[\"a-z0-9A-Z]+" -CAPCHA_NOT_READY = "CAPCHA_NOT_READY" REGEX_RDV_URL = "https:\/\/rendezvousparis\.hermes\.com\/client\/register\/[A-Z0-9]+" otp_value = None OTP_FIELD_ID = "#sms_code" @@ -96,7 +93,7 @@ class CommandorPage: } self.fill_fields() # wait the captha element - self.find_data_sitekey() + self.resolve_captcha() # wait for sms_code field # self.clickOnValidBtn() self.thread_event = e @@ -293,14 +290,6 @@ class CommandorPage: def clear_app_data(self): pass - def click_recapcha_checkbox(self): - captcha_solver = SolveCaptcha(self.page) - captcha_solver.start() - del captcha_solver - # checkbox = self.page.wait_for_selector( - # "#recaptcha-anchor") - # checkbox.click() - def fill_otp(self, otp: str): self.page.focus(OTP_FIELD_ID) time.sleep(get_random_wait_time()) @@ -323,36 +312,9 @@ class CommandorPage: time.sleep(2) self.browser.close() - def find_data_sitekey(self): - content = self.page.content() - data_sitekey = re.findall(REGEX_DATA_SITE_KEY, content) - self.logger.info(data_sitekey) - if len(data_sitekey) == 1: - key_with_comma = data_sitekey[0].split("=")[-1] - key = key_with_comma.replace("\"", '') - print("key is : " + key) - self.send_to_resolve_captcha(key) - - def send_to_resolve_captcha(self, google_key: str): - url_get = "http://2captcha.com/in.php?key=e7e3cd0977aba2dab49e0ea052ca58b1&method=userrecaptcha&googlekey={}&pageurl={}".format( - google_key, self.page.url) - res = requests.get(url_get) - print(res.text) - results = res.text.split("|") - self.captcha_id = results[-1] - # wait for 15 seconds - time.sleep(15) - # get result of the captcha - url_response = "http://2captcha.com/res.php?key=e7e3cd0977aba2dab49e0ea052ca58b1&action=get&id={}".format( - self.captcha_id) - solution = CAPCHA_NOT_READY - while solution == CAPCHA_NOT_READY: - solution_res = requests.get(url_response) - print(solution_res.text) - time.sleep(5) - solution = solution_res.text - print(solution) - self.fill_captcha_solution(solution.split("|")[-1]) + def resolve_captcha(self): + self.captcha_solver = SolveCaptcha(self.page) + self.captcha_solver.start(self.fill_captcha_solution) def fill_captcha_solution(self, solution): self.logger.info("will input solution: " + solution) From b3004ab6b679130ff5961dbeedbef882f3016455 Mon Sep 17 00:00:00 2001 From: PAN Lei Date: Mon, 23 May 2022 13:50:41 +0200 Subject: [PATCH 07/15] resovle again the captcha when reload page --- workers/commandor_page.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workers/commandor_page.py b/workers/commandor_page.py index f2bbed4..a985bfd 100644 --- a/workers/commandor_page.py +++ b/workers/commandor_page.py @@ -93,7 +93,6 @@ class CommandorPage: } self.fill_fields() # wait the captha element - self.resolve_captcha() # wait for sms_code field # self.clickOnValidBtn() self.thread_event = e @@ -126,6 +125,7 @@ class CommandorPage: self.setIdNumber(self.contact.passport) # self._checkCgu() + self.resolve_captcha() def start_browser(self, proxy, pwright, device) -> Union[str, None]: try: From 7e9e830b850f5884c41112e848491f16e6b02809 Mon Sep 17 00:00:00 2001 From: PAN Lei Date: Mon, 23 May 2022 16:33:12 +0200 Subject: [PATCH 08/15] reload captcha when error --- workers/commandor_page.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workers/commandor_page.py b/workers/commandor_page.py index a985bfd..a1d5f04 100644 --- a/workers/commandor_page.py +++ b/workers/commandor_page.py @@ -245,6 +245,7 @@ class CommandorPage: elif CAPTCHA_ERROR_MESSAGE in erro_content: # this email has been already used params.oracle_log_sender.send_captcha_error(self.contact) + self.page.reload(timeout=PAGE_TIMEOUT) def _set_email(self, email): time.sleep(get_random_wait_time()) @@ -267,7 +268,6 @@ class CommandorPage: self.logger.error(error) def _checkCgu(self): - # self.page.mouse.wheel(0, random.randint(200, 600)) try: self.page.evaluate(""" document.getElementById("cgu").focus(); From cecd7f4452f70d7065c38abe0fe2cf38bf7d5e99 Mon Sep 17 00:00:00 2001 From: PAN Lei Date: Tue, 24 May 2022 18:06:49 +0200 Subject: [PATCH 09/15] handle some errors --- workers/SolveCaptch.py | 1 + workers/commandor_page.py | 44 ++++++++++++++++++++++++++------------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/workers/SolveCaptch.py b/workers/SolveCaptch.py index 9f0a470..a26644d 100644 --- a/workers/SolveCaptch.py +++ b/workers/SolveCaptch.py @@ -36,6 +36,7 @@ class SolveCaptcha: url_get = "http://2captcha.com/in.php?key=e7e3cd0977aba2dab49e0ea052ca58b1&method=userrecaptcha&googlekey={}&pageurl={}".format( google_key, self.page.url) res = requests.get(url_get) + print(res.text) results = res.text.split("|") self.captcha_id = results[-1] diff --git a/workers/commandor_page.py b/workers/commandor_page.py index 8109136..3a9eaa9 100644 --- a/workers/commandor_page.py +++ b/workers/commandor_page.py @@ -30,7 +30,7 @@ TOO_MANY_REQUEST_ERROR_MESSAGE = "Due to a large number of requests" CAPTCHA_ERROR_MESSAGE = "Error verifying captcha, please try again" TIME_OUT = 400000 OTP_TIMEOUT = 240 -PAGE_TIMEOUT = 30000 +PAGE_TIMEOUT = 40000 def get_random_wait_time() -> float: @@ -52,6 +52,7 @@ class CommandorPage: self.is_finished = False self.contact = contact self.proxy_type = proxy_type + self.is_evnet_sent = False # 0: random # 1: faubourg # 2: George @@ -65,8 +66,11 @@ class CommandorPage: def on_success(self, result: ReserveResultPojo): self.logger.info("on_success called.") - self.logger.info(result) - params.oracle_log_sender.send_appoint_result(result) + if not self.is_evnet_sent: + self.logger.info("will send successful event") + self.logger.info(result) + params.oracle_log_sender.send_appoint_result(result) + self.is_evnet_sent = True self.is_finished = True def timeout_occurred(self): @@ -92,7 +96,6 @@ class CommandorPage: "password": params.PROXY_PASSWORD } # self.fill_fields() - # wait the captha element # wait for sms_code field # self.clickOnValidBtn() self.thread_event = e @@ -171,11 +174,14 @@ class CommandorPage: self.logger.info("url is " + self.page.url) if self.page.url == RDV_URL: self.fill_fields() - message = self.page.content() - if CONFIRMED_MESSAGE in message: - # publish the successful message - self.publish_message_to_queue(self.contact, PublishType.SUCCESS, self.page.url) - self.get_errors() + try: + message = self.page.content() + if CONFIRMED_MESSAGE in message: + # publish the successful message + self.publish_message_to_queue(self.contact, PublishType.SUCCESS, self.page.url) + self.get_errors() + except Exception as error: + print(error) def on_document_loaded(self): self.logger.info("on_document_loaded called") @@ -234,7 +240,6 @@ class CommandorPage: if DOUBLE_REQUEST_ERROR_MESSAGE in erro_content: # this email has been already used params.oracle_log_sender.send_double_data_error(self.contact) - # close browser time.sleep(2) self.browser.close() elif TOO_MANY_REQUEST_ERROR_MESSAGE in erro_content: @@ -246,7 +251,8 @@ class CommandorPage: elif CAPTCHA_ERROR_MESSAGE in erro_content: # this email has been already used params.oracle_log_sender.send_captcha_error(self.contact) - self.page.reload(timeout=PAGE_TIMEOUT) + # self.page.reload(timeout=PAGE_TIMEOUT) + self.resolve_captcha() def _set_email(self, email): time.sleep(get_random_wait_time()) @@ -319,10 +325,18 @@ class CommandorPage: def fill_captcha_solution(self, solution): self.logger.info("will input solution: " + solution) - self.page.evaluate("""(solution)=>{ - document.getElementById("g-recaptcha-response").innerHTML=solution;}""", solution) - self.logger.info("will click on valid btn") - self.clickOnValidBtn() + try: + self.page.evaluate("""(solution)=>{ + document.getElementById("g-recaptcha-response").innerHTML=solution;}""", solution) + self.logger.info("will click on valid btn") + self.clickOnValidBtn() + # wait for 20s + time.sleep(20) + self.clickOnValidBtn() + + except Exception as error: + print(error) + self.page.reload(timeout=PAGE_TIMEOUT) def get_random_id_number() -> str: From d5c16fbd7bf259a1ba27d7d58610f052b34cb2d1 Mon Sep 17 00:00:00 2001 From: PAN Lei Date: Wed, 25 May 2022 23:18:32 +0200 Subject: [PATCH 10/15] add locker for page reload --- workers/commandor_page.py | 55 +++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/workers/commandor_page.py b/workers/commandor_page.py index 3a9eaa9..48f4bbb 100644 --- a/workers/commandor_page.py +++ b/workers/commandor_page.py @@ -48,11 +48,13 @@ class CommandorPage: def __init__(self, contact: ContactPojo, store_type=0, proxy_type=0): self.otp_value = None - self.logger = logging.getLogger("CommandorPage") + self.logger = logging.getLogger("CommandorPage:" + str(contact.phone)) self.is_finished = False self.contact = contact self.proxy_type = proxy_type - self.is_evnet_sent = False + self.is_event_sent = False + self.is_captcha_in_error = False + self.is_filling_fields = False # 0: random # 1: faubourg # 2: George @@ -66,12 +68,12 @@ class CommandorPage: def on_success(self, result: ReserveResultPojo): self.logger.info("on_success called.") - if not self.is_evnet_sent: + self.is_finished = True + if not self.is_event_sent: self.logger.info("will send successful event") self.logger.info(result) params.oracle_log_sender.send_appoint_result(result) - self.is_evnet_sent = True - self.is_finished = True + self.is_event_sent = True def timeout_occurred(self): params.oracle_log_sender.send_timeout_log(self.contact) @@ -95,7 +97,6 @@ class CommandorPage: "username": proxy_username, "password": params.PROXY_PASSWORD } - # self.fill_fields() # wait for sms_code field # self.clickOnValidBtn() self.thread_event = e @@ -109,7 +110,6 @@ class CommandorPage: self.clickOnValidBtn() otp_sent = self.page.locator(MESSAGE_FIELD_CLASS) otp_sent.wait_for(state='visible', timeout=TIME_OUT) - # print("message is:" + message) time.sleep(get_random_wait_time()) message = self.page.content() if CONFIRMED_MESSAGE in message: @@ -121,15 +121,17 @@ class CommandorPage: self.termine() def fill_fields(self): - self.logger.info("will call fill_fields for " + str(self.contact.phone)) - self._set_name(self.contact.last_name, self.contact.first_name) - self._setPhoneCountryAndStore() - self._setPhoneNumber(self.contact.phone) - self._set_email(self.contact.mail) - self.setIdNumber(self.contact.passport) - # - self._checkCgu() - self.resolve_captcha() + if not self.is_filling_fields: + self.is_filling_fields = True + self.logger.info("will call fill_fields for " + str(self.contact.phone)) + self._set_name(self.contact.last_name, self.contact.first_name) + self._setPhoneCountryAndStore() + self._setPhoneNumber(self.contact.phone) + self._set_email(self.contact.mail) + self.setIdNumber(self.contact.passport) + self._checkCgu() + self.resolve_captcha() + self.is_filling_fields = False def start_browser(self, proxy, pwright, device) -> Union[str, None]: try: @@ -162,7 +164,7 @@ class CommandorPage: pattern = re.compile(REGEX_RDV_URL) if pattern.match(response.url): self.logger.info("result url found: " + response.url) - self.publish_message_to_queue(self.contact, PublishType.PENDING, response.url) + # self.publish_message_to_queue(self.contact, PublishType.PENDING, response.url) def start_page(self, proxy): e = threading.Event() @@ -181,7 +183,7 @@ class CommandorPage: self.publish_message_to_queue(self.contact, PublishType.SUCCESS, self.page.url) self.get_errors() except Exception as error: - print(error) + self.logger.error(error) def on_document_loaded(self): self.logger.info("on_document_loaded called") @@ -231,7 +233,7 @@ class CommandorPage: items = self.page.query_selector("div.alert") if items: erro_content = items.inner_html() - print("错误:" + erro_content) + self.logger.info("错误:" + erro_content) self._handle_errors(erro_content) except Exception as ext: self.logger.error(ext) @@ -250,9 +252,12 @@ class CommandorPage: self.browser.close() elif CAPTCHA_ERROR_MESSAGE in erro_content: # this email has been already used + self.is_captcha_in_error = True params.oracle_log_sender.send_captcha_error(self.contact) - # self.page.reload(timeout=PAGE_TIMEOUT) - self.resolve_captcha() + # no need to retry captcha, if retry ,will generate DOUBLE_REQUEST_ERROR_MESSAGE + time.sleep(2) + self.browser.close() + # self.resolve_captcha() def _set_email(self, email): time.sleep(get_random_wait_time()) @@ -332,10 +337,14 @@ class CommandorPage: self.clickOnValidBtn() # wait for 20s time.sleep(20) - self.clickOnValidBtn() + if not self.is_finished: + if not self.is_captcha_in_error: + self.clickOnValidBtn() + else: + self.is_captcha_in_error = False except Exception as error: - print(error) + self.logger.error(error) self.page.reload(timeout=PAGE_TIMEOUT) From c50787e4bfed7ed26ceca384ea78c5dd5de184cd Mon Sep 17 00:00:00 2001 From: Lei PAN Date: Fri, 27 May 2022 10:44:41 +0200 Subject: [PATCH 11/15] dont send error event when finished --- workers/commandor_page.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/workers/commandor_page.py b/workers/commandor_page.py index 48f4bbb..c567c76 100644 --- a/workers/commandor_page.py +++ b/workers/commandor_page.py @@ -241,21 +241,26 @@ class CommandorPage: def _handle_errors(self, erro_content: str): if DOUBLE_REQUEST_ERROR_MESSAGE in erro_content: # this email has been already used - params.oracle_log_sender.send_double_data_error(self.contact) - time.sleep(2) + if not self.is_finished: + params.oracle_log_sender.send_double_data_error(self.contact) + self.is_finished = True + time.sleep(1) self.browser.close() elif TOO_MANY_REQUEST_ERROR_MESSAGE in erro_content: # this email has been already used - params.oracle_log_sender.send_too_many_error(self.contact) - # close browser - time.sleep(2) + if not self.is_finished: + params.oracle_log_sender.send_too_many_error(self.contact) + self.is_finished = True + time.sleep(1) self.browser.close() elif CAPTCHA_ERROR_MESSAGE in erro_content: # this email has been already used self.is_captcha_in_error = True - params.oracle_log_sender.send_captcha_error(self.contact) + if not self.is_finished: + params.oracle_log_sender.send_captcha_error(self.contact) + self.is_finished = True # no need to retry captcha, if retry ,will generate DOUBLE_REQUEST_ERROR_MESSAGE - time.sleep(2) + time.sleep(1) self.browser.close() # self.resolve_captcha() From 1b446965aa36ef2db23a6d2745b0f58b1fa35dd5 Mon Sep 17 00:00:00 2001 From: Lei PAN Date: Fri, 27 May 2022 12:38:36 +0200 Subject: [PATCH 12/15] add button to GUI --- appointment.py | 20 ++++++++++++++++++-- main.py | 9 ++++++--- pojo/ModeEnum.py | 6 ++++++ workers/commandor_page.py | 17 +++++++++-------- 4 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 pojo/ModeEnum.py diff --git a/appointment.py b/appointment.py index c505dbf..9e07a1a 100644 --- a/appointment.py +++ b/appointment.py @@ -2,6 +2,7 @@ import PySimpleGUI as sg # First the window layout in 2 columns from main import start_book +from pojo.ModeEnum import ModeEnum KEY_CHOOSE_STORE = "CHOOSE_STORE" KEY_START_NUMBER = "KEY_START_NUMBER" @@ -13,6 +14,9 @@ KEY_PROXY_CC = "KEY_PROXY_CC" KEY_FAUBOURG = "KEY_FAUBOURG" KEY_GEORGE = "KEY_GEORGE" KEY_SEVRES = "KEY_SEVRES" +KEY_AUTOMATIC = "KEY_AUTOMATIC" +KEY_MANUAL = "KEY_MANUAL" +GROUP_MODE = "GROUP_MODE" GROUP_STORE = "STORE" GROUP_PROXY = "GROUP_PROXY" @@ -36,12 +40,19 @@ proxy_settings_column = [ [sg.Radio('res(速度)', group_id=GROUP_PROXY, key=KEY_PROXY_RES, default=True)], [sg.Radio('cc(稳定)', group_id=GROUP_PROXY, key=KEY_PROXY_CC, default=False)], ] + +mode_settings_column = [ + [sg.Text("约会模式")], + [sg.Radio('手动', group_id=GROUP_MODE, key=KEY_MANUAL, default=True)], + [sg.Radio('自动', group_id=GROUP_MODE, key=KEY_AUTOMATIC, default=False)], +] # ----- Full layout ----- layout = [ [ sg.Column(file_list_column), sg.Column(store_settings_column), - sg.Column(proxy_settings_column) + sg.Column(proxy_settings_column), + sg.Column(mode_settings_column) ] ] @@ -57,6 +68,7 @@ while True: end_line = int(values[KEY_END_NUMBER]) max_workers = int(values[KEY_MAX_WORKERS]) store_type = 0 + mode = ModeEnum.MANUAL if values[KEY_FAUBOURG]: store_type = 1 elif values[KEY_GEORGE]: @@ -69,7 +81,11 @@ while True: proxy_type = 1 elif values[KEY_PROXY_RES]: proxy_type = 0 - start_book(start_line, end_line, store_choose_state=store_type, max_workers=max_workers, proxy_type=proxy_type) + + if values[KEY_AUTOMATIC]: + mode = ModeEnum.AUTOMATIC + start_book(start_line, end_line, store_choose_state=store_type, max_workers=max_workers, proxy_type=proxy_type, + mode=mode) # except Exception as error: # print("Not Integer: ") # print(error) diff --git a/main.py b/main.py index 28397d6..e05c530 100644 --- a/main.py +++ b/main.py @@ -4,6 +4,7 @@ from concurrent.futures import ThreadPoolExecutor import params from logs.AppLogging import init_logger +from pojo.ModeEnum import ModeEnum from utils.excel_reader import ExcelHelper from workers.commandor_page import CommandorPage @@ -13,7 +14,8 @@ logger = logging.getLogger() logger.addHandler(logging.StreamHandler(stream=sys.stdout)) -def start_book(start_number, end_number, store_choose_state=0, max_workers=10, proxy_type=0): +def start_book(start_number, end_number, store_choose_state=0, max_workers=10, proxy_type=0, + mode: ModeEnum = ModeEnum.MANUAL): # read the contact, and contact the 2 objects together excel_reader = ExcelHelper() all_contacts = excel_reader.read_contacts() @@ -25,8 +27,9 @@ def start_book(start_number, end_number, store_choose_state=0, max_workers=10, p for contact in contacts: proxy = get_proxy(contact.phone, proxy_type) # start the task in thread - executor.submit(CommandorPage(contact, store_type=store_choose_state, proxy_type=proxy_type).start_page, - proxy) + executor.submit( + CommandorPage(contact, store_type=store_choose_state, proxy_type=proxy_type, mode=mode).start_page, + proxy) def get_proxy(phone_number, proxy_type=0): diff --git a/pojo/ModeEnum.py b/pojo/ModeEnum.py new file mode 100644 index 0000000..4a37bf2 --- /dev/null +++ b/pojo/ModeEnum.py @@ -0,0 +1,6 @@ +from enum import Enum + + +class ModeEnum(Enum): + AUTOMATIC = "AUTOMATIC" + MANUAL = "MANUAL" diff --git a/workers/commandor_page.py b/workers/commandor_page.py index c567c76..1cb8c80 100644 --- a/workers/commandor_page.py +++ b/workers/commandor_page.py @@ -10,6 +10,7 @@ from playwright.sync_api import sync_playwright import params from params import PROXY_SERVER, PROXY_PASSWORD +from pojo.ModeEnum import ModeEnum from pojo.ReserveResultPojo import ReserveResultPojo, PublishType from pojo.contact_pojo import ContactPojo from workers.SolveCaptch import SolveCaptcha @@ -46,7 +47,7 @@ class Tls(threading.local): class CommandorPage: tls = Tls() - def __init__(self, contact: ContactPojo, store_type=0, proxy_type=0): + def __init__(self, contact: ContactPojo, store_type=0, proxy_type=0, mode: ModeEnum = ModeEnum.MANUAL): self.otp_value = None self.logger = logging.getLogger("CommandorPage:" + str(contact.phone)) self.is_finished = False @@ -55,6 +56,7 @@ class CommandorPage: self.is_event_sent = False self.is_captcha_in_error = False self.is_filling_fields = False + self.appointment_mode = mode # 0: random # 1: faubourg # 2: George @@ -130,7 +132,8 @@ class CommandorPage: self._set_email(self.contact.mail) self.setIdNumber(self.contact.passport) self._checkCgu() - self.resolve_captcha() + if self.appointment_mode == ModeEnum.AUTOMATIC: + self.resolve_captcha() self.is_filling_fields = False def start_browser(self, proxy, pwright, device) -> Union[str, None]: @@ -244,15 +247,13 @@ class CommandorPage: if not self.is_finished: params.oracle_log_sender.send_double_data_error(self.contact) self.is_finished = True - time.sleep(1) - self.browser.close() + self.termine() elif TOO_MANY_REQUEST_ERROR_MESSAGE in erro_content: # this email has been already used if not self.is_finished: params.oracle_log_sender.send_too_many_error(self.contact) self.is_finished = True - time.sleep(1) - self.browser.close() + self.termine() elif CAPTCHA_ERROR_MESSAGE in erro_content: # this email has been already used self.is_captcha_in_error = True @@ -260,8 +261,7 @@ class CommandorPage: params.oracle_log_sender.send_captcha_error(self.contact) self.is_finished = True # no need to retry captcha, if retry ,will generate DOUBLE_REQUEST_ERROR_MESSAGE - time.sleep(1) - self.browser.close() + self.termine() # self.resolve_captcha() def _set_email(self, email): @@ -314,6 +314,7 @@ class CommandorPage: def termine(self): self.logger.info("will close browser") + time.sleep(1) self.browser.close() def publish_message_to_queue(self, contact: ContactPojo, status: PublishType, url: str): From 9ce2ba343c34b3c0c59ceae6819f3047fa029112 Mon Sep 17 00:00:00 2001 From: PAN Lei Date: Fri, 27 May 2022 13:18:07 +0200 Subject: [PATCH 13/15] change api key --- workers/SolveCaptch.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/workers/SolveCaptch.py b/workers/SolveCaptch.py index a26644d..d8f9023 100644 --- a/workers/SolveCaptch.py +++ b/workers/SolveCaptch.py @@ -3,11 +3,11 @@ import logging import random import re import time - import requests CAPCHA_NOT_READY = "CAPCHA_NOT_READY" REGEX_DATA_SITE_KEY = "data-sitekey=[\"a-z0-9A-Z]+" +API_KEY = "d66aaf490d8aa424a5175e1fbd1aadea" class SolveCaptcha: @@ -28,23 +28,23 @@ class SolveCaptcha: if len(data_sitekey) == 1: key_with_comma = data_sitekey[0].split("=")[-1] key = key_with_comma.replace("\"", '') - print("key is : " + key) + self.logger.info("key is : " + key) self.solve_captcha(key, handle_solution_received) def solve_captcha(self, google_key: str, handle_solution_received): self.logger.info("solve_captcha()") - url_get = "http://2captcha.com/in.php?key=e7e3cd0977aba2dab49e0ea052ca58b1&method=userrecaptcha&googlekey={}&pageurl={}".format( - google_key, self.page.url) + url_get = "http://2captcha.com/in.php?key={}&method=userrecaptcha&googlekey={}&pageurl={}".format(API_KEY, + google_key, + self.page.url) res = requests.get(url_get) - - print(res.text) + self.logger.info(res.text) results = res.text.split("|") self.captcha_id = results[-1] # wait for 15 seconds time.sleep(15) # get result of the captcha - url_response = "http://2captcha.com/res.php?key=e7e3cd0977aba2dab49e0ea052ca58b1&action=get&id={}".format( - self.captcha_id) + url_response = "http://2captcha.com/res.php?key={}&action=get&id={}".format(API_KEY, + self.captcha_id) solution = CAPCHA_NOT_READY while solution == CAPCHA_NOT_READY: solution_res = requests.get(url_response) From 05eb94f2f94b6fe91ad7b844c0b764959a77fdd9 Mon Sep 17 00:00:00 2001 From: Lei PAN Date: Fri, 3 Jun 2022 10:11:29 +0200 Subject: [PATCH 14/15] add some logs in chinese --- check_results.py | 4 ++-- workers/commandor_page.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/check_results.py b/check_results.py index da5e89c..07dbfd5 100644 --- a/check_results.py +++ b/check_results.py @@ -21,7 +21,7 @@ PENDING_SENTENCE_EN = "This evening between 20:00 and 20:30 you will receive a r class TlsPlaywright(threading.local): def __init__(self) -> None: self.playwright = sync_playwright().start() - print("Create playwright instance in Thread", threading.current_thread().name) + print("创建浏览器实例,线程: ", threading.current_thread().name) class ResultChecker: @@ -116,7 +116,7 @@ if __name__ == '__main__': reserve_pojo = ReserveResultPojo.from_firestore_dict(appointment.to_dict()) result_list.append(reserve_pojo) - with ThreadPoolExecutor(max_workers=5) as executor: + with ThreadPoolExecutor(max_workers=25) as executor: for reserve in result_list: count = count + 1 if reserve.accepted is None or ResultEnum.ACCEPTED.value == reserve.accepted: diff --git a/workers/commandor_page.py b/workers/commandor_page.py index 1cb8c80..71ca404 100644 --- a/workers/commandor_page.py +++ b/workers/commandor_page.py @@ -125,7 +125,7 @@ class CommandorPage: def fill_fields(self): if not self.is_filling_fields: self.is_filling_fields = True - self.logger.info("will call fill_fields for " + str(self.contact.phone)) + self.logger.info("填充信息: " + str(self.contact.phone)) self._set_name(self.contact.last_name, self.contact.first_name) self._setPhoneCountryAndStore() self._setPhoneNumber(self.contact.phone) From f8167dd2d06c764e38a9c7f25e0562ceca33bc87 Mon Sep 17 00:00:00 2001 From: Lei PAN Date: Sat, 4 Jun 2022 09:58:48 +0200 Subject: [PATCH 15/15] add fr-FR context --- workers/commandor_page.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/workers/commandor_page.py b/workers/commandor_page.py index 71ca404..70314ed 100644 --- a/workers/commandor_page.py +++ b/workers/commandor_page.py @@ -141,7 +141,7 @@ class CommandorPage: self.browser = pwright.webkit.launch(headless=False, timeout=PAGE_TIMEOUT, proxy=proxy) self.logger.info("模拟设备: " + device) pixel_2 = pwright.devices[device] - context = self.browser.new_context(**pixel_2, locale='en-GB') + context = self.browser.new_context(**pixel_2, locale='fr-FR') self.page = context.new_page() # hide webdriver information self.page.add_init_script("""() => {