mirror of
https://github.com/wd210010/only_for_happly.git
synced 2026-11-05 20:26:45 +08:00
Create tyqh.py
This commit is contained in:
1 parent
3b75c6cdba
commit
354f5cc7dc
1 file changed
+276
@@ -0,0 +1,276 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import requests
|
||||
import time
|
||||
import os
|
||||
import random
|
||||
import urllib.parse
|
||||
from requests.exceptions import RequestException
|
||||
|
||||
# ==============================================================================
|
||||
# 【环境变量QH配置说明】
|
||||
# 1. 格式:
|
||||
# - 单账号:直接填写wid(例:123456)
|
||||
# - 多账号:支持两种分隔方式,可混合使用
|
||||
# - &分隔:123&456&789
|
||||
# - 换行分隔:每个wid单独占一行(Windows/Linux换行符均兼容)
|
||||
# 2. 关键:脚本仅内部使用wid登录,所有输出不显示wid;UA自动生成(适配小程序)
|
||||
'''
|
||||
不用抓包,直接登录小程序。
|
||||
个人中心---用户设置---用户编号就是需要的wid信息
|
||||
'''
|
||||
# ==============================================================================
|
||||
# -------------------------- 【配置+工具函数】--------------------------
|
||||
def generate_random_ua():
|
||||
"""生成随机UA(适配小程序环境)"""
|
||||
os_mobile_map = [
|
||||
("15_8_3", "15E148"),
|
||||
("16_2_0", "16F203"),
|
||||
("16_5_1", "16H62"),
|
||||
("17_0_3", "17A5844a"),
|
||||
("17_1_1", "17B100"),
|
||||
("17_2_0", "17C304"),
|
||||
("17_3_1", "17D50"),
|
||||
("17_4_1", "17E262"),
|
||||
("17_6_1", "15E148")
|
||||
]
|
||||
os_version, mobile_version = random.choice(os_mobile_map)
|
||||
wechat_version = f"8.0.{random.randint(50, 75)}"
|
||||
return (
|
||||
f"Mozilla/5.0 (iPhone; CPU iPhone OS {os_version} like Mac OS X) "
|
||||
"AppleWebKit/605.1.15 (KHTML, like Gecko) "
|
||||
f"Mobile/{mobile_version} MicroMessenger/{wechat_version} "
|
||||
"NetType/WIFI Language/zh_CN miniProgram/wx532ecb3bdaaf92f9"
|
||||
)
|
||||
|
||||
def parse_qh_env():
|
||||
"""解析QH环境变量(支持&和换行分隔多账号)"""
|
||||
qh_env = os.getenv("QH", "")
|
||||
if not qh_env:
|
||||
print("❌ 错误:未检测到环境变量QH,请按配置说明设置!")
|
||||
return None
|
||||
|
||||
unified_env = qh_env.replace("\r\n", "&").replace("\n", "&")
|
||||
account_str_list = unified_env.split("&")
|
||||
|
||||
accounts = []
|
||||
for idx, account_str in enumerate(account_str_list, 1):
|
||||
wid = account_str.strip()
|
||||
if not wid:
|
||||
print(f"⚠️ 检测到第{idx}个无效项(空内容),已跳过")
|
||||
continue
|
||||
|
||||
ua = generate_random_ua()
|
||||
accounts.append({
|
||||
"index": idx,
|
||||
"wid": wid,
|
||||
"token": "",
|
||||
"ua": ua,
|
||||
"user_data": {},
|
||||
"land_data": []
|
||||
})
|
||||
|
||||
if not accounts:
|
||||
print("❌ 没有可用账号(所有项格式错误或为空),脚本终止")
|
||||
return None
|
||||
return accounts
|
||||
|
||||
def get_account_headers(account):
|
||||
"""生成账号请求头(匹配抓包标准)"""
|
||||
headers = {
|
||||
"Authorization": account["token"],
|
||||
"User-Agent": account["ua"],
|
||||
"Origin": "https://h5.zhumanito.cn",
|
||||
"Referer": "https://h5.zhumanito.cn/",
|
||||
"Accept-Language": "zh-CN,zh-Hans;q=0.9",
|
||||
"Accept-Encoding": "gzip, deflate, br",
|
||||
"Connection": "keep-alive"
|
||||
}
|
||||
# 补充Cookie标识,模拟真实用户
|
||||
if account.get("wid"):
|
||||
headers["Cookie"] = f"rprm_cuid={account['wid']}; rprm_uuid={account['wid']}"
|
||||
return headers
|
||||
|
||||
def login_account(account):
|
||||
"""账号自动登录(隐藏wid显示)"""
|
||||
login_url = "https://api.zhumanito.cn/api/login"
|
||||
headers = get_account_headers(account)
|
||||
headers["Content-Type"] = "application/json;charset=utf-8"
|
||||
payload = {"wid": account["wid"]}
|
||||
|
||||
try:
|
||||
print(f"🔐 账号{account['index']}:发起登录请求")
|
||||
response = requests.post(login_url, headers=headers, json=payload, timeout=20)
|
||||
response.raise_for_status()
|
||||
res = response.json()
|
||||
|
||||
if res.get("code") != 200:
|
||||
print(f"❌ 账号{account['index']}:登录失败,原因:{res.get('msg', '未知错误')}")
|
||||
return False
|
||||
|
||||
account["token"] = res["data"]["token"]
|
||||
account["user_data"] = res["data"]["user"]
|
||||
account["land_data"] = res["data"].get("land", [])
|
||||
|
||||
print(f"✅ 账号{account['index']}:登录成功!")
|
||||
print(f" 📌 当前资源:💧{account['user_data']['water_num']},☀️{account['user_data']['sun_num']},🍀{account['user_data']['seed_num']},🍎{account['user_data']['fruit_num']}")
|
||||
if account["land_data"]:
|
||||
print(f" 🌱 土地状态:共{len(account['land_data'])}块,生长阶段{account['land_data'][0]['seed_stage']}")
|
||||
return True
|
||||
|
||||
except RequestException as e:
|
||||
print(f"❌ 账号{account['index']}:登录异常,原因:{str(e)}")
|
||||
return False
|
||||
|
||||
def get_user_status(account):
|
||||
"""获取账号当前资源(水、阳光、种子、果实)"""
|
||||
if not account.get("user_data"):
|
||||
print(f"⚠️ 账号{account['index']}:未获取到用户数据,返回默认资源值0")
|
||||
return 0, 0, 0, 0
|
||||
water = account["user_data"].get("water_num", 0)
|
||||
sun = account["user_data"].get("sun_num", 0)
|
||||
seed = account["user_data"].get("seed_num", 0)
|
||||
fruit = account["user_data"].get("fruit_num", 0)
|
||||
return water, sun, seed, fruit
|
||||
|
||||
def check_land_mature(account):
|
||||
"""检查土地是否成熟(seed_stage=0 或 5 判定为可收获/可播种)"""
|
||||
if not account.get("land_data"):
|
||||
print(f"⚠️ 账号{account['index']}:未获取到土地数据,默认判定为未成熟")
|
||||
return False
|
||||
return any(land["seed_stage"] in (0, 5) for land in account["land_data"])
|
||||
|
||||
# -------------------------- 【核心操作函数】--------------------------
|
||||
def complete_harvest(headers, account_idx, account):
|
||||
"""执行收获操作(支持seed_stage=0/5成熟阶段)"""
|
||||
harvest_url = "https://api.zhumanito.cn/api/harvest"
|
||||
try:
|
||||
mature_stages = [land["seed_stage"] for land in account["land_data"] if land["seed_stage"] in (0, 5)]
|
||||
print("=" * 35)
|
||||
print(f"🍎 账号{account_idx}:开始执行收获操作(成熟阶段:{mature_stages})")
|
||||
harvest_headers = headers.copy()
|
||||
harvest_headers["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8"
|
||||
|
||||
response = requests.post(harvest_url, headers=harvest_headers, data=b"", timeout=(25, 30))
|
||||
response.raise_for_status()
|
||||
res = response.json()
|
||||
|
||||
if res.get("code") != 200:
|
||||
print(f"❌ 账号{account_idx}:收获失败,原因:{res.get('msg', '未知错误')}")
|
||||
return False
|
||||
|
||||
account["user_data"] = res["data"]["user"]
|
||||
account["land_data"] = res["data"].get("land", [])
|
||||
|
||||
current_water, current_sun, current_seed, current_fruit = get_user_status(account)
|
||||
land_count = len(account["land_data"])
|
||||
print(f"✅ 账号{account_idx}:收获成功!")
|
||||
print(f"📊 收获后资源:💧{current_water},☀️{current_sun},🍀{current_seed},🍎{current_fruit}")
|
||||
if land_count > 0:
|
||||
print(f"🌱 土地状态:共{land_count}块,当前阶段{account['land_data'][0]['seed_stage']}")
|
||||
print("=" * 35)
|
||||
return True
|
||||
|
||||
except RequestException as e:
|
||||
print(f"❌ 账号{account_idx}:收获异常,原因:{str(e)}")
|
||||
return False
|
||||
|
||||
def complete_seed(headers, account_idx, account):
|
||||
"""执行播种操作(无重试)"""
|
||||
seed_url = "https://api.zhumanito.cn/api/seed"
|
||||
_, _, current_seed, _ = get_user_status(account)
|
||||
if current_seed < 1:
|
||||
print(f"⚠️ 账号{account_idx}:种子数量不足(当前🍀{current_seed}),无法播种")
|
||||
return False
|
||||
|
||||
try:
|
||||
print("=" * 35)
|
||||
print(f"🌱 账号{account_idx}:开始执行播种操作(当前种子:🍀{current_seed})")
|
||||
seed_headers = headers.copy()
|
||||
seed_headers["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8"
|
||||
|
||||
response = requests.post(seed_url, headers=seed_headers, data=b"", timeout=(25, 30))
|
||||
response.raise_for_status()
|
||||
res = response.json()
|
||||
|
||||
if res.get("code") != 200:
|
||||
print(f"❌ 账号{account_idx}:播种失败,原因:{res.get('msg', '未知错误')}")
|
||||
return False
|
||||
|
||||
account["user_data"] = res["data"]["user"]
|
||||
account["land_data"] = res["data"]["land"]
|
||||
|
||||
current_water, current_sun, new_seed, current_fruit = get_user_status(account)
|
||||
land_count = len(account["land_data"])
|
||||
print(f"✅ 账号{account_idx}:播种成功!")
|
||||
print(f"📊 播种后资源:💧{current_water},☀️{current_sun},🍀{new_seed},🍎{current_fruit}")
|
||||
print(f"🌱 土地状态:共{land_count}块,生长阶段{account['land_data'][0]['seed_stage']}")
|
||||
print("=" * 35)
|
||||
return True
|
||||
|
||||
except RequestException as e:
|
||||
print(f"❌ 账号{account_idx}:播种异常,原因:{str(e)}")
|
||||
return False
|
||||
|
||||
# -------------------------- 【主流程】--------------------------
|
||||
def auto_multi_account():
|
||||
"""多账号自动处理主流程:登录→检测成熟→收获→播种"""
|
||||
accounts = parse_qh_env()
|
||||
if not accounts:
|
||||
return
|
||||
|
||||
for account in accounts:
|
||||
account_idx = account["index"]
|
||||
total_accounts = len(accounts)
|
||||
print(f"\n" + "=" * 35)
|
||||
print(f"📌 正在处理账号 {account_idx}/{total_accounts}")
|
||||
print("=" * 35)
|
||||
|
||||
# 1. 账号登录
|
||||
login_success = login_account(account)
|
||||
if not login_success:
|
||||
print(f"❌ 账号{account_idx}:登录失败,跳过后续所有操作")
|
||||
continue
|
||||
|
||||
# 2. 获取请求头
|
||||
account_headers = get_account_headers(account)
|
||||
|
||||
# 3. 收获→播种流程
|
||||
print(f"\n🔄 账号{account_idx}:进入收获→播种流程")
|
||||
|
||||
# 3.1 检测土地成熟度并收获
|
||||
if check_land_mature(account):
|
||||
print(f"\n📌 账号{account_idx}:检测到土地成熟,执行收获")
|
||||
harvest_success = complete_harvest(account_headers, account_idx, account)
|
||||
if harvest_success:
|
||||
time.sleep(2)
|
||||
else:
|
||||
print(f"\n📌 账号{account_idx}:土地未成熟,跳过收获")
|
||||
|
||||
# 3.2 播种(种子≥1且土地可播种)
|
||||
_, _, current_seed, _ = get_user_status(account)
|
||||
if current_seed >= 1 and check_land_mature(account):
|
||||
print(f"\n📌 账号{account_idx}:种子充足且土地可播种,执行播种")
|
||||
complete_seed(account_headers, account_idx, account)
|
||||
else:
|
||||
print(f"\n📌 账号{account_idx}:种子不足(🍀{current_seed})或土地不可播种,跳过播种")
|
||||
|
||||
# 单个账号处理完成
|
||||
print(f"\n✅ 账号{account_idx}/{total_accounts}:收获播种流程处理完毕")
|
||||
if account_idx < total_accounts:
|
||||
delay_time = 5
|
||||
print(f"⏳ 账号间延迟{delay_time}秒,准备处理下一个账号...\n")
|
||||
time.sleep(delay_time)
|
||||
|
||||
# 所有账号处理完成
|
||||
print("\n" + "=" * 35)
|
||||
print("🎯 所有账号收获播种流程已全部处理完成!脚本执行结束")
|
||||
print("=" * 35)
|
||||
|
||||
# 脚本入口
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
auto_multi_account()
|
||||
except KeyboardInterrupt:
|
||||
print(f"\n" + "=" * 35)
|
||||
print("⚠️ 脚本被手动终止")
|
||||
print("=" * 35)
|
||||
Reference in new issue
Block a user