Files
cookie/browser_login.py
T
2026-03-02 17:02:09 +08:00

320 lines
8.8 KiB
Python

"""浏览器登录模块 - 使用 DrissionPage 控制浏览器进行登录检测和 cookie 管理"""
from typing import Dict, List, Optional
import json
import time
from DrissionPage import Chromium, ChromiumOptions
from applogger import get_logger
logger = get_logger(__name__)
class BrowserLogin:
"""浏览器登录客户端"""
def __init__(self, browser_type: str = "edge", headless: bool = False):
"""
初始化浏览器登录客户端
Args:
browser_type: 浏览器类型 (chrome 或 edge)
headless: 是否无头模式
"""
self.browser_type = browser_type.lower()
self.headless = headless
self.browser = None
self.tab = None
def _create_browser(self):
"""创建浏览器实例"""
co = ChromiumOptions()
# 设置浏览器路径
if self.browser_type == "edge":
co.set_browser_path("C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe")
elif self.browser_type == "chrome":
co.set_browser_path("chrome")
# 设置无头模式
if self.headless:
co.headless = True
# 设置其他选项
co.set_argument('--no-sandbox')
co.set_argument('--disable-dev-shm-usage')
# 创建浏览器
self.browser = Chromium(co)
self.tab = self.browser.new_tab()
def _close_browser(self):
"""关闭浏览器"""
if self.browser:
try:
self.browser.quit()
except Exception as e:
logger.error(f"关闭浏览器失败: {e}")
finally:
self.browser = None
self.tab = None
def _get_domain_from_url(self, url: str) -> str:
"""
从 URL 中提取域名
Args:
url: 网站地址
Returns:
域名
"""
from urllib.parse import urlparse
parsed = urlparse(url)
return parsed.netloc
def _get_cookies_dict(self) -> Dict[str, List[Dict]]:
"""
获取当前浏览器的所有 cookie,按域名分组
Returns:
按域名分组的 cookie 字典
"""
cookies = self.tab.cookies.as_dict
# 按域名分组
cookie_dict = {}
for cookie in cookies:
domain = cookie.get('domain', '')
# 统一域名格式(去掉开头的点)
if domain.startswith('.'):
domain = domain[1:]
if domain not in cookie_dict:
cookie_dict[domain] = []
cookie_dict[domain].append(cookie)
return cookie_dict
def check_login(self, url: str, check_selector: str, success_text: str) -> bool:
"""
检查是否已登录
Args:
url: 网站地址
check_selector: 登录检测选择器
success_text: 登录成功时显示的文本
Returns:
是否已登录
"""
if not self.browser or not self.tab:
self._create_browser()
try:
# 访问网站
self.tab.get(url)
# 等待页面加载
time.sleep(2)
# 检查登录状态
element = self.tab.ele(check_selector, timeout=10)
if element and element.text and success_text in element.text:
return True
return False
except Exception as e:
logger.error(f"检查登录状态失败: {e}")
return False
def login_with_cookies(
self,
url: str,
cookies: List[Dict],
check_selector: str,
success_text: str
) -> bool:
"""
使用 cookie 登录
Args:
url: 网站地址
cookies: cookie 列表
check_selector: 登录检测选择器
success_text: 登录成功时显示的文本
Returns:
是否登录成功
"""
if not self.browser or not self.tab:
self._create_browser()
try:
# 访问网站
self.tab.get(url)
# 添加 cookies
for cookie in cookies:
self.tab.set.cookies(cookie)
# 刷新页面
self.tab.refresh()
# 等待页面加载
time.sleep(3)
# 检查登录状态
element = self.tab.ele(check_selector, timeout=10)
if element and element.text and success_text in element.text:
return True
return False
except Exception as e:
logger.error(f"使用 cookie 登录失败: {e}")
return False
def refresh_and_save_cookies(self, url: str) -> List[Dict]:
"""
刷新页面并保存新的 cookie
Args:
url: 网站地址
Returns:
cookie 列表
"""
if not self.browser or not self.tab:
self._create_browser()
try:
# 刷新页面
self.tab.refresh()
# 等待页面加载
time.sleep(3)
# 获取 cookies
cookies = self.tab.cookies.as_dict
return cookies
except Exception as e:
logger.error(f"刷新页面并保存 cookie 失败: {e}")
return []
def close(self):
"""关闭浏览器"""
self._close_browser()
class CookieManager:
"""Cookie 管理器"""
def __init__(self, cookie_file: str):
"""
初始化 Cookie 管理器
Args:
cookie_file: cookie 文件路径
"""
self.cookie_file = cookie_file
self.cookies = self._load_cookies()
def _load_cookies(self) -> Dict[str, Dict[str, List[Dict]]]:
"""加载 cookie 文件"""
import os
if os.path.exists(self.cookie_file):
try:
with open(self.cookie_file, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
logger.error(f"加载 cookie 文件失败: {e}")
return {}
def _save_cookies(self):
"""保存 cookie 文件"""
try:
with open(self.cookie_file, 'w', encoding='utf-8') as f:
json.dump(self.cookies, f, indent=2, ensure_ascii=False)
except Exception as e:
logger.error(f"保存 cookie 文件失败: {e}")
def get_cookies(self, user_name: str, website_name: str) -> List[Dict]:
"""
获取指定用户和网站的 cookie
Args:
user_name: 用户名
website_name: 网站名
Returns:
cookie 列表
"""
if user_name not in self.cookies:
return []
if website_name not in self.cookies[user_name]:
return []
return self.cookies[user_name][website_name]
def save_cookies(self, user_name: str, website_name: str, cookies: List[Dict]):
"""
保存指定用户和网站的 cookie
Args:
user_name: 用户名
website_name: 网站名
cookies: cookie 列表
"""
if user_name not in self.cookies:
self.cookies[user_name] = {}
self.cookies[user_name][website_name] = cookies
self._save_cookies()
def get_cookies_for_domain(self, domain: str) -> List[Dict]:
"""
获取指定域名的 cookie(从所有用户的 cookie 中查找)
Args:
domain: 域名
Returns:
cookie 列表
"""
all_cookies = []
for user_name, websites in self.cookies.items():
for website_name, cookies in websites.items():
for cookie in cookies:
cookie_domain = cookie.get('domain', '')
# 统一域名格式
if cookie_domain.startswith('.'):
cookie_domain = cookie_domain[1:]
if domain in cookie_domain or cookie_domain in domain:
all_cookies.append(cookie)
return all_cookies
if __name__ == "__main__":
# 测试代码
manager = CookieManager("cookies.json")
# 保存测试 cookie
test_cookies = [
{"name": "test", "value": "123", "domain": "example.com", "path": "/"}
]
manager.save_cookies("测试用户", "测试网站", test_cookies)
# 获取 cookie
cookies = manager.get_cookies("测试用户", "测试网站")
logger.info(f"获取到的 cookie: {cookies}")