Files
ai_wht_wechat/backend/test_cookie_inject.py

399 lines
13 KiB
Python
Raw Normal View History

2026-01-06 19:36:42 +08:00
"""
Cookie注入测试脚本
使用Playwright注入Cookie并验证其有效性
支持跳转到创作者中心或小红书首页
"""
import asyncio
import sys
import json
from pathlib import Path
from playwright.async_api import async_playwright
from typing import Optional, List, Dict, Any
class CookieInjector:
"""Cookie注入器"""
def __init__(self, headless: bool = False):
"""
初始化Cookie注入器
Args:
headless: 是否使用无头模式False可以看到浏览器界面
"""
self.headless = headless
self.playwright = None
self.browser = None
self.context = None
self.page = None
async def init_browser(self):
"""初始化浏览器"""
try:
print("正在启动浏览器...")
# Windows环境下设置事件循环策略
if sys.platform == 'win32':
try:
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
except Exception as e:
print(f"警告: 设置事件循环策略失败: {str(e)}")
self.playwright = await async_playwright().start()
# 启动浏览器
self.browser = await self.playwright.chromium.launch(
headless=self.headless,
args=['--disable-blink-features=AutomationControlled']
)
# 创建浏览器上下文
self.context = await self.browser.new_context(
viewport={'width': 1280, 'height': 720},
user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
)
# 创建新页面
self.page = await self.context.new_page()
print("浏览器初始化成功")
except Exception as e:
print(f"浏览器初始化失败: {str(e)}")
raise
async def inject_cookies(self, cookies: List[Dict[str, Any]]) -> bool:
"""
注入Cookie
Args:
cookies: Cookie列表
Returns:
是否注入成功
"""
try:
if not self.context:
await self.init_browser()
print(f"正在注入 {len(cookies)} 个Cookie...")
# 注入Cookie到浏览器上下文
await self.context.add_cookies(cookies)
print("Cookie注入成功")
return True
except Exception as e:
print(f"Cookie注入失败: {str(e)}")
return False
async def verify_and_navigate(self, target_page: str = 'creator') -> Dict[str, Any]:
"""
验证Cookie并跳转到指定页面
Args:
target_page: 目标页面类型 ('creator' 'home')
Returns:
验证结果字典
"""
try:
if not self.page:
return {"success": False, "error": "浏览器未初始化"}
# 确定目标URL
urls = {
'creator': 'https://creator.xiaohongshu.com',
'home': 'https://www.xiaohongshu.com'
}
target_url = urls.get(target_page, urls['creator'])
page_name = '创作者中心' if target_page == 'creator' else '小红书首页'
print(f"\n正在访问{page_name}: {target_url}")
# 访问目标页面
await self.page.goto(target_url, wait_until='networkidle', timeout=30000)
await asyncio.sleep(2) # 等待页面完全加载
# 获取当前URL和标题
current_url = self.page.url
title = await self.page.title()
print(f"当前URL: {current_url}")
print(f"页面标题: {title}")
# 检查是否被重定向到登录页
is_logged_in = 'login' not in current_url.lower()
if is_logged_in:
print("Cookie验证成功已登录状态")
# 尝试获取用户信息
try:
# 等待用户相关元素出现(如头像、用户名等)
await self.page.wait_for_selector('[class*="avatar"], [class*="user"]', timeout=5000)
print("检测到用户信息元素,确认登录成功")
except Exception:
print("未检测到明显的用户信息元素,但未跳转到登录页")
return {
"success": True,
"message": f"Cookie有效已成功访问{page_name}",
"url": current_url,
"title": title,
"logged_in": True
}
else:
print("Cookie可能已失效页面跳转到登录页")
return {
"success": False,
"error": "Cookie已失效或无效页面跳转到登录页",
"url": current_url,
"title": title,
"logged_in": False
}
except Exception as e:
print(f"验证过程异常: {str(e)}")
import traceback
traceback.print_exc()
return {
"success": False,
"error": f"验证过程异常: {str(e)}"
}
async def keep_browser_open(self, duration: int = 60):
"""
保持浏览器打开一段时间方便观察
Args:
duration: 保持打开的秒数0表示永久打开直到手动关闭
"""
try:
if duration == 0:
print("\n浏览器将保持打开,按 Ctrl+C 关闭...")
try:
while True:
await asyncio.sleep(1)
except KeyboardInterrupt:
print("\n用户中断,准备关闭浏览器...")
else:
print(f"\n浏览器将保持打开 {duration} 秒...")
await asyncio.sleep(duration)
print("时间到,准备关闭浏览器...")
except Exception as e:
print(f"保持浏览器异常: {str(e)}")
async def close_browser(self):
"""关闭浏览器"""
try:
print("\n正在关闭浏览器...")
if self.page:
await self.page.close()
if self.context:
await self.context.close()
if self.browser:
await self.browser.close()
if self.playwright:
await self.playwright.stop()
print("浏览器已关闭")
except Exception as e:
print(f"关闭浏览器异常: {str(e)}")
def load_cookies_from_file(file_path: str) -> Optional[List[Dict[str, Any]]]:
"""
从文件加载Cookie
Args:
file_path: Cookie文件路径
Returns:
Cookie列表失败返回None
"""
try:
cookie_file = Path(file_path)
if not cookie_file.exists():
print(f"Cookie文件不存在: {file_path}")
return None
with open(cookie_file, 'r', encoding='utf-8') as f:
cookies = json.load(f)
if not isinstance(cookies, list):
print("Cookie格式错误必须是数组")
return None
if len(cookies) == 0:
print("Cookie数组为空")
return None
# 验证每个Cookie必须有name和value
for cookie in cookies:
if not cookie.get('name') or not cookie.get('value'):
print(f"Cookie格式错误缺少name或value字段")
return None
print(f"成功加载 {len(cookies)} 个Cookie")
return cookies
except json.JSONDecodeError as e:
print(f"Cookie文件JSON解析失败: {str(e)}")
return None
except Exception as e:
print(f"加载Cookie文件失败: {str(e)}")
return None
async def test_cookie_inject(
cookies_source: str,
target_page: str = 'creator',
headless: bool = False,
keep_open: int = 0
):
"""
测试Cookie注入
Args:
cookies_source: Cookie来源文件路径或JSON字符串
target_page: 目标页面 ('creator' 'home')
headless: 是否使用无头模式
keep_open: 保持浏览器打开的秒数0表示永久打开
"""
print("="*60)
print("Cookie注入并验证测试")
print("="*60)
# 加载Cookie
cookies = None
# 尝试作为文件路径加载
if Path(cookies_source).exists():
print(f"\n从文件加载Cookie: {cookies_source}")
cookies = load_cookies_from_file(cookies_source)
else:
# 尝试作为JSON字符串解析
try:
print("\n尝试解析Cookie JSON字符串...")
cookies = json.loads(cookies_source)
if isinstance(cookies, list) and len(cookies) > 0:
print(f"成功解析 {len(cookies)} 个Cookie")
except Exception as e:
print(f"Cookie解析失败: {str(e)}")
if not cookies:
print("\n加载Cookie失败请检查输入")
return
# 创建注入器
injector = CookieInjector(headless=headless)
try:
# 初始化浏览器
await injector.init_browser()
# 注入Cookie
inject_success = await injector.inject_cookies(cookies)
if not inject_success:
print("\nCookie注入失败")
return
# 验证并跳转
result = await injector.verify_and_navigate(target_page)
print("\n" + "="*60)
print("验证结果")
print("="*60)
if result.get('success'):
print(f"状态: 成功")
print(f"消息: {result.get('message')}")
print(f"URL: {result.get('url')}")
print(f"标题: {result.get('title')}")
print(f"登录状态: {'已登录' if result.get('logged_in') else '未登录'}")
else:
print(f"状态: 失败")
print(f"错误: {result.get('error')}")
if result.get('url'):
print(f"当前URL: {result.get('url')}")
# 保持浏览器打开
if keep_open >= 0:
await injector.keep_browser_open(keep_open)
except KeyboardInterrupt:
print("\n\n用户中断测试")
except Exception as e:
print(f"\n测试过程异常: {str(e)}")
import traceback
traceback.print_exc()
finally:
await injector.close_browser()
print("\n" + "="*60)
print("测试完成")
print("="*60)
async def main():
"""主函数"""
print("="*60)
print("小红书Cookie注入测试工具")
print("="*60)
print("\n功能说明:")
print("1. 注入Cookie到浏览器")
print("2. 验证Cookie有效性")
print("3. 跳转到指定页面(创作者中心/小红书首页)")
print("\n" + "="*60)
# 输入Cookie来源
print("\n请输入Cookie来源")
print("1. 输入Cookie文件路径如: cookies.json")
print("2. 直接粘贴JSON格式的Cookie")
cookies_source = input("\nCookie来源: ").strip()
if not cookies_source:
print("Cookie来源不能为空")
return
# 选择目标页面
print("\n请选择目标页面:")
print("1. 创作者中心creator.xiaohongshu.com")
print("2. 小红书首页www.xiaohongshu.com")
page_choice = input("\n选择 (1 或 2, 默认为 1): ").strip()
target_page = 'home' if page_choice == '2' else 'creator'
# 选择浏览器模式
headless_choice = input("\n是否使用无头模式?(y/n, 默认为 n): ").strip().lower()
headless = headless_choice == 'y'
# 选择保持打开时间
keep_open_input = input("\n保持浏览器打开时间0表示直到手动关闭默认60: ").strip()
try:
keep_open = int(keep_open_input) if keep_open_input else 60
except ValueError:
keep_open = 60
# 执行测试
await test_cookie_inject(
cookies_source=cookies_source,
target_page=target_page,
headless=headless,
keep_open=keep_open
)
if __name__ == "__main__":
# Windows环境下设置事件循环策略
if sys.platform == 'win32':
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
# 运行测试
asyncio.run(main())