Files
weibo_signin/test_fetch_topics.py

128 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
验证签到流程是否正常。
在服务器上执行: docker exec -it weibo-scheduler python -m test_fetch_topics
或本地: cd backend && python ../test_fetch_topics.py
会从数据库读取第一个 active 账号,解密 Cookie模拟 _fetch_topics 流程。
"""
import os
import sys
import re
import asyncio
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "backend"))
sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
# 兼容容器内运行(/app 目录)
if os.path.exists("/app/shared"):
sys.path.insert(0, "/app")
from shared.config import shared_settings
from shared.crypto import decrypt_cookie, derive_key
WEIBO_HEADERS = {
"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",
"Referer": "https://weibo.com/",
"Accept": "*/*",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
}
async def main():
import httpx
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
from shared.models.account import Account
engine = create_async_engine(shared_settings.DATABASE_URL, echo=False)
Session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async with Session() as session:
result = await session.execute(
select(Account).where(Account.status.in_(["active", "pending"])).limit(1)
)
account = result.scalar_one_or_none()
if not account:
print("❌ 没有 active/pending 账号")
return
print(f"📱 账号: {account.remark or account.weibo_user_id} (status={account.status})")
key = derive_key(shared_settings.COOKIE_ENCRYPTION_KEY)
cookie_str = decrypt_cookie(account.encrypted_cookies, account.iv, key)
cookies = {}
for pair in cookie_str.split(";"):
pair = pair.strip()
if "=" in pair:
k, v = pair.split("=", 1)
cookies[k.strip()] = v.strip()
print(f"🍪 Cookie 数量: {len(cookies)}, keys: {list(cookies.keys())}")
# 检查 Cookie 有效期
from datetime import datetime
alf = cookies.get("ALF", "")
if alf and alf.isdigit():
expire_time = datetime.fromtimestamp(int(alf))
remain = (expire_time - datetime.now()).days
print(f"📅 Cookie 过期时间: {expire_time.strftime('%Y-%m-%d %H:%M:%S')} (还剩 {remain} 天)")
else:
print(f"📅 ALF 字段: {alf or ''} (无法判断过期时间)")
await engine.dispose()
# 测试 1: 直接请求超话 API不经过首页
print("\n--- 测试 1: 直接请求超话 API ---")
async with httpx.AsyncClient(timeout=20, follow_redirects=False) as client:
xsrf = cookies.get("XSRF-TOKEN", "")
headers = {
**WEIBO_HEADERS,
"X-Requested-With": "XMLHttpRequest",
}
if xsrf:
headers["X-XSRF-TOKEN"] = xsrf
resp = await client.get(
"https://weibo.com/ajax/profile/topicContent",
params={"tabid": "231093_-_chaohua", "page": "1"},
headers=headers, cookies=cookies,
)
print(f" 状态码: {resp.status_code}")
print(f" URL: {resp.url}")
if resp.status_code in (301, 302):
print(f" 重定向到: {resp.headers.get('location', '')[:120]}")
print("\n❌ Cookie 已失效API 被重定向)")
# 对比:访问首页看看
print("\n--- 对比: GET https://weibo.com/ ---")
async with httpx.AsyncClient(timeout=20, follow_redirects=True) as c2:
r2 = await c2.get("https://weibo.com/", headers=WEIBO_HEADERS, cookies=cookies)
print(f" 最终URL: {r2.url}")
print(f" 是否登录页: {'login.sina' in str(r2.url) or 'passport' in str(r2.url)}")
return
try:
data = resp.json()
print(f" ok: {data.get('ok')}")
topics = data.get("data", {}).get("list", [])
print(f" 超话数量: {len(topics)}")
for t in topics[:5]:
title = t.get("topic_name", "") or t.get("title", "")
print(f" - {title}")
if topics:
print("\n✅ Cookie 有效,超话获取正常(直接 API 模式)")
elif data.get("ok") == 1:
print("\n⚠️ Cookie 有效但没有关注超话")
else:
print(f"\n❌ API 返回异常: {str(data)[:200]}")
except Exception as e:
print(f" ❌ 响应非 JSON: {resp.text[:300]}")
print(f"\n❌ 获取超话失败: {e}")
if __name__ == "__main__":
asyncio.run(main())