1.购买服务器阿里云:服务器购买地址https://t.aliyun.com/U/PfsP97若失效,可用地址
阿里云:
服务器购买地址
https://t.aliyun.com/U/PfsP97若失效,可用地址
https://www.aliyun.com/activity/wuying/dj?source=5176.29345612&userCode=49hts92d腾讯云:
https://curl.qcloud.com/wJpWmSfU若失效,可用地址
https://cloud.tencent.com/act/cps/redirect?redirect=2446&cps_key=ad201ee2ef3b771157f72ee5464b1fea&from=console华为云
https://activity.huaweicloud.com/cps.html?fromacct=64b5cf7cc11b4840bb4ed2ea0b2f4468&utm_source=V1g3MDY4NTY=&utm_medium=cps&utm_campaign=2019052.部署教程
3.代码如下
"""cron: 39 17 * * *new Env('什么值得买签到')"""import requests, json, time, hashlib, os, random, refrom datetime import datetime, timedelta# ---------------- 统一通知模块加载 ----------------hadsend = Falsesend = None# 随机延迟配置max_random_delay = int(os.getenv("MAX_RANDOM_DELAY", "3600"))random_signin = os.getenv("RANDOM_SIGNIN", "true").lower() == "true"def format_time_remaining(seconds):"""格式化时间显示"""if seconds <= 0:return "立即执行"hours, minutes = divmod(seconds, 3600)minutes, secs = divmod(minutes, 60)if hours > 0:return f"{hours}小时{minutes}分{secs}秒"elif minutes > 0:return f"{minutes}分{secs}秒"else:return f"{secs}秒"def wait_with_countdown(delay_seconds, task_name):"""带倒计时的随机延迟等待"""if delay_seconds <= 0:returnprint(f"{task_name} 需要等待 {format_time_remaining(delay_seconds)}")remaining = delay_secondswhile remaining > 0:if remaining <= 10 or remaining % 10 == 0:print(f"{task_name} 倒计时: {format_time_remaining(remaining)}")sleep_time = 1 if remaining <= 10 else min(10, remaining)time.sleep(sleep_time)remaining -= sleep_timedef notify_user(title, content):"""统一通知函数"""if hadsend:try:send(title, content)print(f" 通知发送完成: {title}")except Exception as e:print(f" 通知发送失败: {e}")else:print(f" {title}\n📄 {content}")def get_user_info(cookie):"""获取用户基本信息"""try:print(" 正在获取用户信息...")infourl = 'https://zhiyou.smzdm.com/user/'headers = {'Host': 'zhiyou.smzdm.com','Accept': '*/*','Connection': 'keep-alive','Cookie': cookie,'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148/smzdm 10.4.6 rv:130.1 (iPhone 13; iOS 15.6; zh_CN)/iphone_smzdmapp/10.4.6/wkwebview/jsbv_1.0.0','Accept-Language': 'zh-CN,zh-Hans;q=0.9','Referer': 'https://m.smzdm.com/','Accept-Encoding': 'gzip, deflate, br'}response_info = requests.get(url=infourl, headers=headers, timeout=15).text# 解析用户信息name_match = re.search(r'<a href="https://zhiyou.smzdm.com/user"> (.*?) </a>', response_info)level_match = re.search(r'<img', response_info)gold_match = re.search(r'<div class="assets-part assets-gold">.*?<span class="assets-part-element assets-num">(.*?)</span>', response_info, re.S)silver_match = re.search(r'<div class="assets-part assets-prestige">.*?<span class="assets-part-element assets-num">(.*?)</span>', response_info, re.S)name = name_match.group(1).strip() if name_match else "未知用户"level = level_match.group(1) if level_match else "0"gold = gold_match.group(1).strip() if gold_match else "0"silver = silver_match.group(1).strip() if silver_match else "0"print(f" 用户: {name} (VIP{level})")print(f" 金币: {gold}, 碎银: {silver}")return name, level, gold, silverexcept Exception as e:print(f" 获取用户信息失败: {e}")return "未知用户", "0", "0", "0"def get_monthly_exp(cookie):"""获取本月经验"""try:print(" 正在获取本月经验...")current_month = datetime.now().strftime('%Y-%m')total_exp = 0for page in range(1, 4): # 查询前3页url = f'https://zhiyou.m.smzdm.com/user/exp/ajax_log?page={page}'headers = {'Host': 'zhiyou.m.smzdm.com','Accept': 'application/json, text/plain, */*','Connection': 'keep-alive','Cookie': cookie,'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148/smzdm 10.4.40 rv:137.6 (iPhone 13; iOS 15.6; zh_CN)/iphone_smzdmapp/10.4.40/wkwebview/jsbv_1.0.0','Accept-Language': 'zh-CN,zh-Hans;q=0.9','Referer': 'https://zhiyou.m.smzdm.com/user/exp/','Accept-Encoding': 'gzip, deflate, br'}resp = requests.get(url=url, headers=headers, timeout=10)if resp.status_code != 200:breakresult = resp.json()rows = result.get('data', {}).get('rows', [])if not rows:breakfor row in rows:exp_date = row.get('creation_date', '')[:7]if exp_date == current_month:total_exp += int(row.get('add_exp', 0))elif exp_date < current_month:# 如果日期小于当前月份,说明已经查完了return total_exp# 添加请求间隔time.sleep(random.uniform(0.5, 1.5))print(f" 本月经验: {total_exp}")return total_expexcept Exception as e:print(f" 获取月度经验失败: {e}")return 0def smzdm_signin(cookie, index):"""什么值得买签到 - 单个账号"""print(f"\n==== 开始第{index}个帐号签到 ====")try:# 0. 获取用户信息name, level, gold, silver = get_user_info(cookie)# 1. 获取Tokenprint(" 正在获取Token...")ts = int(round(time.time() * 1000))url = 'https://user-api.smzdm.com/robot/token'headers = {'Host': 'user-api.smzdm.com','Content-Type': 'application/x-www-form-urlencoded','Cookie': cookie,'User-Agent': 'smzdm_android_V10.4.1 rv:841 (22021211RC;Android12;zh)smzdmapp',}data = {"f": "android","v": "10.4.1","weixin": 1,"time": ts,"sign": hashlib.md5(bytes(f'f=android&time={ts}&v=10.4.1&weixin=1&key=apr1$AwP!wRRT$gJ/q.X24poeBInlUJC', encoding='utf-8')).hexdigest().upper()}html = requests.post(url=url, headers=headers, data=data, timeout=15)# 检查HTTP状态码if html.status_code != 200:error_msg = f" 账号{index}: HTTP请求失败,状态码: {html.status_code}"print(error_msg)return error_msg, False# 尝试解析JSONtry:result = html.json()except json.JSONDecodeError as e:error_msg = f" 账号{index}: 响应不是有效的JSON格式 - {str(e)}"print(error_msg)return error_msg, False# 检查API返回的错误码error_code = result.get('error_code')error_msg_api = result.get('error_msg', '未知错误')if str(error_code) != "0":error_msg = f" 账号{index}: Token获取失败 - 错误码: {error_code}, 错误信息: {error_msg_api}"print(error_msg)return error_msg, False# 检查是否有data字段和tokenif 'data' not in result or 'token' not in result['data']:error_msg = f" 账号{index}: 响应中缺少token数据 - {result}"print(error_msg)return error_msg, Falsetoken = result['data']['token']print(f" Token获取成功")# 2. 执行签到print(" 正在执行签到...")Timestamp = int(round(time.time() * 1000))sign_data = {"f": "android","v": "10.4.1","sk": "ierkM0OZZbsuBKLoAgQ6OJneLMXBQXmzX+LXkNTuKch8Ui2jGlahuFyWIzBiDq/L","weixin": 1,"time": Timestamp,"token": token,"sign": hashlib.md5(bytes(f'f=android&sk=ierkM0OZZbsuBKLoAgQ6OJneLMXBQXmzX+LXkNTuKch8Ui2jGlahuFyWIzBiDq/L&time={Timestamp}&token={token}&v=10.4.1&weixin=1&key=apr1$AwP!wRRT$gJ/q.X24poeBInlUJC', encoding='utf-8')).hexdigest().upper()}# 签到请求url_signin = 'https://user-api.smzdm.com/checkin'html_signin = requests.post(url=url_signin, headers=headers, data=sign_data, timeout=15)if html_signin.status_code != 200:error_msg = f" 账号{index}: 签到HTTP请求失败,状态码: {html_signin.status_code}"print(error_msg)return error_msg, Falsetry:signin_result = html_signin.json()except json.JSONDecodeError as e:error_msg = f" 账号{index}: 签到响应不是有效的JSON格式 - {str(e)}"print(error_msg)return error_msg, Falsesignin_msg = signin_result.get('error_msg', '签到状态未知')signin_code = signin_result.get('error_code', -1)print(f" 签到状态: {signin_msg}")# 3. 获取签到奖励print(" 正在查询签到奖励...")url_reward = 'https://user-api.smzdm.com/checkin/all_reward'html_reward = requests.post(url=url_reward, headers=headers, data=sign_data, timeout=15)reward_info = ""if html_reward.status_code == 200:try:reward_result = html_reward.json()if str(reward_result.get('error_code')) == "0" and reward_result.get('data'):normal_reward = reward_result["data"].get("normal_reward", {})if normal_reward:reward_content = normal_reward.get("reward_add", {}).get("content", "无奖励")sub_title = normal_reward.get("sub_title", "无连续签到信息")reward_info = f"\n 签到奖励: {reward_content}\n📅 连续签到: {sub_title}"print(f" 签到奖励: {reward_content}")print(f" 连续签到: {sub_title}")except Exception as e:print(f" 奖励信息解析失败: {e}")else:print(f" 奖励查询失败,状态码: {html_reward.status_code}")# 4. 获取本月经验monthly_exp = get_monthly_exp(cookie)# 5. 组合结果消息final_msg = f"""什么值得买签到结果账号: 第{index}个账号 ({name})等级: VIP{level}金币: {gold}碎银: {silver}本月经验: {monthly_exp}签到状态: {signin_msg}状态码: {signin_code}{reward_info}签到时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"""# 判断是否成功is_success = (str(signin_code) == "0" or"成功" in signin_msg or"已经" in signin_msg or"重复" in signin_msg or"已签" in signin_msg)print(f"{' 签到成功' if is_success else ' 签到失败'}")return final_msg, is_successexcept requests.exceptions.Timeout:error_msg = f" 账号{index}: 请求超时,网络连接可能有问题"print(error_msg)return error_msg, Falseexcept requests.exceptions.ConnectionError:error_msg = f" 账号{index}: 网络连接错误,无法连接到服务器"print(error_msg)return error_msg, Falseexcept Exception as e:error_msg = f" 账号{index}: 签到异常 - {str(e)}"print(error_msg)return error_msg, Falsedef main():"""主程序入口"""print(f"==== 什么值得买签到开始 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} ====")# 随机延迟(整体延迟)if random_signin:delay_seconds = random.randint(0, max_random_delay)if delay_seconds > 0:signin_time = datetime.now() + timedelta(seconds=delay_seconds)print(f"🎲 随机模式: 延迟 {format_time_remaining(delay_seconds)} 后开始")print(f"⏰ 预计开始时间: {signin_time.strftime('%H:%M:%S')}")wait_with_countdown(delay_seconds, "什么值得买签到")# 获取环境变量SMZDM_COOKIE_env = os.getenv("SMZDM_COOKIE")if not SMZDM_COOKIE_env:error_msg = " 未找到SMZDM_COOKIE环境变量,请设置什么值得买Cookie"print(error_msg)notify_user("什么值得买签到失败", error_msg)return# 解析多账号CookieSMZDM_COOKIEs = SMZDM_COOKIE_env.split('&')print(f" 共发现 {len(SMZDM_COOKIEs)} 个账号")success_count = 0total_count = len(SMZDM_COOKIEs)for i, cookie in enumerate(SMZDM_COOKIEs):try:# 账号间随机等待if i > 0:delay = random.uniform(5, 15)print(f" 随机等待 {delay:.1f} 秒后处理下一个账号...")time.sleep(delay)# 执行签到result_msg, is_success = smzdm_signin(cookie.strip(), i + 1)if is_success:success_count += 1# 发送单个账号通知title = f"什么值得买账号{i + 1}签到{'成功' if is_success else '失败'}"notify_user(title, result_msg)except Exception as e:error_msg = f" 账号{i + 1}: 处理异常 - {str(e)}"print(error_msg)notify_user(f"什么值得买账号{i + 1}签到失败", error_msg)# 发送汇总通知if total_count > 1:summary_msg = f"""什么值得买签到汇总总计处理: {total_count}个账号签到成功: {success_count}个账号签到失败: {total_count - success_count}个账号成功率: {success_count/total_count*100:.1f}%完成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"""notify_user("什么值得买签到汇总", summary_msg)print(f"\n==== 什么值得买签到完成 - 成功{success_count}/{total_count} - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} ====")if __name__ == "__main__":main()
该脚本为自动化什么值得买签到脚本,主要作用包括:
自动签到 SMZDM:获取
token→ 生成签名参数 → 调用签到接口。查询并汇报:抓取用户昵称/等级/金币/碎银、当月经验,查询签到奖励,整合成结果消息。
多账号支持:从环境变量
SMZDM_COOKIE读取多个账号(用&分隔)逐个执行。随机延迟与风控友好:可配置整体随机延迟与账号间随机等待,降低并发痕迹。
关键配置与输入
环境变量
SMZDM_COOKIE:必填,支持多账号,&分隔;直接作为请求Cookie头。MAX_RANDOM_DELAY、RANDOM_SIGNIN:控制整体随机延迟。依赖:
requests、re/json/time/datetime/random/hashlib
主要方法的作用
通用与通知
format_time_remaining(seconds)
将秒数格式化为"X小时Y分Z秒"的友好字符串。wait_with_countdown(delay_seconds, task_name)
倒计时等待(整体随机延迟可视化打印),每 10 秒或最后 10 秒逐秒提示。
用户与经验查询
get_user_info(cookie)
用移动端 UA 访问https://zhiyou.smzdm.com/user/,用正则解析:用户名、等级(VIP)、金币、碎银(页面元素抓取)。
get_monthly_exp(cookie)
访问https://zhiyou.m.smzdm.com/user/exp/ajax_log?page=…(前 3 页)
汇总 当月新增经验(按creation_date前 7 位对齐YYYY-MM)。
签到核心
smzdm_signin(cookie, index)(单账号全流程)解析
normal_reward.reward_add.content、sub_title(连续签到信息)。需带上 token 与另一个
sign(同样按固定模板计算 MD5)。关键参数:
f=android, v=10.4.1, weixin=1, time=毫秒时间戳sign为 MD5(按固定顺序串 + 固定 key),再upper()。获取基本信息:调用
get_user_info。取 Token:POST
https://user-api.smzdm.com/robot/token执行签到:POST
https://user-api.smzdm.com/checkin查询签到奖励:POST
https://user-api.smzdm.com/checkin/all_reward查当月经验:调用
get_monthly_exp。结果整合:拼装账号信息、签到状态码/文案、奖励、经验、时间等;
判断"成功/已签/重复"等文案视为成功,返回(msg, is_success)。异常处理:对网络超时、连接错误、JSON 解析异常、非 200 状态码等都返回明确错误信息。
主控
main()打印启动时间 → (可选)整体随机延迟(
wait_with_countdown)。读取并拆分
SMZDM_COOKIE多账号 → 逐个执行smzdm_signin。账号间随机停顿(5–15 秒)。
每个账号执行完发送单账号通知;最后多账号给出成功率汇总通知。
控制台输出总成绩与结束时间。
调用链总览(单账号)
smzdm_signin├─ get_user_info # 页面解析昵称/等级/金币/碎银├─ 获取token(签名MD5) # /robot/token├─ 签到(签名MD5+token) # /checkin├─ 查询签到奖励 # /checkin/all_reward├─ get_monthly_exp # /user/exp/ajax_log└─ 组合消息 & 返回状态
注意:
本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。
【相关文章】
没有评论:
发表评论