144 lines
5.5 KiB
Python
144 lines
5.5 KiB
Python
|
|
import datetime
|
|||
|
|
import asyncio
|
|||
|
|
import httpx
|
|||
|
|
from loguru import logger
|
|||
|
|
from utils.decorators import handle_exceptions_unified
|
|||
|
|
|
|||
|
|
|
|||
|
|
class BrowserApi:
|
|||
|
|
"""
|
|||
|
|
浏览器接口
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
def __init__(self):
|
|||
|
|
self.local_url = 'http://127.0.0.1:54345'
|
|||
|
|
self.headers = {'Content-Type': 'application/json'}
|
|||
|
|
# 使用异步 HTTP 客户端,启用连接池和超时设置
|
|||
|
|
self.client = httpx.AsyncClient(
|
|||
|
|
base_url=self.local_url,
|
|||
|
|
headers=self.headers,
|
|||
|
|
timeout=httpx.Timeout(30.0, connect=10.0), # 总超时30秒,连接超时10秒
|
|||
|
|
limits=httpx.Limits(max_keepalive_connections=50, max_connections=100), # 连接池配置
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
async def __aenter__(self):
|
|||
|
|
"""异步上下文管理器入口"""
|
|||
|
|
return self
|
|||
|
|
|
|||
|
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|||
|
|
"""异步上下文管理器出口,关闭客户端"""
|
|||
|
|
await self.aclose()
|
|||
|
|
|
|||
|
|
async def aclose(self):
|
|||
|
|
"""关闭 HTTP 客户端"""
|
|||
|
|
if self.client:
|
|||
|
|
await self.client.aclose()
|
|||
|
|
|
|||
|
|
# 打开指纹浏览器
|
|||
|
|
@handle_exceptions_unified()
|
|||
|
|
async def open_browser(self, id: str, jc: int = 0):
|
|||
|
|
"""
|
|||
|
|
打开指纹浏览器(异步优化版本)
|
|||
|
|
:param jc: 计次
|
|||
|
|
:param id: 浏览器id
|
|||
|
|
:return:http, pid
|
|||
|
|
"""
|
|||
|
|
if jc > 3:
|
|||
|
|
return None, None
|
|||
|
|
url = '/browser/open'
|
|||
|
|
data = {
|
|||
|
|
'id': id
|
|||
|
|
}
|
|||
|
|
try:
|
|||
|
|
res = await self.client.post(url, json=data)
|
|||
|
|
res.raise_for_status() # 检查 HTTP 状态码
|
|||
|
|
res_data = res.json()
|
|||
|
|
logger.info(f'打开指纹浏览器: {res_data}')
|
|||
|
|
if not res_data.get('success'):
|
|||
|
|
logger.error(f'打开指纹浏览器失败: {res_data}')
|
|||
|
|
return await self.open_browser(id, jc + 1)
|
|||
|
|
data = res_data.get('data')
|
|||
|
|
http = data.get('http')
|
|||
|
|
pid = data.get('pid')
|
|||
|
|
logger.info(f'打开指纹浏览器成功: {http}, {pid}')
|
|||
|
|
return http, pid
|
|||
|
|
except httpx.TimeoutException as e:
|
|||
|
|
logger.error(f'打开指纹浏览器超时: {e}')
|
|||
|
|
if jc < 3:
|
|||
|
|
return await self.open_browser(id, jc + 1)
|
|||
|
|
return None, None
|
|||
|
|
except httpx.RequestError as e:
|
|||
|
|
logger.error(f'打开指纹浏览器请求错误: {e}')
|
|||
|
|
if jc < 3:
|
|||
|
|
return await self.open_browser(id, jc + 1)
|
|||
|
|
return None, None
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f'打开指纹浏览器异常: {e}')
|
|||
|
|
if jc < 3:
|
|||
|
|
return await self.open_browser(id, jc + 1)
|
|||
|
|
return None, None
|
|||
|
|
|
|||
|
|
# 关闭指纹浏览器
|
|||
|
|
@handle_exceptions_unified()
|
|||
|
|
async def close_browser(self, id: str, jc: int = 0):
|
|||
|
|
"""
|
|||
|
|
关闭指纹浏览器(异步优化版本)
|
|||
|
|
:param jc: 计次
|
|||
|
|
:param id: 浏览器id
|
|||
|
|
:return:
|
|||
|
|
"""
|
|||
|
|
if jc > 3:
|
|||
|
|
return None
|
|||
|
|
url = '/browser/close'
|
|||
|
|
data = {
|
|||
|
|
'id': id
|
|||
|
|
}
|
|||
|
|
try:
|
|||
|
|
res = await self.client.post(url, json=data)
|
|||
|
|
res.raise_for_status() # 检查 HTTP 状态码
|
|||
|
|
res_data = res.json()
|
|||
|
|
logger.info(f'关闭指纹浏览器: {res_data}')
|
|||
|
|
if not res_data.get('success'):
|
|||
|
|
msg = res_data.get('msg', '')
|
|||
|
|
# 如果浏览器正在打开中,等待后重试(不是真正的错误)
|
|||
|
|
if '正在打开中' in msg or 'opening' in msg.lower():
|
|||
|
|
if jc < 3:
|
|||
|
|
# 等待 1-3 秒后重试(根据重试次数递增等待时间)
|
|||
|
|
wait_time = (jc + 1) * 1.0 # 第1次重试等1秒,第2次等2秒,第3次等3秒
|
|||
|
|
logger.info(f'浏览器正在打开中,等待 {wait_time} 秒后重试关闭: browser_id={id}')
|
|||
|
|
await asyncio.sleep(wait_time)
|
|||
|
|
return await self.close_browser(id, jc + 1)
|
|||
|
|
else:
|
|||
|
|
# 超过重试次数,记录警告但不作为错误
|
|||
|
|
logger.warning(f'关闭指纹浏览器失败(浏览器正在打开中,已重试3次): browser_id={id}')
|
|||
|
|
return None
|
|||
|
|
else:
|
|||
|
|
# 其他错误,记录为错误并重试
|
|||
|
|
logger.error(f'关闭指纹浏览器失败: {res_data}')
|
|||
|
|
if jc < 3:
|
|||
|
|
await asyncio.sleep(0.5) # 短暂等待后重试
|
|||
|
|
return await self.close_browser(id, jc + 1)
|
|||
|
|
return None
|
|||
|
|
logger.info(f'关闭指纹浏览器成功: browser_id={id}')
|
|||
|
|
return True
|
|||
|
|
except httpx.TimeoutException as e:
|
|||
|
|
logger.error(f'关闭指纹浏览器超时: {e}')
|
|||
|
|
if jc < 3:
|
|||
|
|
await asyncio.sleep(1.0)
|
|||
|
|
return await self.close_browser(id, jc + 1)
|
|||
|
|
return None
|
|||
|
|
except httpx.RequestError as e:
|
|||
|
|
logger.error(f'关闭指纹浏览器请求错误: {e}')
|
|||
|
|
if jc < 3:
|
|||
|
|
await asyncio.sleep(1.0)
|
|||
|
|
return await self.close_browser(id, jc + 1)
|
|||
|
|
return None
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f'关闭指纹浏览器异常: {e}')
|
|||
|
|
if jc < 3:
|
|||
|
|
await asyncio.sleep(1.0)
|
|||
|
|
return await self.close_browser(id, jc + 1)
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
browser_api = BrowserApi()
|