Files
qinglong/脚本库/web版/账密/百度贴吧签到/2026-05-23_Tieba_9b1ac223.py
2026-05-24 03:53:42 +00:00

334 lines
13 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.
# Source: https://github.com/CN-Grace/QinglongScripts/blob/main/Tieba.py
# Raw: https://raw.githubusercontent.com/CN-Grace/QinglongScripts/main/Tieba.py
# Repo: CN-Grace/QinglongScripts
# Path: Tieba.py
# UploadedAt: 2026-05-23T15:48:24Z
# SHA256: 9b1ac22330324c1b5579826fd6202a49e6e4aa857d1819be3cd7073dd7c092c2
# Category: web版/账密
# Evidence: web/H5关键词 + username/password/login
#!/usr/bin/env python3
"""
cron: 0 0 * * *
new Env("百度贴吧签到")
百度贴吧 每日自动签到脚本
- 获取用户登录状态
- 获取关注的贴吧列表(含等级、经验值)
- 对每个贴吧进行签到
- 统计签到结果和等级分布
"""
import hashlib
import os
import random
import time
import requests
from typing import Optional, List, Dict, Any
from utils import log_info, log_success, log_warning, log_error, beijing_time_str
from notifier import send as notify_send
# ==================== 用户配置 ====================
TIEBA_COOKIE = os.environ.get("TIEBA_COOKIE", "")
def create_session(cookie: str) -> requests.Session:
"""创建带 Cookie 的 requests.Session贴吧专用 User-Agent 和 Host"""
session = requests.Session()
session.headers.update({
"Host": "tieba.baidu.com",
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36",
"Connection": "keep-alive",
"Accept-Encoding": "gzip, deflate",
"Cache-Control": "no-cache",
})
cookie_dict = {item.split("=")[0]: item.split("=")[1] for item in cookie.split("; ") if "=" in item}
requests.utils.add_dict_to_cookiejar(session.cookies, cookie_dict)
return session
def encode_data(data: Dict, sign_key: str = "tiebaclient!!!") -> Dict:
"""对请求数据进行签名"""
s = ""
for key in sorted(data.keys()):
s += f"{key}={data[key]}"
sign = hashlib.md5((s + sign_key).encode("utf-8")).hexdigest().upper()
data.update({"sign": sign})
return data
def request(session: requests.Session, url: str, method: str = "get", data: Optional[Dict] = None, retry: int = 3) -> Dict:
"""带重试的请求函数"""
for i in range(retry):
try:
if method.lower() == "get":
response = session.get(url, timeout=10)
else:
response = session.post(url, data=data, timeout=10)
response.raise_for_status()
if not response.text.strip():
raise ValueError("空响应内容")
return response.json()
except Exception as e:
if i == retry - 1:
raise Exception(f"请求失败: {e!s}")
wait_time = 1.5 * (2 ** i) + random.uniform(0, 1)
time.sleep(wait_time)
raise Exception(f"请求失败,已达最大重试次数 {retry}")
# ---------- 核心功能 ----------
def get_user_info(session: requests.Session) -> tuple:
"""获取用户登录信息,返回 (tbs, user_name) 或 (False, 错误信息)"""
try:
result = request(session, "http://tieba.baidu.com/dc/common/tbs")
if result.get("is_login", 0) == 0:
return False, "登录失败Cookie 异常"
tbs = result.get("tbs", "")
try:
user_info = request(session, "https://tieba.baidu.com/f/user/json_userinfo")
user_data = user_info.get("data", "")
user_name = user_data.get("show_nickname", "未知用户") if isinstance(user_data, dict) else "未知用户"
except Exception:
user_name = "未知用户"
return tbs, user_name
except Exception as e:
return False, f"登录验证异常: {e}"
def get_favorite(session: requests.Session, bduss: str) -> List[Dict]:
"""获取用户关注的贴吧列表,包含等级信息"""
forums = []
page_no = 1
like_url = "http://c.tieba.baidu.com/c/f/forum/like"
while True:
data = encode_data({
"BDUSS": bduss,
"_client_type": "2",
"_client_id": "wappc_1534235498291_488",
"_client_version": "9.7.8.0",
"_phone_imei": "000000000000000",
"from": "1008621y",
"page_no": str(page_no),
"page_size": "200",
"model": "MI+5",
"net_type": "1",
"timestamp": str(int(time.time())),
"vcode_tag": "11",
})
try:
res = request(session, like_url, "post", data)
if "forum_list" in res:
for forum_type in ["non-gconforum", "gconforum"]:
if forum_type in res["forum_list"]:
items = res["forum_list"][forum_type]
if isinstance(items, list):
for f in items:
f["_is_signed"] = (forum_type == "gconforum")
forums.extend(items)
elif isinstance(items, dict):
items["_is_signed"] = (forum_type == "gconforum")
forums.append(items)
if res.get("has_more") != "1":
break
page_no += 1
time.sleep(random.uniform(1, 2))
except Exception as e:
log_error(f"获取贴吧列表出错: {e}")
break
log_info(f"共获取到 {len(forums)} 个关注的贴吧")
return forums
def build_level_summary(forums: List[Dict]) -> Dict:
"""从贴吧列表中提取等级汇总"""
total_exp = 0
level_stats = {}
forum_levels = []
for f in forums:
name = f.get("name", "")
level_id = int(f.get("level_id", 0))
cur_score = int(f.get("cur_score", 0))
levelup_score = int(f.get("levelup_score", 0))
total_exp += cur_score
if level_id not in level_stats:
level_stats[level_id] = {"count": 0, "total_exp": 0}
level_stats[level_id]["count"] += 1
level_stats[level_id]["total_exp"] += cur_score
forum_levels.append({
"name": name,
"level_id": level_id,
"cur_score": cur_score,
"levelup_score": levelup_score,
"exp_percent": round(cur_score / levelup_score * 100, 1) if levelup_score > 0 else 0,
})
sorted_levels = sorted(level_stats.items(), key=lambda x: x[0], reverse=True)
return {
"forum_count": len(forums),
"total_exp": total_exp,
"level_stats": sorted_levels,
"forum_levels": forum_levels,
}
def sign_forums(session: requests.Session, bduss: str, forums: List[Dict], tbs: str) -> Dict[str, Any]:
"""对贴吧列表进行签到"""
success_count = 0
error_count = 0
exist_count = 0
shield_count = 0
total = len(forums)
details = []
log_info(f"开始签到 {total} 个贴吧")
base_data = {
"_client_type": "2",
"_client_version": "9.7.8.0",
"_phone_imei": "000000000000000",
"model": "MI+5",
"net_type": "1",
}
last_request_time = time.time()
for idx, forum in enumerate(forums):
elapsed = time.time() - last_request_time
delay = max(0, 1.0 + random.uniform(0.5, 1.5) - elapsed)
time.sleep(delay)
last_request_time = time.time()
if (idx + 1) % 10 == 0:
extra_delay = random.uniform(5, 10)
log_info(f"已签到 {idx + 1}/{total} 个贴吧,休息 {extra_delay:.2f}")
time.sleep(extra_delay)
forum_name = forum.get("name", "")
forum_id = forum.get("id", "")
level_id = forum.get("level_id", "?")
log_prefix = f"{forum_name}】吧(Lv.{level_id})({idx + 1}/{total})"
try:
data = base_data.copy()
data.update({"BDUSS": bduss, "fid": forum_id, "kw": forum_name, "tbs": tbs, "timestamp": str(int(time.time()))})
data = encode_data(data)
result = request(session, "http://c.tieba.baidu.com/c/c/forum/sign", "post", data)
error_code = result.get("error_code", "")
rank = None
if error_code == "0":
success_count += 1
if "user_info" in result:
rank = result["user_info"].get("user_sign_rank")
log_success(f"{log_prefix} 签到成功,第{rank}个签到" if rank else f"{log_prefix} 签到成功")
else:
log_success(f"{log_prefix} 签到成功")
details.append({"name": forum_name, "status": "success", "rank": rank, "level": level_id})
elif error_code == "160002":
exist_count += 1
log_warning(f"{log_prefix} {result.get('error_msg', '今日已签到')}")
details.append({"name": forum_name, "status": "exist", "rank": None, "level": level_id})
elif error_code == "340006":
shield_count += 1
log_warning(f"{log_prefix} 贴吧已被屏蔽")
details.append({"name": forum_name, "status": "shield", "rank": None, "level": level_id})
else:
error_count += 1
log_error(f"{log_prefix} 签到失败,错误: {result.get('error_msg', '未知错误')}")
details.append({"name": forum_name, "status": "error", "rank": None, "level": level_id})
except Exception as e:
error_count += 1
log_error(f"{log_prefix} 签到异常: {e!s}")
details.append({"name": forum_name, "status": "error", "rank": None, "level": level_id})
return {"total": total, "success": success_count, "exist": exist_count, "shield": shield_count, "error": error_count, "details": details}
def build_report(stats: Dict, user_name: str, details: List[Dict], level_summary: Optional[Dict] = None) -> str:
"""构建签到报告"""
lines = ["📢 百度贴吧 签到报告", "", f"👤 账号: {user_name}", ""]
lines.append("📊 签到统计")
lines.append(f"📌 贴吧总数: {stats['total']}")
lines.append(f"✅ 签到成功: {stats['success']}")
lines.append(f"⚠️ 已经签到: {stats['exist']}")
lines.append(f"🚫 被屏蔽的: {stats['shield']}")
lines.append(f"❌ 签到失败: {stats['error']}")
if level_summary:
lines.append("")
lines.append("🎯 等级汇总")
lines.append(f"📈 总经验值: {level_summary['total_exp']:,}")
top_levels = level_summary["level_stats"][:5]
level_dist = " | ".join([f"Lv.{lv}: {info['count']}个吧" for lv, info in top_levels])
lines.append(f"🏅 等级分布: {level_dist}")
if details:
lines.append("")
lines.append("📋 详细签到情况")
for d in details:
name = d["name"]
status = d["status"]
rank = d.get("rank")
level = d.get("level", "?")
if status == "success":
emoji = ""
rank_text = f" (第{rank}个)" if rank else ""
elif status == "exist":
emoji = "⚠️"; rank_text = ""
elif status == "shield":
emoji = "🚫"; rank_text = ""
else:
emoji = ""; rank_text = ""
lines.append(f"{emoji} {name} Lv.{level}{rank_text}")
lines.append("")
lines.append("" * 18)
lines.append(f"🕒 执行时间: {beijing_time_str()}")
return "\n".join(lines)
def main() -> Dict:
"""主流程"""
cookie_dict = {item.split("=")[0]: item.split("=")[1] for item in TIEBA_COOKIE.split("; ") if "=" in item}
bduss = cookie_dict.get("BDUSS", "")
if not bduss:
log_error("Cookie 中未找到 BDUSS请检查配置")
return {"user_name": "未知", "stats": {"total": 0, "success": 0, "exist": 0, "shield": 0, "error": 0}, "details": [], "level_summary": None}
session = create_session(TIEBA_COOKIE)
tbs, user_name = get_user_info(session)
if not tbs:
log_error(user_name)
return {"user_name": "登录失败", "stats": {"total": 0, "success": 0, "exist": 0, "shield": 0, "error": 0}, "details": [], "level_summary": None}
log_success(f"登录成功,用户名: {user_name}")
forums = get_favorite(session, bduss=bduss)
if not forums:
log_warning("未获取到任何贴吧,请检查 Cookie 或网络")
return {"user_name": user_name, "stats": {"total": 0, "success": 0, "exist": 0, "shield": 0, "error": 0}, "details": [], "level_summary": None}
level_summary = build_level_summary(forums)
log_info(f"总经验值: {level_summary['total_exp']:,},最高等级: Lv.{level_summary['level_stats'][0][0] if level_summary['level_stats'] else '?'}")
result = sign_forums(session, bduss, forums, tbs)
log_info(f"签到完成: 总数 {result['total']},成功 {result['success']},已签 {result['exist']},屏蔽 {result['shield']},失败 {result['error']}")
return {"user_name": user_name, "stats": result, "details": result["details"], "level_summary": level_summary}
if __name__ == "__main__":
result = main()
if result:
report = build_report(result["stats"], result["user_name"], result["details"], result.get("level_summary"))
notify_send("百度贴吧 签到报告", report)