0.1.7
This commit is contained in:
139
spider/111.py
Normal file
139
spider/111.py
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
from math import log
|
||||||
|
import random
|
||||||
|
from re import S
|
||||||
|
import time
|
||||||
|
from tkinter import N
|
||||||
|
from DrissionPage import Chromium
|
||||||
|
from loguru import logger
|
||||||
|
from work import get_random_canada_info
|
||||||
|
from mail_ import mail_
|
||||||
|
from bit_browser import bit_browser
|
||||||
|
from api import api
|
||||||
|
|
||||||
|
|
||||||
|
class Auto:
|
||||||
|
def __init__(self, http: str = None):
|
||||||
|
self.browser = Chromium(http)
|
||||||
|
self.tab = self.browser.latest_tab
|
||||||
|
pass
|
||||||
|
|
||||||
|
# cf打码
|
||||||
|
def solve_cloudflare(self, is_ok: bool = False):
|
||||||
|
tab = self.browser.latest_tab
|
||||||
|
for _ in range(5):
|
||||||
|
tab.wait(1)
|
||||||
|
res = tab.ele(
|
||||||
|
't:h1@text()=Sorry, you have been blocked', timeout=1)
|
||||||
|
if res:
|
||||||
|
logger.error("Cloudflare验证失败")
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
shadow1 = tab.ele(
|
||||||
|
'x://*[@name="cf-turnstile-response"]').parent().shadow_root
|
||||||
|
iframe = shadow1.get_frame(1)
|
||||||
|
if iframe:
|
||||||
|
logger.debug("找到Cloudflare iframe")
|
||||||
|
shadow2 = iframe.ele('x:/html/body').shadow_root
|
||||||
|
if shadow2:
|
||||||
|
logger.debug("找到Cloudflare iframe body shadow root")
|
||||||
|
status = shadow2.ele(
|
||||||
|
'x://span[text()="Verifying..."]', timeout=1.5)
|
||||||
|
if status:
|
||||||
|
logger.debug("Cloudflare验证中,等待3秒")
|
||||||
|
tab.wait(3)
|
||||||
|
status = shadow2.ele(
|
||||||
|
'x://span[text()="Success!"]', timeout=1.5)
|
||||||
|
if status:
|
||||||
|
logger.debug("Cloudflare验证成功")
|
||||||
|
return True
|
||||||
|
checkbox = shadow2.ele(
|
||||||
|
'x://input[@type="checkbox"]', timeout=1.5)
|
||||||
|
if checkbox:
|
||||||
|
logger.debug("点击Cloudflare复选框")
|
||||||
|
checkbox.click()
|
||||||
|
tab.wait(3)
|
||||||
|
logger.debug("重新获取状态")
|
||||||
|
# return False
|
||||||
|
except Exception as e:
|
||||||
|
# logger.error(f"处理Cloudflare异常: {e}")
|
||||||
|
if is_ok:
|
||||||
|
logger.debug(f"cloudflare处理通过: {e}")
|
||||||
|
return True
|
||||||
|
return self.solve_cloudflare(is_ok=True)
|
||||||
|
tab.wait(1)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def wait_home(self):
|
||||||
|
logger.debug("等待进入首页")
|
||||||
|
jc = 0
|
||||||
|
while True:
|
||||||
|
if jc > 3:
|
||||||
|
logger.error("等待进入首页超过5次,未成功")
|
||||||
|
return False
|
||||||
|
self.tab.wait(1)
|
||||||
|
# 判断cf是否通过
|
||||||
|
bol = self.solve_cloudflare()
|
||||||
|
if not bol:
|
||||||
|
logger.debug("Cloudflare验证失败.")
|
||||||
|
# 刷新网页
|
||||||
|
self.tab.refresh()
|
||||||
|
self.tab.wait(1.5)
|
||||||
|
jc += 1
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
logger.debug("Cloudflare验证成功.")
|
||||||
|
self.tab.wait(1.5)
|
||||||
|
bol = self.tab.ele(
|
||||||
|
't:h1@text()=Sorry, you have been blocked', timeout=1)
|
||||||
|
if bol:
|
||||||
|
logger.debug("ip被ban秒")
|
||||||
|
return False
|
||||||
|
|
||||||
|
bol = self.tab.ele(
|
||||||
|
't:div@text():ERR_TIMED_OUT', timeout=1)
|
||||||
|
if bol:
|
||||||
|
logger.debug("刷新网页")
|
||||||
|
self.tab.refresh()
|
||||||
|
self.tab.wait(1.5)
|
||||||
|
bol = self.tab.ele(
|
||||||
|
't:div@text():ERR_SSL_PROTOCOL_ERROR', timeout=1)
|
||||||
|
if bol:
|
||||||
|
logger.debug("刷新网页")
|
||||||
|
self.tab.refresh()
|
||||||
|
self.tab.wait(1.5)
|
||||||
|
bol = self.tab.ele(
|
||||||
|
't:div@text():ERR_SOCKS_CONNECTION_FAILED', timeout=1)
|
||||||
|
if bol:
|
||||||
|
logger.debug("刷新网页")
|
||||||
|
self.tab.refresh()
|
||||||
|
self.tab.wait(1.5)
|
||||||
|
html = self.tab.url
|
||||||
|
logger.debug(f"当前URL: {html}")
|
||||||
|
if 'https://veritaconnect.ca/canadianbreadsettlement/en-us' == html:
|
||||||
|
logger.debug("成功进入首页")
|
||||||
|
return True
|
||||||
|
jc += 1
|
||||||
|
|
||||||
|
def open_url(self, url: str):
|
||||||
|
self.tab.get(url)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
browser_id = bit_browser.bit_browser_create(
|
||||||
|
remark=f"us.novproxy.io:1000:ozua8623-region-CA-st-Ontario-city-Toronto:6wdcv4gq",
|
||||||
|
host="us.novproxy.io",
|
||||||
|
port=1000,
|
||||||
|
proxy_user="ozua8623-region-CA-st-Alberta-city-Calgary",
|
||||||
|
proxy_pwd="6wdcv4gq",
|
||||||
|
proxy_type='socks5'
|
||||||
|
)
|
||||||
|
http = bit_browser.bit_browser_open(browser_id)
|
||||||
|
logger.debug(f"打开浏览器 {browser_id}, http: {http}")
|
||||||
|
auto = Auto(http)
|
||||||
|
auto.open_url(
|
||||||
|
"https://veritaconnect.ca/canadianbreadsettlement/en-us/Claimant/UnknownClaimForm")
|
||||||
|
auto.wait_home()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -196,12 +196,13 @@ class BitBrowser:
|
|||||||
url = f"{self.bit_host}:{bit_port}/browser/close"
|
url = f"{self.bit_host}:{bit_port}/browser/close"
|
||||||
headers = {'Content-Type': 'application/json'}
|
headers = {'Content-Type': 'application/json'}
|
||||||
data = {'id': f'{pk}'}
|
data = {'id': f'{pk}'}
|
||||||
requests.post(url, json=data, headers=headers).json()
|
res = requests.post(url, json=data, headers=headers).json()
|
||||||
time.sleep(5) # 等待5s,等待浏览器关闭
|
if not res.get('success'):
|
||||||
# 关闭浏览器进程
|
raise Exception(res)
|
||||||
# pid = self.bit_browser_pid(pk, bit_port)
|
bol = self.bit_browser_status(pk)
|
||||||
# if pid is not None:
|
if bol:
|
||||||
# os.system(f"kill -9 {pid}")
|
raise Exception(f'浏览器ID {pk} 未正常关闭')
|
||||||
|
return True
|
||||||
|
|
||||||
# 删除比特币浏览器
|
# 删除比特币浏览器
|
||||||
@retry(max_retries=3, delay=1.0, backoff=1.0)
|
@retry(max_retries=3, delay=1.0, backoff=1.0)
|
||||||
@@ -215,7 +216,10 @@ class BitBrowser:
|
|||||||
url = f"{self.bit_host}:{bit_port}/browser/delete"
|
url = f"{self.bit_host}:{bit_port}/browser/delete"
|
||||||
headers = {'Content-Type': 'application/json'}
|
headers = {'Content-Type': 'application/json'}
|
||||||
data = {'id': f'{pk}'}
|
data = {'id': f'{pk}'}
|
||||||
print(requests.post(url, json=data, headers=headers).json())
|
res = requests.post(url, json=data, headers=headers).json()
|
||||||
|
if not res.get('success'):
|
||||||
|
raise Exception(res)
|
||||||
|
return True
|
||||||
|
|
||||||
# 获取所有比特币浏览器
|
# 获取所有比特币浏览器
|
||||||
@retry(max_retries=3, delay=1.0, backoff=1.0)
|
@retry(max_retries=3, delay=1.0, backoff=1.0)
|
||||||
@@ -275,209 +279,26 @@ class BitBrowser:
|
|||||||
raise Exception(res)
|
raise Exception(res)
|
||||||
return res['data'][pk]
|
return res['data'][pk]
|
||||||
|
|
||||||
@staticmethod
|
# 获取窗口状态
|
||||||
async def __request(method: str, url: str, params: dict = None, **kwargs) -> dict:
|
@retry(max_retries=3, delay=1.0, backoff=1.0)
|
||||||
|
def bit_browser_status(self, pk: str, bit_port: str = "54345") -> dict:
|
||||||
"""
|
"""
|
||||||
通用异步请求方法
|
获取比特浏览器窗口状态
|
||||||
:param method: HTTP方法 (GET, POST, PUT, DELETE)
|
|
||||||
:param endpoint: API接口地址
|
|
||||||
:param kwargs: 其他请求参数 (json, params等)
|
|
||||||
:return: 返回JSON数据
|
|
||||||
"""
|
|
||||||
if params:
|
|
||||||
# 将布尔值转换为字符串或整数
|
|
||||||
params = {k: str(v).lower() if isinstance(v, bool) else v for k, v in params.items()}
|
|
||||||
async with aiohttp.ClientSession() as session:
|
|
||||||
async with session.request(method, url, params=params, **kwargs) as response:
|
|
||||||
return await response.json()
|
|
||||||
|
|
||||||
# 创建比特币浏览器
|
|
||||||
@async_retry(max_retries=3, delay=1.0, backoff=1.0)
|
|
||||||
async def _bit_browser_create(self, remark: str = '指纹浏览器', ua: str = None, host: str = None, port: str = None,
|
|
||||||
proxy_user: str = None,
|
|
||||||
proxy_pwd: str = None, proxy_type: str = 'noproxy', urls: str = None,
|
|
||||||
bit_port: str = "54345") -> str:
|
|
||||||
"""
|
|
||||||
创建比特币浏览器
|
|
||||||
:param urls: 额外打开的url (可选) 多个用,分割
|
|
||||||
:param remark: 备注 (可选)
|
|
||||||
:param bit_port: 可选,默认54345
|
|
||||||
:return: 返回浏览器ID
|
|
||||||
"""
|
|
||||||
url = f"{self.bit_host}:{bit_port}/browser/update"
|
|
||||||
headers = {'Content-Type': 'application/json'}
|
|
||||||
data = {
|
|
||||||
'name': f'{remark if len(remark) < 40 else remark[:40]}', # 窗口名称
|
|
||||||
'remark': f'{remark}', # 备注
|
|
||||||
'proxyType': f'{proxy_type}',
|
|
||||||
"browserFingerPrint": {"userAgent": ua} # 留空,随机指纹
|
|
||||||
}
|
|
||||||
if host is not None:
|
|
||||||
data['host'] = host
|
|
||||||
if port is not None:
|
|
||||||
data['port'] = port
|
|
||||||
if proxy_user is not None:
|
|
||||||
data['proxyUserName'] = proxy_user
|
|
||||||
if proxy_pwd is not None:
|
|
||||||
data['proxyPassword'] = proxy_pwd
|
|
||||||
if urls is not None:
|
|
||||||
data['url'] = urls # 额外打开的url 多个用,分割
|
|
||||||
res = await self.__request('POST', url, json=data, headers=headers)
|
|
||||||
if not res.get('success'):
|
|
||||||
raise Exception(res)
|
|
||||||
browser_pk = res['data']['id']
|
|
||||||
return browser_pk
|
|
||||||
|
|
||||||
# 修改比特币浏览器
|
|
||||||
@async_retry(max_retries=3, delay=1.0, backoff=1.0)
|
|
||||||
async def _bit_browser_update(self, pk: str, remark: str = None, proxyType: str = 'noproxy', host: str = None,
|
|
||||||
port: str = None, proxy_user: str = None, proxy_pwd: str = None, urls: str = None,
|
|
||||||
bit_port: str = "54345") -> bool:
|
|
||||||
"""
|
|
||||||
修改比特币浏览器 传入某个参数则修改某个参数
|
|
||||||
:param pk: # 浏览器ID
|
|
||||||
:param remark: # 备注
|
|
||||||
:param urls: # 额外打开的url 多个用,分割
|
|
||||||
:param bit_port: # 可选,默认54345
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
url = f"{self.bit_host}:{bit_port}/browser/update/partial"
|
|
||||||
headers = {'Content-Type': 'application/json'}
|
|
||||||
data = dict()
|
|
||||||
data['ids'] = [pk]
|
|
||||||
if remark is not None:
|
|
||||||
data['remark'] = remark
|
|
||||||
data['name'] = remark
|
|
||||||
if urls is not None:
|
|
||||||
data['url'] = urls
|
|
||||||
if proxyType != 'noproxy':
|
|
||||||
data['proxyType'] = proxyType
|
|
||||||
if host is not None:
|
|
||||||
data['host'] = host
|
|
||||||
if port is not None:
|
|
||||||
data['port'] = port if isinstance(port, int) else int(port)
|
|
||||||
if proxy_user is not None:
|
|
||||||
data['proxyUserName'] = proxy_user
|
|
||||||
if proxy_pwd is not None:
|
|
||||||
data['proxyPassword'] = proxy_pwd
|
|
||||||
res = await self.__request('POST', url, json=data, headers=headers)
|
|
||||||
if not res.get('success'):
|
|
||||||
raise Exception(res)
|
|
||||||
return True
|
|
||||||
|
|
||||||
# 打开比特币浏览器
|
|
||||||
@async_retry(max_retries=3, delay=1.0, backoff=1.0)
|
|
||||||
async def _bit_browser_open(self, pk: str, bit_port: str = "54345") -> str:
|
|
||||||
"""
|
|
||||||
打开比特币浏览器
|
|
||||||
:param pk: 浏览器ID
|
:param pk: 浏览器ID
|
||||||
:param bit_port: 可选,默认54345
|
:param bit_port: 可选,默认54345
|
||||||
:return: 返回浏览器地址
|
:return: {'success': True, 'data': {'id': '12a3126accc14c93bd34adcccfc3083c', 'name': '12a3126accc14c93bd34adcccfc3083c', 'remark': '12a3126accc14c93bd34adcccfc3083c', '
|
||||||
"""
|
"""
|
||||||
url = f"{self.bit_host}:{bit_port}/browser/open"
|
url = f"{self.bit_host}:{bit_port}/browser/pids"
|
||||||
data = {"id": f'{pk}'}
|
|
||||||
headers = {'Content-Type': 'application/json'}
|
headers = {'Content-Type': 'application/json'}
|
||||||
res = await self.__request('POST', url, json=data, headers=headers)
|
data = {'ids': [pk]}
|
||||||
|
res = requests.post(url, json=data, headers=headers).json()
|
||||||
|
# print(f'res --> {res}')
|
||||||
if not res.get('success'):
|
if not res.get('success'):
|
||||||
raise Exception(res)
|
raise Exception(res)
|
||||||
debugger_address = res['data']['http']
|
if res.get('data').get(pk) is None:
|
||||||
return debugger_address
|
return False
|
||||||
|
|
||||||
# 关闭比特币浏览器
|
|
||||||
async def _bit_browser_close(self, pk: str, bit_port: str = "54345"):
|
|
||||||
"""
|
|
||||||
关闭比特币浏览器 - 执行后需要等待5s
|
|
||||||
:param pk: 浏览器ID
|
|
||||||
:param bit_port: 可选,默认54345
|
|
||||||
:return: 无返回值
|
|
||||||
"""
|
|
||||||
url = f"{self.bit_host}:{bit_port}/browser/close"
|
|
||||||
headers = {'Content-Type': 'application/json'}
|
|
||||||
data = {'id': f'{pk}'}
|
|
||||||
await self.__request('POST', url, json=data, headers=headers)
|
|
||||||
await asyncio.sleep(5) # 等待5s,等待浏览器关闭
|
|
||||||
|
|
||||||
# 删除比特币浏览器
|
|
||||||
async def _bit_browser_delete(self, pk: str, bit_port: str = "54345"):
|
|
||||||
"""
|
|
||||||
删除比特币浏览器
|
|
||||||
:param pk: 浏览器ID
|
|
||||||
:param bit_port: 可选,默认54345
|
|
||||||
:return: 无返回值
|
|
||||||
"""
|
|
||||||
url = f"{self.bit_host}:{bit_port}/browser/delete"
|
|
||||||
headers = {'Content-Type': 'application/json'}
|
|
||||||
data = {'id': f'{pk}'}
|
|
||||||
print(await self.__request('POST', url, json=data, headers=headers))
|
|
||||||
|
|
||||||
# 获取所有比特币浏览器
|
|
||||||
@async_retry(max_retries=3, delay=1.0, backoff=1.0)
|
|
||||||
async def _bit_browser_get(self, page: int = 0, limit: int = 10, group_id: str | None = None,
|
|
||||||
bit_port: str | None = "54345",
|
|
||||||
) -> dict:
|
|
||||||
"""
|
|
||||||
获取所有比特币浏览器
|
|
||||||
:param page: 页码
|
|
||||||
:param group_id: 分组ID
|
|
||||||
:param limit: 每页数量
|
|
||||||
:param bit_port: 可选,默认54345
|
|
||||||
:return: {'success': True, 'data': {'page': 1, 'pageSize': 10, 'totalNum': 128, 'list': [{'id': '12a3126accc14c93bd34adcccfc3083c'},{'id':'edc5d61a56214e9f8a8bbf1a2e1b405d'}]}}
|
|
||||||
"""
|
|
||||||
|
|
||||||
url = f"{self.bit_host}:{bit_port}/browser/list"
|
|
||||||
headers = {'Content-Type': 'application/json'}
|
|
||||||
data = {'page': page, 'pageSize': limit}
|
|
||||||
if group_id is not None:
|
|
||||||
data['groupId'] = group_id
|
|
||||||
res = await self.__request('POST', url, json=data, headers=headers)
|
|
||||||
if not res.get('success'):
|
|
||||||
raise Exception(res)
|
|
||||||
return res
|
|
||||||
|
|
||||||
# 获取比特浏览器窗口详情
|
|
||||||
@async_retry(max_retries=3, delay=1.0, backoff=1.0)
|
|
||||||
async def _bit_browser_detail(self, pk: str, bit_port: str = "54345") -> dict:
|
|
||||||
"""
|
|
||||||
获取比特浏览器窗口详情
|
|
||||||
:param pk: 浏览器ID
|
|
||||||
:param bit_port: 可选,默认54345
|
|
||||||
:return: {'success': True, 'data': {'id': '12a3126accc14c93bd34adcccfc3083c', 'name': '12a3126accc14c93bd34adcccfc3083c', 'remark': '12a3126accc14c93bd34adcccfc3083c', 'groupId': '12a3126accc14c93bd34adcccfc3083c', 'proxyType
|
|
||||||
"""
|
|
||||||
url = f"{self.bit_host}:{bit_port}/browser/detail"
|
|
||||||
headers = {'Content-Type': 'application/json'}
|
|
||||||
data = {
|
|
||||||
"id": pk
|
|
||||||
}
|
|
||||||
res = await self.__request('POST', url, json=data, headers=headers)
|
|
||||||
if not res.get('success'):
|
|
||||||
raise Exception(res)
|
|
||||||
return res
|
|
||||||
|
|
||||||
# 获取比特浏览器的进程id并杀死进程
|
|
||||||
@async_retry(max_retries=3, delay=1.0, backoff=1.0)
|
|
||||||
async def _bit_browser_kill_pid(self, pk: str, bit_port: str = "54345") -> str:
|
|
||||||
"""
|
|
||||||
获取比特浏览器的进程id
|
|
||||||
:param pk: 浏览器ID
|
|
||||||
:param bit_port: 可选,默认54345
|
|
||||||
:return: 返回进程id
|
|
||||||
"""
|
|
||||||
url = f"{self.bit_host}:{bit_port}/browser/pids/alive"
|
|
||||||
headers = {'Content-Type': 'application/json'}
|
|
||||||
data = {
|
|
||||||
"ids": [pk]
|
|
||||||
}
|
|
||||||
res = await self.__request('POST', url, json=data, headers=headers)
|
|
||||||
if not res.get('success'):
|
|
||||||
raise Exception(res)
|
|
||||||
pid = res['data'][pk]
|
|
||||||
# 检测系统 并杀死进程
|
|
||||||
if pid is not None:
|
|
||||||
if os.name == 'nt':
|
|
||||||
os.system(f"taskkill /F /PID {pid}")
|
|
||||||
else:
|
else:
|
||||||
os.system(f"kill -9 {pid}")
|
return True
|
||||||
return pid
|
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
|
|||||||
Reference in New Issue
Block a user