from abc import ABC, abstractmethod
|
from pathlib import Path
|
import os
|
import asyncio
|
from playwright.async_api import async_playwright, TimeoutError as PlaywrightTimeoutError
|
|
from auto_media_publisher.config.conf_base import COOKIE_DIR,PLAYWRIGHT_STEALTH_JS_PATH,DEFAULT_USER_AGENT
|
from auto_media_publisher.config.conf_platform_login_url import PLATFORM_LOGIN_MAP
|
from auto_media_publisher.utils.logger import get_logger
|
|
|
class LoginChrome(ABC):
|
def __init__(self, user,platform,proxy):
|
self.user = user
|
self.platform = platform
|
self.proxy = proxy
|
self.cookie_path = os.path.join(COOKIE_DIR, user, f"{platform}.json")
|
os.makedirs(os.path.dirname(self.cookie_path), exist_ok=True)
|
self.logger = get_logger(platform,user)
|
for k, v in PLATFORM_LOGIN_MAP.get(self.platform).items():
|
setattr(self, k, v)
|
|
@classmethod
|
def create_sub_class(cls, user,platform,proxy): # cls 相当于 self
|
return cls(user, platform, proxy)
|
|
|
async def _init_browser_context(self,playwright,headless=True):
|
"""
|
初始化 self.browser and self.context
|
如果有 self.proxy,设置
|
如果有 self.cookie_path ,设置
|
"""
|
browser_args = {"headless": headless,"channel": "chrome"}
|
|
if getattr(self, 'browser_addon_options', None):
|
browser_args.update(self.browser_addon_options)
|
print(f"start to init browser Using proxy: {self.proxy}")
|
if isinstance(self.proxy, str) and self.proxy.strip().lower().startswith(('http://', 'https://')):
|
browser_args["proxy"] = {"server": self.proxy}
|
self.browser = await playwright.chromium.launch(**browser_args)
|
if os.path.exists(self.cookie_path):
|
self.context = await self.browser.new_context(storage_state=f"{self.cookie_path}", user_agent=DEFAULT_USER_AGENT,viewport={"width": 1920, "height": 1080})
|
else:
|
self.context = await self.browser.new_context(user_agent=DEFAULT_USER_AGENT,viewport={"width": 1920, "height": 1080})
|
if os.path.exists(PLAYWRIGHT_STEALTH_JS_PATH):
|
await self.context.add_init_script(path=Path(PLAYWRIGHT_STEALTH_JS_PATH))
|
await self.context.grant_permissions(['geolocation'])
|
|
async def check_cookie_valid(self,if_hold_page:bool = False,headless:bool = True,login_url_time_out_ = 100000,login_element_time_out = 300000) -> bool:
|
"""
|
检查当前 cookie 是否有效(如是否已登录)
|
默认 if_hold_page = False,就是登录后即退出,不等待
|
默认 headless = False ,就是 不显示浏览器窗口
|
"""
|
async with async_playwright() as playwright:
|
await self._init_browser_context(playwright,headless)
|
# 创建一个新的页面
|
page = await self.context.new_page()
|
# 访问指定的 URL
|
try:
|
self.logger.info(f"{self.user},正在打开{self.login_url}")
|
if if_hold_page:
|
login_url_time_out_ = 300000
|
await page.goto(self.login_url, timeout=login_url_time_out_)
|
except Exception as e:
|
self.logger.error(f"[login_chrome] 发生错误:{e}")
|
try:
|
locator = page.locator(self.login_element)
|
await locator.first.wait_for(timeout=login_element_time_out) # 等待至少一个元素出现
|
await self.context.storage_state(path=self.cookie_path)
|
self.logger.info(f"check_cookie_valid:{self.user}登录{self.platform}成功,cookie 已保存到 {self.cookie_path}")
|
if if_hold_page:
|
while True:
|
await asyncio.sleep(1)
|
|
return True
|
except PlaywrightTimeoutError:
|
self.logger.error("check_cookie_valid:{self.user}登录{self.platform}失败,等待跳转到目标页面超时,cookie 未保存")
|
return False
|
|
finally:
|
await self.browser.close()
|
|
|
async def run(self):
|
try:
|
self.logger.info(f'[+] 开始检测{self.user}在{self.platform}的登录信息cookie文件是否存在或过期!')
|
if not os.path.exists(self.cookie_path) or not await self.check_cookie_valid():
|
self.logger.info('[+] cookie文件不存在或已失效,即将自动打开浏览器,请扫码登录,登陆后会自动生成cookie文件')
|
await self.check_cookie_valid(if_hold_page=False,headless=False)
|
|
return True
|
except Exception as e:
|
self.logger.error(f"{self.user} login fails :{e}")
|
return False
|
|
|
async def open(self):
|
try:
|
await self.check_cookie_valid(if_hold_page=True,headless=False)
|
return True
|
except Exception as e:
|
self.logger.error(f"{self.user} login fails :{e}")
|
return False
|