189 lines
6.1 KiB
Python
189 lines
6.1 KiB
Python
|
|
"""
|
|||
|
|
测试 API 返回格式
|
|||
|
|
验证登录 API 是否正确返回 cookies 和 cookies_full
|
|||
|
|
"""
|
|||
|
|
import json
|
|||
|
|
|
|||
|
|
|
|||
|
|
def test_api_response_format():
|
|||
|
|
"""测试 API 响应格式"""
|
|||
|
|
|
|||
|
|
# 模拟 API 返回的数据
|
|||
|
|
mock_response = {
|
|||
|
|
"code": 0,
|
|||
|
|
"message": "登录成功",
|
|||
|
|
"data": {
|
|||
|
|
"user_info": {},
|
|||
|
|
"cookies": {
|
|||
|
|
"a1": "xxx",
|
|||
|
|
"webId": "yyy",
|
|||
|
|
"web_session": "zzz"
|
|||
|
|
},
|
|||
|
|
"cookies_full": [
|
|||
|
|
{
|
|||
|
|
"name": "a1",
|
|||
|
|
"value": "xxx",
|
|||
|
|
"domain": ".xiaohongshu.com",
|
|||
|
|
"path": "/",
|
|||
|
|
"expires": 1797066496,
|
|||
|
|
"httpOnly": False,
|
|||
|
|
"secure": False,
|
|||
|
|
"sameSite": "Lax"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "webId",
|
|||
|
|
"value": "yyy",
|
|||
|
|
"domain": ".xiaohongshu.com",
|
|||
|
|
"path": "/",
|
|||
|
|
"expires": 1797066496,
|
|||
|
|
"httpOnly": False,
|
|||
|
|
"secure": False,
|
|||
|
|
"sameSite": "Lax"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "web_session",
|
|||
|
|
"value": "zzz",
|
|||
|
|
"domain": ".xiaohongshu.com",
|
|||
|
|
"path": "/",
|
|||
|
|
"expires": 1797066497,
|
|||
|
|
"httpOnly": True,
|
|||
|
|
"secure": True,
|
|||
|
|
"sameSite": "Lax"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"login_time": "2025-12-12T23:30:00"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
print("="*60)
|
|||
|
|
print("API 响应格式测试")
|
|||
|
|
print("="*60)
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
# 检查响应结构
|
|||
|
|
assert "code" in mock_response, "缺少 code 字段"
|
|||
|
|
assert "message" in mock_response, "缺少 message 字段"
|
|||
|
|
assert "data" in mock_response, "缺少 data 字段"
|
|||
|
|
|
|||
|
|
data = mock_response["data"]
|
|||
|
|
|
|||
|
|
# 检查 cookies 字段(键值对格式)
|
|||
|
|
print("✅ 检查 cookies 字段(键值对格式):")
|
|||
|
|
assert "cookies" in data, "缺少 cookies 字段"
|
|||
|
|
assert isinstance(data["cookies"], dict), "cookies 应该是字典类型"
|
|||
|
|
print(f" 类型: {type(data['cookies']).__name__}")
|
|||
|
|
print(f" 示例: {json.dumps(data['cookies'], ensure_ascii=False, indent=2)}")
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
# 检查 cookies_full 字段(Playwright 完整格式)
|
|||
|
|
print("✅ 检查 cookies_full 字段(Playwright 完整格式):")
|
|||
|
|
assert "cookies_full" in data, "缺少 cookies_full 字段"
|
|||
|
|
assert isinstance(data["cookies_full"], list), "cookies_full 应该是列表类型"
|
|||
|
|
print(f" 类型: {type(data['cookies_full']).__name__}")
|
|||
|
|
print(f" 数量: {len(data['cookies_full'])} 个 Cookie")
|
|||
|
|
print(f" 示例(第一个):")
|
|||
|
|
print(f"{json.dumps(data['cookies_full'][0], ensure_ascii=False, indent=6)}")
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
# 检查 cookies_full 的每个元素
|
|||
|
|
print("✅ 检查 cookies_full 的结构:")
|
|||
|
|
for i, cookie in enumerate(data["cookies_full"]):
|
|||
|
|
assert "name" in cookie, f"Cookie[{i}] 缺少 name 字段"
|
|||
|
|
assert "value" in cookie, f"Cookie[{i}] 缺少 value 字段"
|
|||
|
|
assert "domain" in cookie, f"Cookie[{i}] 缺少 domain 字段"
|
|||
|
|
assert "path" in cookie, f"Cookie[{i}] 缺少 path 字段"
|
|||
|
|
assert "expires" in cookie, f"Cookie[{i}] 缺少 expires 字段"
|
|||
|
|
assert "httpOnly" in cookie, f"Cookie[{i}] 缺少 httpOnly 字段"
|
|||
|
|
assert "secure" in cookie, f"Cookie[{i}] 缺少 secure 字段"
|
|||
|
|
assert "sameSite" in cookie, f"Cookie[{i}] 缺少 sameSite 字段"
|
|||
|
|
print(f" Cookie[{i}] ({cookie['name']}): ✅ 所有字段完整")
|
|||
|
|
|
|||
|
|
print()
|
|||
|
|
print("="*60)
|
|||
|
|
print("🎉 所有检查通过!API 返回格式正确")
|
|||
|
|
print("="*60)
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
# 使用场景说明
|
|||
|
|
print("📝 使用场景:")
|
|||
|
|
print()
|
|||
|
|
print("1. 前端展示 - 使用 cookies(键值对格式):")
|
|||
|
|
print(" const cookies = response.data.cookies;")
|
|||
|
|
print(" console.log(cookies.a1, cookies.webId);")
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
print("2. 数据库存储 - 使用 cookies_full(完整格式):")
|
|||
|
|
print(" const cookiesFull = response.data.cookies_full;")
|
|||
|
|
print(" await db.saveCookies(userId, JSON.stringify(cookiesFull));")
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
print("3. Python 脚本使用 - 使用 cookies_full:")
|
|||
|
|
print(" cookies_full = response['data']['cookies_full']")
|
|||
|
|
print(" publisher = XHSPublishService(cookies_full)")
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
|
|||
|
|
def compare_formats():
|
|||
|
|
"""对比两种格式"""
|
|||
|
|
|
|||
|
|
print("="*60)
|
|||
|
|
print("格式对比分析")
|
|||
|
|
print("="*60)
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
# 键值对格式
|
|||
|
|
cookies_dict = {
|
|||
|
|
"a1": "xxx",
|
|||
|
|
"webId": "yyy",
|
|||
|
|
"web_session": "zzz"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Playwright 完整格式
|
|||
|
|
cookies_full = [
|
|||
|
|
{
|
|||
|
|
"name": "a1",
|
|||
|
|
"value": "xxx",
|
|||
|
|
"domain": ".xiaohongshu.com",
|
|||
|
|
"path": "/",
|
|||
|
|
"expires": 1797066496,
|
|||
|
|
"httpOnly": False,
|
|||
|
|
"secure": False,
|
|||
|
|
"sameSite": "Lax"
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
print("📊 键值对格式:")
|
|||
|
|
dict_str = json.dumps(cookies_dict, ensure_ascii=False, indent=2)
|
|||
|
|
print(dict_str)
|
|||
|
|
print(f" 大小: {len(dict_str)} 字符")
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
print("📊 Playwright 完整格式:")
|
|||
|
|
full_str = json.dumps(cookies_full, ensure_ascii=False, indent=2)
|
|||
|
|
print(full_str)
|
|||
|
|
print(f" 大小: {len(full_str)} 字符")
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
print("📊 对比结果:")
|
|||
|
|
print(f" 完整格式 vs 键值对格式: {len(full_str)} / {len(dict_str)} = {len(full_str)/len(dict_str):.1f}x")
|
|||
|
|
print(f" 每个 Cookie 完整格式约增加: {(len(full_str) - len(dict_str)) // len(cookies_dict)} 字符")
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
print("✅ 结论:")
|
|||
|
|
print(" - 完整格式虽然较大,但包含所有必要属性")
|
|||
|
|
print(" - 对于数据库存储,建议使用完整格式")
|
|||
|
|
print(" - 对于前端展示,可以使用键值对格式")
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
# 测试 API 响应格式
|
|||
|
|
test_api_response_format()
|
|||
|
|
|
|||
|
|
# 对比两种格式
|
|||
|
|
compare_formats()
|
|||
|
|
|
|||
|
|
print("="*60)
|
|||
|
|
print("✅ 测试完成!")
|
|||
|
|
print("="*60)
|