Merge branch 'feature/pb_datadome' into feature/anti-cap

This commit is contained in:
2022-09-02 17:06:14 +02:00
8 changed files with 488 additions and 681 deletions
+9 -9
View File
@@ -9,8 +9,8 @@ KEY_START_NUMBER = "KEY_START_NUMBER"
KEY_END_NUMBER = "KEY_END_NUMBER"
KEY_MAX_WORKERS = "KEY_MAX_WORKERS"
KEY_RANDOM = "KEY_RANDOM"
KEY_PROXY_BRIGHTDATA = "KEY_PROXY_BRIGHTDATA"
KEY_PROXY_NETNUT = "KEY_PROXY_NETNUT"
KEY_PROXY_MOBILE = "KEY_PROXY_MOBILE"
KEY_PROXY_RESIDENTIAL = "KEY_PROXY_RESIDENTIAL"
KEY_FAUBOURG = "KEY_FAUBOURG"
KEY_GEORGE = "KEY_GEORGE"
KEY_SEVRES = "KEY_SEVRES"
@@ -39,8 +39,8 @@ store_settings_column = [
]
proxy_settings_column = [
[sg.Text("代理ip池")],
[sg.Radio('亮数据', group_id=GROUP_PROXY, key=KEY_PROXY_BRIGHTDATA, default=True)],
[sg.Radio('Netnut', group_id=GROUP_PROXY, key=KEY_PROXY_NETNUT, default=False)],
[sg.Radio('住宅IP', group_id=GROUP_PROXY, key=KEY_PROXY_RESIDENTIAL, default=True)],
[sg.Radio('手机IP', group_id=GROUP_PROXY, key=KEY_PROXY_MOBILE, default=False)],
]
mode_settings_column = [
@@ -82,11 +82,11 @@ while True:
elif values[KEY_SEVRES]:
store_type = 3
proxy_type = ProxyType.BRIGHT_DATA
if values[KEY_PROXY_NETNUT]:
proxy_type = ProxyType.NETNUT
elif values[KEY_PROXY_BRIGHTDATA]:
proxy_type = ProxyType.BRIGHT_DATA
proxy_type = ProxyType.RESIDENTIAL
if values[KEY_PROXY_RESIDENTIAL]:
proxy_type = ProxyType.RESIDENTIAL
elif values[KEY_PROXY_MOBILE]:
proxy_type = ProxyType.MOBILE
if values[KEY_AUTOMATIC]:
mode = ModeEnum.AUTOMATIC
+18 -18
View File
@@ -1,19 +1,19 @@
dataclasses_json==0.5.7
firebase_admin==5.2.0
pandas~=1.3.5
playwright==1.25.0
dataclasses~=0.6
SpeechRecognition==3.8.1
pymongo==4.1.1
anticaptchaofficial==1.0.43
oci~=2.54.1
XlsxWriter~=3.0.3
playwright-stealth==1.0.5
boto3~=1.21.13
openpyxl==3.0.9
google-cloud-firestore==2.4.0
PySimpleGUI==4.60.1
SQLAlchemy~=1.4.37
requests~=2.27.1
sqlalchemy_utils~=0.38.2
dataclasses_json==0.5.7
firebase_admin==5.2.0
pandas~=1.3.5
playwright==1.25.0
dataclasses~=0.6
SpeechRecognition==3.8.1
pymongo==4.1.1
anticaptchaofficial==1.0.43
oci~=2.54.1
XlsxWriter~=3.0.3
playwright-stealth==1.0.5
boto3~=1.21.13
openpyxl==3.0.9
google-cloud-firestore==2.4.0
PySimpleGUI==4.60.1
SQLAlchemy~=1.4.37
requests~=2.27.1
sqlalchemy_utils~=0.38.2
Mako~=1.2.0
+173 -173
View File
@@ -1,173 +1,173 @@
import datetime
import email
import imaplib
import re
from concurrent.futures import ThreadPoolExecutor
from email.header import decode_header
from email.message import Message
from builtins import list
from src import params
from src.db.mongo_manager import MONGO_STORE_MANAGER
from src.pojo.mail.mail_pojo import MailPojo, MailAddress
from src.proxy.proxy_type import ProxyType
from src.workers.link_validator import LinkValidator
AOL_IMAP_SERVER = "imap.aol.com"
IMAP_SERVER_163 = "imap.163.com"
VALIDATION_URL_SUBJECT = 'Validation de votre demande de rendez-vous'
VALIDATION_URL_REGEX = """https:\/\/rendezvousparis.hermes.com\/client\/register\/[A-Z0-9]+\/validate.code=[A-Z0-9]+"""
HERMES_EMAIL = "no-reply@hermes.com"
DOMAIN_163 = "163.com"
date_format = "%d-%b-%Y" # DD-Mon-YYYY e.g., 3-Mar-2014
class MailReader():
def __init__(self, login, password):
self.login = login
self.password = password
@staticmethod
def show_folders(imap):
for i in imap.list()[1]:
l = i.decode().split(' "/" ')
print(l[0] + " = " + l[1])
def read_emails(self, mails_messages: list) -> list:
# create an IMAP4 class with SSL
if DOMAIN_163 in self.login:
imap = imaplib.IMAP4_SSL(IMAP_SERVER_163)
else:
imap = imaplib.IMAP4_SSL(AOL_IMAP_SERVER)
# authenticate
imap.login(self.login, self.password)
mail_list = []
print("read mails from {}".format(self.login))
# self.show_folders(imap)
# total number of emails
# get mails from inbox
# (\Archive \HasNoChildren) = "Archive"
# (\Junk \HasNoChildren) = "Bulk"
# (\Drafts \HasNoChildren) = "Draft"
# (\HasNoChildren) = "Inbox"
# (\Sent \HasNoChildren) = "Sent"
# (\Trash \HasNoChildren) = "Trash"
mail_list.extend(self._get_messages_from_folder(imap))
# mail_list.extend(self._get_messages_from_folder(imap, folder="Bulk"))
# close the connection and logout
imap.close()
imap.logout()
mails_messages.extend(mail_list)
return mail_list
def _get_messages_from_folder(self, imap, folder="INBOX") -> list:
imap.select(folder)
mail_messages = []
typ, data = imap.search(None, '(SUBJECT "{}" SINCE "{}")'.format(VALIDATION_URL_SUBJECT,
datetime.datetime.today().strftime(
date_format)))
for i in data[0].split():
# fetch the email message by ID
res, msg = imap.fetch(i.decode("utf-8"), "(RFC822)")
body = ''
for response in msg:
if isinstance(response, tuple):
# parse a bytes email into a message object
msg = email.message_from_bytes(response[1])
# decode the email subject
subject, subject_encoded = decode_header(msg["Subject"])[0]
received_date = msg["Date"]
if isinstance(subject, bytes):
# if it's a bytes, decode to str
subject = subject.decode(subject_encoded)
# decode email sender
from_address, subject_encoded = decode_header(msg.get("From"))[0]
if isinstance(from_address, bytes):
from_address = from_address.decode(subject_encoded)
print("From:", from_address)
print("Subject:", subject)
# if the email message is multipart
if msg.is_multipart():
# iterate over email parts
for part in msg.walk():
try:
# get the email body
payloads = part.get_payload()
if isinstance(payloads, list):
for payload in payloads:
if isinstance(payload, Message):
body = body + payload.get_payload(decode=True).decode("iso-8859-1")
# print(body)
except Exception as Error:
print(Error)
else:
body = msg.get_payload(decode=True).decode()
print(body)
if VALIDATION_URL_SUBJECT in subject:
mail = MailPojo(subject=subject, body=body, from_address=from_address)
mail_messages.append(mail)
return mail_messages
def clean(text):
# clean text for creating a folder
return "".join(c if c.isalnum() else "_" for c in text)
def need_to_valid_url(url: str, successful_items) -> bool:
print("url is :" + url)
parts = url.split('/')
id = parts[5]
if len(id) == 6:
for item in successful_items:
# if item.url_validated is not None:
# print("id:{}, status:{} ".format(id, str(item.url_validated)))
if item.id == id:
if item.url_validated is not None:
return not item.url_validated
else:
# if url_validated is None
return True
# return True by default
return False
else:
print("id not valid:{}".format(id))
return False
def read_mails():
# get email address
mail_list = MONGO_STORE_MANAGER.get_destination_emails()
# # mail_address1 = MailAddress(mail="appointment2022@aol.com", password="gyilpmvyyvlcaviq")
# # mail_address2 = MailAddress(mail="chenpeijun@aol.com", password="ytifuwguknzifqyb")
# # mail_address2 = MailAddress(mail="sdfgfhgf1986@aol.com", password="fjwcgvhxxlywqfwm")
# # mail_address3 = MailAddress(mail="ciyuexie@aol.com", password="czezlmmyypokdfce")
# # mail_address4 = MailAddress(mail="hongjiang176@aol.com", password="ftzpscgzvwneelmn")
# mail_address4 = MailAddress(mail="ribka_puchkova@aol.com", password="aqvsozoyifbixtdc")
# mail_list = [mail_address3, mail_address2, mail_address1, mail_address4]
# mail_list = [mail_address4]
successful_items = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
mails_messages = []
with ThreadPoolExecutor(max_workers=20) as executor:
for mail in mail_list:
mail_reader = MailReader(mail.mail, mail.password)
executor.submit(mail_reader.read_emails, mails_messages)
with ThreadPoolExecutor(max_workers=20) as executor:
for mail in mails_messages:
match = re.search(VALIDATION_URL_REGEX, mail.body)
if match:
url = match.group(0)
if need_to_valid_url(url, successful_items):
url_validator = LinkValidator(url)
print("need to validate url: " + url)
executor.submit(url_validator.start_page, params.get_proxy(ProxyType.BRIGHT_DATA), False)
else:
print("do not need to click url --> {}".format(mail.mail_address))
# check whether the url has already been clicked
if __name__ == '__main__':
read_mails()
import datetime
import email
import imaplib
import re
from concurrent.futures import ThreadPoolExecutor
from email.header import decode_header
from email.message import Message
from builtins import list
from src import params
from src.db.mongo_manager import MONGO_STORE_MANAGER
from src.pojo.mail.mail_pojo import MailPojo
from src.proxy.proxy_type import ProxyType
from src.workers.link_validator import LinkValidator
AOL_IMAP_SERVER = "imap.aol.com"
IMAP_SERVER_163 = "imap.163.com"
VALIDATION_URL_SUBJECT = 'Validation de votre demande de rendez-vous'
VALIDATION_URL_REGEX = """https:\/\/rendezvousparis.hermes.com\/client\/register\/[A-Z0-9]+\/validate.code=[A-Z0-9]+"""
HERMES_EMAIL = "no-reply@hermes.com"
DOMAIN_163 = "163.com"
date_format = "%d-%b-%Y" # DD-Mon-YYYY e.g., 3-Mar-2014
class MailReader():
def __init__(self, login, password):
self.login = login
self.password = password
@staticmethod
def show_folders(imap):
for i in imap.list()[1]:
l = i.decode().split(' "/" ')
print(l[0] + " = " + l[1])
def read_emails(self, mails_messages: list) -> list:
# create an IMAP4 class with SSL
if DOMAIN_163 in self.login:
imap = imaplib.IMAP4_SSL(IMAP_SERVER_163)
else:
imap = imaplib.IMAP4_SSL(AOL_IMAP_SERVER)
# authenticate
imap.login(self.login, self.password)
mail_list = []
print("read mails from {}".format(self.login))
# self.show_folders(imap)
# total number of emails
# get mails from inbox
# (\Archive \HasNoChildren) = "Archive"
# (\Junk \HasNoChildren) = "Bulk"
# (\Drafts \HasNoChildren) = "Draft"
# (\HasNoChildren) = "Inbox"
# (\Sent \HasNoChildren) = "Sent"
# (\Trash \HasNoChildren) = "Trash"
mail_list.extend(self._get_messages_from_folder(imap))
# mail_list.extend(self._get_messages_from_folder(imap, folder="Bulk"))
# close the connection and logout
imap.close()
imap.logout()
mails_messages.extend(mail_list)
return mail_list
def _get_messages_from_folder(self, imap, folder="INBOX") -> list:
imap.select(folder)
mail_messages = []
typ, data = imap.search(None, '(SUBJECT "{}" SINCE "{}")'.format(VALIDATION_URL_SUBJECT,
datetime.datetime.today().strftime(
date_format)))
for i in data[0].split():
# fetch the email message by ID
res, msg = imap.fetch(i.decode("utf-8"), "(RFC822)")
body = ''
for response in msg:
if isinstance(response, tuple):
# parse a bytes email into a message object
msg = email.message_from_bytes(response[1])
# decode the email subject
subject, subject_encoded = decode_header(msg["Subject"])[0]
received_date = msg["Date"]
if isinstance(subject, bytes):
# if it's a bytes, decode to str
subject = subject.decode(subject_encoded)
# decode email sender
from_address, subject_encoded = decode_header(msg.get("From"))[0]
if isinstance(from_address, bytes):
from_address = from_address.decode(subject_encoded)
print("From:", from_address)
print("Subject:", subject)
# if the email message is multipart
if msg.is_multipart():
# iterate over email parts
for part in msg.walk():
try:
# get the email body
payloads = part.get_payload()
if isinstance(payloads, list):
for payload in payloads:
if isinstance(payload, Message):
body = body + payload.get_payload(decode=True).decode("iso-8859-1")
# print(body)
except Exception as Error:
print(Error)
else:
body = msg.get_payload(decode=True).decode()
print(body)
if VALIDATION_URL_SUBJECT in subject:
mail = MailPojo(subject=subject, body=body, from_address=from_address)
mail_messages.append(mail)
return mail_messages
def clean(text):
# clean text for creating a folder
return "".join(c if c.isalnum() else "_" for c in text)
def need_to_valid_url(url: str, successful_items) -> bool:
print("url is :" + url)
parts = url.split('/')
id = parts[5]
if len(id) == 6:
for item in successful_items:
# if item.url_validated is not None:
# print("id:{}, status:{} ".format(id, str(item.url_validated)))
if item.id == id:
if item.url_validated is not None:
return not item.url_validated
else:
# if url_validated is None
return True
# return True by default
return False
else:
print("id not valid:{}".format(id))
return False
def read_mails():
# get email address
mail_list = MONGO_STORE_MANAGER.get_destination_emails()
# # mail_address1 = MailAddress(mail="appointment2022@aol.com", password="gyilpmvyyvlcaviq")
# # mail_address2 = MailAddress(mail="chenpeijun@aol.com", password="ytifuwguknzifqyb")
# # mail_address2 = MailAddress(mail="sdfgfhgf1986@aol.com", password="fjwcgvhxxlywqfwm")
# # mail_address3 = MailAddress(mail="ciyuexie@aol.com", password="czezlmmyypokdfce")
# # mail_address4 = MailAddress(mail="hongjiang176@aol.com", password="ftzpscgzvwneelmn")
# mail_address4 = MailAddress(mail="ribka_puchkova@aol.com", password="aqvsozoyifbixtdc")
# mail_list = [mail_address3, mail_address2, mail_address1, mail_address4]
# mail_list = [mail_address4]
successful_items = MONGO_STORE_MANAGER.get_all_successful_items_for_day()
mails_messages = []
with ThreadPoolExecutor(max_workers=20) as executor:
for mail in mail_list:
mail_reader = MailReader(mail.mail, mail.password)
executor.submit(mail_reader.read_emails, mails_messages)
with ThreadPoolExecutor(max_workers=20) as executor:
for mail in mails_messages:
match = re.search(VALIDATION_URL_REGEX, mail.body)
if match:
url = match.group(0)
if need_to_valid_url(url, successful_items):
url_validator = LinkValidator(url)
print("need to validate url: " + url)
executor.submit(url_validator.start_page, params.get_proxy(ProxyType.RESIDENTIAL), True)
else:
print("do not need to click url --> {}".format(mail.mail_address))
# check whether the url has already been clicked
if __name__ == '__main__':
read_mails()
+60 -259
View File
@@ -1,259 +1,60 @@
import random
import string
from src.logs.LogSender import LogSender
from src.proxy.proxy_type import ProxyType
oracle_log_sender = LogSender()
# proxy
PROXY_SERVER = "http://gw.ntnt.io:5959"
PROXY_PASSWORD = "94sY7zwBG13i"
BRIGHT_DATA_PROXY_SERVER = "http://zproxy.lum-superproxy.io:22225"
BRIGHT_DATA_PROXY_USERNAME = "lum-customer-c_daabba94-zone-residential-country-fr"
BRIGHT_DATA_MOBILE_PROXY_USERNAME = "lum-customer-c_daabba94-zone-mobile-country-fr-mobile"
BRIGHT_DATA_PROXY_PASSWORD = "9dwmh54u3bbh"
BRIGHT_DATA_MOBILE_PROXY_PASSWORD = "fk5f7c2z2c19"
PROXY_NAME_PREFIX_RES = "panleicim-res-fr-"
PROXY_NAME_PREFIX_CC = "panleicim-cc-fr-"
def get_proxy_name_prefix() -> str:
return PROXY_NAME_PREFIX_RES
def get_proxy(proxy_type: ProxyType):
if proxy_type == ProxyType.NETNUT:
random_id_number = get_random_id_number_for_proxy()
proxy_username = get_proxy_name_prefix() + random_id_number
proxy = {
"server": PROXY_SERVER,
"username": proxy_username,
"password": PROXY_PASSWORD
}
else:
proxy = {
"server": BRIGHT_DATA_PROXY_SERVER,
"username": BRIGHT_DATA_PROXY_USERNAME,
"password": BRIGHT_DATA_PROXY_PASSWORD
}
return proxy
def get_random_id_number_for_proxy() -> str:
S = 8 # number of characters in the string.
ran = ''.join(random.choices(string.digits, k=S))
id_number = str(ran)
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',
'iPhone 7 Plus landscape', 'iPhone 8', 'iPhone 8 landscape', 'iPhone 8 Plus', 'iPhone 8 Plus landscape',
'iPhone SE', 'iPhone SE landscape', 'iPhone X', 'iPhone X landscape', 'iPhone XR', 'iPhone XR landscape',
'iPhone 11', 'iPhone 11 landscape', 'iPhone 11 Pro', 'iPhone 11 Pro landscape', 'iPhone 11 Pro Max',
'iPhone 11 Pro Max landscape', 'iPhone 12', 'iPhone 12 landscape', 'iPhone 12 Pro',
'iPhone 12 Pro landscape', 'iPhone 12 Pro Max', 'iPhone 12 Pro Max landscape', 'iPhone 12 Mini', 'iPhone 13',
'iPhone 13 landscape', 'iPhone 13 Pro', 'iPhone 13 Pro landscape', 'iPhone 13 Pro Max', 'iPhone 13 Mini']
firefox_user_agent_list = [
'Mozilla/5.0 (Linux; Android 5.1.1; GT-I9100 Build/LMY48G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; m8 Build/LMY48B) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; GT-I9301I Build/LMY48G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G360T1 Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-N9005 Build/LMY48B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; S6 Build/G920TU) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.114 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; S6 Build/G920TU) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; D6653 Build/23.4.A.0.546) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; wx_un_do Build/LMY48G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; wx_un_do Build/LMY48G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; LGLS665 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; C2004 Build/LMY48G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G530T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; VS880 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-G900T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; LG-H634 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Spice Mi-498 Build/LMY48K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.89 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; C6603 Build/10.7.A.0.222) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; U; Android 5.1.1; en-us; SM-G360T1 Build/LMY47X) AppleWebKit/537.16 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.16',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-A800F Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.3 Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; MI 3W Build/LVY48F) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G360T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; GT-I9300 Build/LMY47Z) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-G928T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.4 Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; LG-H345 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G925W8-parrot Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2 Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-N9005 Build/LVY48F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-G530T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.3 Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-N920T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SGP511 Build/23.4.A.0.546) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920F Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Moto G Build/LVY48F; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36 bdbrowser/4.9.2.2',
'Mozilla/5.0 (Linux; Android 5.1.1; Moto G Build/LVY48F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; VS880 Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36/TansoDL',
'Mozilla/5.0 (Linux; Android 5.1.1; Moto G Build/LVY48F) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; U; Android 5.1.1; en-US; Nexus 4 Build/LMY48I) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 UCBrowser/10.7.0.636 U3/0.8.0 Mobile Safari/534.30',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-J500N0 Build/LMY48B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; loudnetgoCR18/13plus Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; loudnetgoCR18/13plus Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920F Build/LMY47X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/45.0.2454.87 Mobile Safari/537.36 BingWeb/5.5.25151058',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920K Build/LMY47X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36 NAVER(inapp; search; 390; 6.4.2)',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 4 Build/LMY48G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY48G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.89 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G530P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Moto G Build/LVY48F; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/45.0.2454.87 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Moto G Build/LMY48G; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; D6603 Build/23.4.A.0.546; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-N915P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G530R4 Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G925T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG-SM-N920A Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-T537V Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-N915P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920R4 Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920I Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Micromax AQ4501 Build/LMY48K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G928T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY48G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920F Build/LMY47X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-N920P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-N920T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-N915P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-N910P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-G920T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2 Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LMY48I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/45.0.2454.87 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920V Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 10 Build/LMY48M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 10 Build/LMY48I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; GT-I9300 Build/LMY47Z) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-G928T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.4 Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; LG-H345 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G925W8-parrot Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.2 Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-N9005 Build/LVY48F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-G530T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.3 Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-N920T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920F Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Moto G Build/LVY48F; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36 bdbrowser/4.9.2.2',
'Mozilla/5.0 (Linux; Android 5.1.1; Moto G Build/LVY48F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Moto G Build/LVY48F) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; U; Android 5.1.1; en-US; Nexus 4 Build/LMY48I) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 UCBrowser/10.7.0.636 U3/0.8.0 Mobile Safari/534.30',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-J500N0 Build/LMY48B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920F Build/LMY47X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/45.0.2454.87 Mobile Safari/537.36 BingWeb/5.5.25151058',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920K Build/LMY47X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36 NAVER(inapp; search; 390; 6.4.2)',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 4 Build/LMY48G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY48G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.89 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G530P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Moto G Build/LVY48F; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/45.0.2454.87 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Moto G Build/LMY48G; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-N915P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G530R4 Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G925T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG-SM-N920A Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-T537V Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2499.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; XT1526 Build/LPI29-18-S.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36',
'Mozilla/5.0 (Android 5.1.1; Mobile; rv:41.0) Gecko/41.0 Firefox/97.0.1',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 10 Build/LMY48I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; D6603 Build/23.4.A.0.546) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.89 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; HTC Desire 626s Build/LMY47O; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/42.0.2311.137 Mobile Safari/537.36 MinuteMaid',
'Mozilla/5.0 (Linux; Android 5.1; XT1528 Build/LPI29-17) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LMY48I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920T1 Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; m2 note Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.114 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 4 Build/LMY48I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 4 Build/LMY48I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/45.0.2454.87 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/44.0.0.26.142;]',
'Mozilla/5.0 (Linux; Android 5.1; LG-H815 Build/LMY47E) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; Nexus 6 Build/LMY47E; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; LGLS665 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; A0001 Build/LMY48B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G900T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; LG-H345 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-G360T1 Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.3 Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; LG-H631 Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; LG-H631 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; VS986 Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 9 Build/LMY47X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; A0001 Build/LMY48G) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; LG-D855 Build/LMY48G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; XT1096 Build/LPE23.32-25-3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-T710 Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 4 Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/44.0.0.26.142;]',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920V Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; Nexus 4 Build/LMY47O) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; XT1526 Build/LPI29-18-S.2; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; HTC One M9 Build/LMY47O) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-G360T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.3 Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; Android SDK built for Build/LKY45) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Crosswalk/15.44.384.6 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; D6503 Build/23.4.A.0.546) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; D6503 Build/23.4.A.0.546) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G925F Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920F Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G925V Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-T330NU Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; D6603 Build/23.4.A.0.546) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; LG-H811 Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; XT1526 Build/LPI29-18-S.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.78 Mobile Safari/537.36 OPR/30.0.1856.95530',
'Mozilla/5.0 (Linux; Android 5.1; XT1254 Build/SU3TL-39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-N910P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.1 Chrome/34.0.1847.76 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; GT-I9300 Build/LVY48C) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Xperia S Build/LVY48E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.78 Mobile Safari/537.36 OPR/30.0.1856.95530',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY48I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; D6503 Build/23.4.A.0.546) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.89 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; XT1528 Build/LPI29-17) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 9 Build/LMY48I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.89 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G925V Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; D6603 Build/23.4.A.0.570) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G928T Build/LMY47X; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.121 Mobile Safari/537.36 [Pinterest/Android]',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G900T1 Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; XT1254 Build/SU3TL-39; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36 Mobile/1 EtsyInc/4.20.0 Android/1',
'Mozilla/5.0 (Linux; Android 5.1; Nexus 5 Build/LMY47I) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.0.0 Mobile Safari/537.36; DailymotionEmbedSDK 1.0',
'Mozilla/5.0 (Linux; Android 5.1.1; D5803 Build/23.4.A.1.210) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Xperia Z1 Compact Build/LMY48G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; D6603 Build/23.4.A.0.570; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; U; Android 5.1.1; en-US; SM-E500H Build/LMY47X) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 UCBrowser/10.7.0.636 U3/0.8.0 Mobile Safari/534.30',
'Mozilla/5.0 (Linux; Android 5.1.1; LGLS665 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G925P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; ToughMobile Build/SDP3_3.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; Elephone P8000 Build/LMY47D) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Safari/537.36',
'Mozilla/5.0 (Linux; U; Android 5.1.1; en-us; SM-G360T1 Build/LMY47X) AppleWebKit/537.16 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.16',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-A800F Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.3 Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; MI 3W Build/LVY48F) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G360T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920P Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; GT-I9300 Build/LMY47Z) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-G928T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.4 Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.111 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; LG-H345 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G925W8-parrot Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/ Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-N9005 Build/LVY48F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-G530T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.3 Chrome/38.0.2125.102 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-N920T Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1; MotoE2(4G-LTE) Build/LPI29-18.5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.93 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SGP511 Build/23.4.A.0.546) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Nexus 7 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-G920F Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.93 Mobile Safari/537.36',
'Mozilla/5.0 (Linux; Android 5.1.1; Moto G Build/LVY48F; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/44.0.2403.117 Mobile Safari/537.36 bdbrowser/4.9.',
'Mozilla/5.0 (Linux; Android 5.1.1; SM-T537V Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.84 Safari/537.36']
import random
import string
from src.logs.LogSender import LogSender
from src.proxy.proxy_type import ProxyType
oracle_log_sender = LogSender()
# proxy
PROXY_SERVER = "http://gw.ntnt.io:5959"
PROXY_PASSWORD = "94sY7zwBG13i"
BRIGHT_DATA_PROXY_SERVER = "http://zproxy.lum-superproxy.io:22225"
BRIGHT_DATA_PROXY_USERNAME = "lum-customer-c_daabba94-zone-residential-country-fr"
BRIGHT_DATA_MOBILE_PROXY_USERNAME = "lum-customer-c_daabba94-zone-mobile-country-fr-mobile"
BRIGHT_DATA_PROXY_PASSWORD = "9dwmh54u3bbh"
BRIGHT_DATA_MOBILE_PROXY_PASSWORD = "fk5f7c2z2c19"
PROXY_NAME_PREFIX_RES = "panleicim-res-fr-"
PROXY_NAME_PREFIX_CC = "panleicim-cc-fr-"
def get_proxy_name_prefix() -> str:
return PROXY_NAME_PREFIX_RES
def get_proxy(proxy_type: ProxyType):
if proxy_type == ProxyType.RESIDENTIAL:
# random_id_number = get_random_id_number_for_proxy()
# proxy_username = get_proxy_name_prefix() + random_id_number
proxy = {
"server": BRIGHT_DATA_PROXY_SERVER,
"username": BRIGHT_DATA_PROXY_USERNAME,
"password": BRIGHT_DATA_PROXY_PASSWORD
}
else:
proxy = {
"server": BRIGHT_DATA_PROXY_SERVER,
"username": BRIGHT_DATA_MOBILE_PROXY_USERNAME,
"password": BRIGHT_DATA_MOBILE_PROXY_PASSWORD
}
return proxy
def get_random_id_number_for_proxy() -> str:
S = 8 # number of characters in the string.
ran = ''.join(random.choices(string.digits, k=S))
id_number = str(ran)
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',
'iPhone 7 Plus landscape', 'iPhone 8', 'iPhone 8 landscape', 'iPhone 8 Plus', 'iPhone 8 Plus landscape',
'iPhone SE', 'iPhone SE landscape', 'iPhone X', 'iPhone X landscape', 'iPhone XR', 'iPhone XR landscape',
'iPhone 11', 'iPhone 11 landscape', 'iPhone 11 Pro', 'iPhone 11 Pro landscape', 'iPhone 11 Pro Max',
'iPhone 11 Pro Max landscape', 'iPhone 12', 'iPhone 12 landscape', 'iPhone 12 Pro',
'iPhone 12 Pro landscape', 'iPhone 12 Pro Max', 'iPhone 12 Pro Max landscape', 'iPhone 12 Mini', 'iPhone 13',
'iPhone 13 landscape', 'iPhone 13 Pro', 'iPhone 13 Pro landscape', 'iPhone 13 Pro Max', 'iPhone 13 Mini']
+2 -2
View File
@@ -2,5 +2,5 @@ from enum import Enum
class ProxyType(Enum):
NETNUT = "NETNUT"
BRIGHT_DATA = "BRIGHT_DATA"
RESIDENTIAL = "RESIENTIAL"
MOBILE = "MOBILE"
+51 -38
View File
@@ -6,7 +6,9 @@ import wget
WAV_FILE_REGEX = "https:[\/a-z0-9.-]+.wav"
number_text_dict = {'eight': 8, 'zero': 0, 'one': 1, 'to': 2, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6,
number_text_dict = {'eight': 8, 'zero': 0, 'one': 1, 'won': 1, 'to': 2, 'two': 2, 'three': 3, 'four': 4, 'for': 4,
'five': 5,
'six': 6,
'seven': 7, 'nine': 9}
@@ -22,54 +24,65 @@ class GeoCaptchaSolver:
self.iframe = iframe
print(type(iframe))
print("url is " + iframe.url)
r = requests.get(iframe.url)
body = r.text
# r = requests.get(iframe.url)
audio_tag = iframe.query_selector('.audio-captcha-track').inner_html()
print("audio_tag " + audio_tag)
wav_url = self.get_wav_src()
print("src " + wav_url)
# body = r.text
# print(body)
match = re.search(WAV_FILE_REGEX, body)
if match:
wav_url = match.group(0)
print("wav file " + wav_url)
response = requests.get(wav_url)
file_name = wav_url.split("/")[-1]
wget.download(wav_url, file_name)
open(file_name, "wb").write(response.content)
r = sr.Recognizer()
with sr.AudioFile(file_name) as source:
audio = r.record(source) # read the entire audio file
# recognize speech using Sphinx
try:
text = r.recognize_sphinx(audio)
number_list = text.split(" ")[-6:]
print(number_list)
number_to_type = []
for number in number_list:
number_to_type.append(number_text_dict[number])
print(number_to_type)
if len(number_to_type) == 6:
self.input_numbers(number_to_type)
print("Sphinx thinks you said " + text)
except sr.UnknownValueError:
print("Sphinx could not understand audio")
except sr.RequestError as e:
print("Sphinx error; {0}".format(e))
else:
print("wav file not found")
# match = re.search(WAV_FILE_REGEX, body)
# if match:
# wav_url = match.group(0)
# print("wav file " + wav_url)
response = requests.get(wav_url)
file_name = wav_url.split("/")[-1]
wget.download(wav_url, file_name)
open(file_name, "wb").write(response.content)
r = sr.Recognizer()
with sr.AudioFile(file_name) as source:
audio = r.record(source) # read the entire audio file
# recognize speech using Sphinx
try:
text = r.recognize_sphinx(audio)
number_list = text.split(" ")[-6:]
print(number_list)
number_to_type = []
for number in number_list:
number_to_type.append(number_text_dict[number])
print(number_to_type)
if len(number_to_type) == 6:
self.input_numbers(number_to_type)
print("Sphinx thinks you said " + text)
except sr.UnknownValueError:
print("Sphinx could not understand audio")
except sr.RequestError as e:
print("Sphinx error; {0}".format(e))
def input_numbers(self, number_to_type):
# use javascript to input
self.input_by_js(number_to_type)
# input_elements = self.page.query_selector('.audio-captcha-inputs')
# print(input_elements)
# download file
def get_wav_src(self):
src = self.iframe.evaluate("""()=>{
return document.querySelector('.audio-captcha-track').src;
}
""")
return src
def input_by_js(self, number_to_type):
index = 0
# self.iframe.query_selector('.audio-captcha-inputs').evaluate(
#
# )
for number in number_to_type:
index = index + 1
(self.iframe.page).evaluate("""(info) =>{
(self.iframe).evaluate("""(info) =>{
let input_fileds = document.getElementsByClassName("audio-captcha-inputs");
console.log(input_fileds)
input_fileds[info.index].focus();
input_fileds[info.index].value = info.number;}
""", {'index': index, 'number': number})
index = index + 1
self.iframe.query_selector(".audio-captcha-verify-button").evaluate("""(btn)=>{
btn.click()};""")
+40 -47
View File
@@ -2,14 +2,14 @@ import datetime
import logging
import random
import re
import requests
import sys
import threading
import time
import traceback
from typing import Union
from playwright_stealth import stealth_sync
from src import params, definitions
from src.db.mongo_manager import MONGO_STORE_MANAGER
from src.pojo.ModeEnum import ModeEnum
@@ -26,6 +26,8 @@ RDV_URL = "https://rendezvousparis.hermes.com/client/register"
# RDV_URL = "https://api.ipify.org"
# RDV_URL ="https://bot.sannysoft.com/"
REGEX_RDV_URL = "https:\/\/rendezvousparis\.hermes\.com\/client\/register\/[A-Z0-9]+"
BLOCKED_MESSAGE_FR = "Pourquoi ce blocage"
BLOCKED_MESSAGE_EN = "You have been blocked"
otp_value = None
OTP_FIELD_ID = "#sms_code"
MESSAGE_FIELD_CLASS = ".message"
@@ -53,7 +55,7 @@ def get_random_wait_time() -> float:
class CommandorPage:
tls = TlsPlaywright()
def __init__(self, contact: ContactPojo, store_type=0, proxy_type=ProxyType.BRIGHT_DATA,
def __init__(self, contact: ContactPojo, store_type=0, proxy_type=ProxyType.RESIDENTIAL,
mode: ModeEnum = ModeEnum.MANUAL, headless=False):
self.otp_value = None
self.is_finished = False
@@ -97,6 +99,12 @@ class CommandorPage:
self.on_success_listener = on_success
# reset otp_value to None
self.otp_value = None
# ios_devices_keys = self.tls.playwright.devices.keys()
# ios_keys = []
# for key in ios_devices_keys:
# if "iPhone" in key or "iPad" in key:
# ios_keys.append(key)
# print(ios_keys)
devices = random.choice(params.DEVICES)
first_page = None
while first_page is None:
@@ -145,7 +153,6 @@ class CommandorPage:
def create_and_config_page(self, context):
self.page = context.new_page()
stealth_sync(self.page)
# hide webdriver information
self.page.add_init_script("""() => {
Object.defineProperty(navigator,'webdriver',{get: () => undefined});
@@ -171,36 +178,11 @@ class CommandorPage:
def solve_datadome_captcha(self):
print("solve_datadome_captcha")
solver = GeoCaptchaSolver(self.page)
# time.sleep(2)
# self._click_audio_btn()
# time.sleep(1)
self._click_audio_btn()
time.sleep(20)
solver = GeoCaptchaSolver(self.page)
solver.solve()
# solver = antigateTask()
# solver.set_verbose(1)
# solver.set_key("ede6a69396fc961af351e7c8ffda9059")
# solver.set_website_url(RDV_URL)
# solver.set_template_name("Anti-bot screen bypass")
# solver.set_variables({
# "css_selector": ".captcha__human__container"
# })
# result = solver.solve_and_return_solution()
# if result != 0:
# cookies, localStorage, fingerprint, url, domain = result["cookies"], result["localStorage"], result[
# "fingerprint"], result["url"], result["domain"]
# print("cookies: ", cookies)
# print("localStorage: ", localStorage)
# print("fingerprint: ", fingerprint)
# print("url: " + url)
# print("domain: " + domain)
# # add cookies to playwright
# cookie_list = []
# cookie_list.append(SetCookieParam(name='datadome', value=cookies['datadome'], url=url))
# self.page.context.add_cookies(cookie_list)
# self.config_page_with_fingerprint(fingerprint)
# self.page.reload()
# else:
# print("task finished with error " + solver.error_code)
def _on_page_loaded(self):
# time.sleep(40000)
@@ -218,6 +200,10 @@ class CommandorPage:
self.get_errors()
except Exception as error:
self.logger.error(error)
# else:
# if self.check_is_blocked():
# print("we are blocked")
# # self.termine()
else:
self.solve_datadome_captcha()
@@ -264,10 +250,15 @@ class CommandorPage:
def _click_audio_btn(self):
time.sleep(get_random_wait_time())
self.page.evaluate("""{
let surname = document.getElementById('captcha__audio__button');
surname.click();}
""")
iframe = self.page.query_selector('iframe').content_frame()
iframe.query_selector('#captcha__audio__button').click()
time.sleep(2)
iframe.query_selector('.audio-captcha-play-button').evaluate("""(btn)=>{btn.click()}""")
# self.page.evaluate("""{
# let surname = document.getElementById('captcha__audio__button');
# surname.click();}
# """)
def get_errors(self):
# send error result
@@ -406,16 +397,18 @@ class CommandorPage:
MONGO_STORE_MANAGER.insert_captcha_error_contact(self.contact)
params.oracle_log_sender.send_captcha_error(self.contact)
def config_page_with_fingerprint(self, fingerprint):
self.page.add_init_script("""() => {
Object.defineProperty(navigator,'webdriver',{get: () => undefined});
Object.defineProperty(navigator, 'platform', {
get: () => {
return "iPhone";
}});
}
""")
def check_is_blocked(self) -> bool:
iframe = self.page.query_selector('iframe').content_frame()
self.iframe = iframe
print(type(iframe))
print("url is " + iframe.url)
r = requests.get(iframe.url)
body = r.text
# print("iframe content is " + body)
if BLOCKED_MESSAGE_FR in body or BLOCKED_MESSAGE_EN in body:
return True
else:
return False
def on_success(result: ReserveResultPojo):
@@ -427,7 +420,7 @@ def launch_page():
first_name="xingzhen",
mail="ColbyPatel653@gmail.com", ccid="", position=0)
page = CommandorPage(contact, store_type=1)
return page.start_page(params.get_proxy(ProxyType.BRIGHT_DATA))
return page.start_page(params.get_proxy(ProxyType.RESIDENTIAL))
def wait_for_otp(event: threading.Event, commandor: CommandorPage):
+135 -135
View File
@@ -1,135 +1,135 @@
import logging
import random
import traceback
from typing import Union
import sys
import time
from src import params
from src.db.mongo_manager import MONGO_STORE_MANAGER
from src.pojo.ReserveResultPojo import PublishType
from src.proxy.proxy_type import ProxyType
from src.workers.TlsPlaywright import TlsPlaywright
OTP_FIELD_ID = "#sms_code"
TIME_OUT = 10 * 60 * 1000 # 10 mins
PAGE_TIMEOUT = 40000
CONFIRMED_MESSAGE_FR = "Votre demande de rendez-vous Maroquinerie a bien été enregistrée et nous vous en remercions."
SORRY_SENTENCE_FR = "nous sommes sincèrement désolés de n'avoir pu vous satisfaire cette fois-ci"
DOUBLE_REQUEST_ERROR_MESSAGE_FR = "Une demande avec les données saisies a déjà été validée aujourdhui."
class LinkValidator:
tls = TlsPlaywright()
def __init__(self, link: str, proxy_type=ProxyType.BRIGHT_DATA, headless=False):
self.is_finished = False
self.link = link
self.proxy_type = proxy_type
self.is_event_sent = False
self.is_captcha_in_error = False
self.is_filling_fields = False
self.headless = headless
self.logger = logging.getLogger("LinkValidator")
def on_success(self):
self.logger.info("on_success called.")
self.is_finished = True
if not self.is_event_sent:
self.logger.info("will send successful event")
params.oracle_log_sender.send_url_validation_result()
self.is_event_sent = True
def timeout_occurred(self):
params.oracle_log_sender.send_timeout_log(self.link)
self.logger.info("will close timeout modem")
self.termine()
def _run(self, proxy):
self.logger.info("will start browser")
# reset otp_value to None
devices = random.choice(params.DEVICES)
first_page = None
while first_page is None:
first_page = self.start_browser(proxy, self.tls.playwright, devices)
proxy = params.get_proxy(self.proxy_type)
otp_input = self.page.locator(OTP_FIELD_ID)
otp_input.wait_for(state='visible', timeout=TIME_OUT)
self.logger.info("timeout")
self.termine()
def start_browser(self, proxy, pwright, device) -> Union[str, None]:
try:
self.browser = pwright.webkit.launch(headless=self.headless, timeout=PAGE_TIMEOUT, proxy=proxy)
self.logger.info("模拟设备: " + device)
simulated_mobile = pwright.devices[device]
context = self.browser.new_context(**simulated_mobile, locale='fr-FR')
self.page = context.new_page()
# hide webdriver information
self.page.add_init_script("""() => {
Object.defineProperty(navigator,'webdriver',{get: () => undefined});
Object.defineProperty(navigator, 'platform', {
get: () => {
return "iPhone";
}});
}
""")
self.page.on("load", self._on_page_loaded)
self.page.goto(self.link, timeout=PAGE_TIMEOUT)
captcha_url = "geo.captcha-delivery.com/captcha"
if captcha_url in self.page.content():
self.logger.info("will close browser")
self.browser.close()
return None
else:
return self.page.content()
except Exception as error:
params.oracle_log_sender.send_error(str(error))
traceback.print_exc(*sys.exc_info())
self.logger.exception(error)
self.logger.info("will close browser")
self.browser.close()
return None
def start_page(self, proxy, headless=False):
self.headless = headless
self._run(proxy)
def _on_page_loaded(self):
self.logger.info("页面加载完毕")
self.logger.info("url is " + self.page.url)
try:
message = self.page.content()
if CONFIRMED_MESSAGE_FR in message:
# publish the successful message
self.publish_message_to_queue(PublishType.SUCCESS)
elif SORRY_SENTENCE_FR in message:
# publish the successful message
self.publish_message_to_queue(PublishType.SUCCESS)
elif DOUBLE_REQUEST_ERROR_MESSAGE_FR in message:
# publish the successful message
self.publish_message_to_queue(PublishType.DUPLICATED)
except Exception as error:
self.logger.error(error)
def on_document_loaded(self):
self.logger.info("on_document_loaded called")
def _handle_errors(self, erro_content: str):
pass
def termine(self):
self.logger.info("will close browser")
time.sleep(1)
self.browser.close()
def publish_message_to_queue(self, status: PublishType):
# create the message
if status is PublishType.SUCCESS:
MONGO_STORE_MANAGER.link_validated_for_result(self.page.url)
else:
MONGO_STORE_MANAGER.link_validated_for_result(self.page.url, state=status.name)
self.on_success()
time.sleep(2)
self.browser.close()
import logging
import random
import traceback
from typing import Union
import sys
import time
from src import params
from src.db.mongo_manager import MONGO_STORE_MANAGER
from src.pojo.ReserveResultPojo import PublishType
from src.proxy.proxy_type import ProxyType
from src.workers.TlsPlaywright import TlsPlaywright
OTP_FIELD_ID = "#sms_code"
TIME_OUT = 10 * 60 * 1000 # 10 mins
PAGE_TIMEOUT = 40000
CONFIRMED_MESSAGE_FR = "Votre demande de rendez-vous Maroquinerie a bien été enregistrée et nous vous en remercions."
SORRY_SENTENCE_FR = "nous sommes sincèrement désolés de n'avoir pu vous satisfaire cette fois-ci"
DOUBLE_REQUEST_ERROR_MESSAGE_FR = "Une demande avec les données saisies a déjà été validée aujourdhui."
class LinkValidator:
tls = TlsPlaywright()
def __init__(self, link: str, proxy_type=ProxyType.RESIDENTIAL, headless=False):
self.is_finished = False
self.link = link
self.proxy_type = proxy_type
self.is_event_sent = False
self.is_captcha_in_error = False
self.is_filling_fields = False
self.headless = headless
self.logger = logging.getLogger("LinkValidator")
def on_success(self):
self.logger.info("on_success called.")
self.is_finished = True
if not self.is_event_sent:
self.logger.info("will send successful event")
params.oracle_log_sender.send_url_validation_result()
self.is_event_sent = True
def timeout_occurred(self):
params.oracle_log_sender.send_timeout_log(self.link)
self.logger.info("will close timeout modem")
self.termine()
def _run(self, proxy):
self.logger.info("will start browser")
# reset otp_value to None
devices = random.choice(params.DEVICES)
first_page = None
while first_page is None:
first_page = self.start_browser(proxy, self.tls.playwright, devices)
proxy = params.get_proxy(self.proxy_type)
otp_input = self.page.locator(OTP_FIELD_ID)
otp_input.wait_for(state='visible', timeout=TIME_OUT)
self.logger.info("timeout")
self.termine()
def start_browser(self, proxy, pwright, device) -> Union[str, None]:
try:
self.browser = pwright.webkit.launch(headless=self.headless, timeout=PAGE_TIMEOUT, proxy=proxy)
self.logger.info("模拟设备: " + device)
simulated_mobile = pwright.devices[device]
context = self.browser.new_context(**simulated_mobile, locale='fr-FR')
self.page = context.new_page()
# hide webdriver information
self.page.add_init_script("""() => {
Object.defineProperty(navigator,'webdriver',{get: () => undefined});
Object.defineProperty(navigator, 'platform', {
get: () => {
return "iPhone";
}});
}
""")
self.page.on("load", self._on_page_loaded)
self.page.goto(self.link, timeout=PAGE_TIMEOUT)
captcha_url = "geo.captcha-delivery.com/captcha"
if captcha_url in self.page.content():
self.logger.info("will close browser")
self.browser.close()
return None
else:
return self.page.content()
except Exception as error:
params.oracle_log_sender.send_error(str(error))
traceback.print_exc(*sys.exc_info())
self.logger.exception(error)
self.logger.info("will close browser")
self.browser.close()
return None
def start_page(self, proxy, headless=False):
self.headless = headless
self._run(proxy)
def _on_page_loaded(self):
self.logger.info("页面加载完毕")
self.logger.info("url is " + self.page.url)
try:
message = self.page.content()
if CONFIRMED_MESSAGE_FR in message:
# publish the successful message
self.publish_message_to_queue(PublishType.SUCCESS)
elif SORRY_SENTENCE_FR in message:
# publish the successful message
self.publish_message_to_queue(PublishType.SUCCESS)
elif DOUBLE_REQUEST_ERROR_MESSAGE_FR in message:
# publish the successful message
self.publish_message_to_queue(PublishType.DUPLICATED)
except Exception as error:
self.logger.error(error)
def on_document_loaded(self):
self.logger.info("on_document_loaded called")
def _handle_errors(self, erro_content: str):
pass
def termine(self):
self.logger.info("will close browser")
time.sleep(1)
self.browser.close()
def publish_message_to_queue(self, status: PublishType):
# create the message
if status is PublishType.SUCCESS:
MONGO_STORE_MANAGER.link_validated_for_result(self.page.url)
else:
MONGO_STORE_MANAGER.link_validated_for_result(self.page.url, state=status.name)
self.on_success()
time.sleep(2)
self.browser.close()