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.代码如下
#!/usr/bin/python3# -*- coding: utf-8 -*-"""cron "9 15 * * *" script-path=xxx.py,tag=匹配cron用new Env('顺丰速运签到')"""import hashlibimport jsonimport osimport randomimport timefrom datetime import datetime, timedeltaimport requestsfrom requests.packages.urllib3.exceptions import InsecureRequestWarningfrom urllib.parse import unquote# 禁用安全请求警告requests.packages.urllib3.disable_warnings(InsecureRequestWarning)hadsend = Falsesend = None# 随机延迟配置max_random_delay = int(os.getenv("MAX_RANDOM_DELAY", "3600"))random_signin = os.getenv("RANDOM_SIGNIN", "true").lower() == "true"# 全局日志变量send_msg = ''one_msg = ''def Log(cont=''):"""记录日志"""global send_msg, one_msgprint(cont)if cont:one_msg += f'{cont}\n'send_msg += f'{cont}\n'def format_time_remaining(seconds):"""格式化时间显示"""if seconds <= 0:return "立即执行"hours = seconds // 3600minutes = (seconds % 3600) // 60secs = seconds % 60if 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:returnLog(f"{task_name} 需要等待 {format_time_remaining(delay_seconds)}")remaining = delay_secondswhile remaining > 0:if remaining <= 10 or remaining % 10 == 0:Log(f"{task_name} 倒计时: {format_time_remaining(remaining)}")sleep_time = 1 if remaining <= 10 else min(10, remaining)time.sleep(sleep_time)remaining -= sleep_timeinviteId = ['']class RUN:def __init__(self, info, index):"""初始化账号信息"""global one_msgone_msg = ''split_info = info.split('@')url = split_info[0]self.send_UID = split_info[-1] if len(split_info) > 1 and "UID_" in split_info[-1] else Noneself.index = index + 1self.s = requests.session()self.s.verify = Falseself.headers = {'Host': 'mcs-mimp-web.sf-express.com','upgrade-insecure-requests': '1','user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 NetType/WIFI MicroMessenger/7.0.20.1781(0x6700143B) WindowsWechat(0x6309092b) XWEB/6763 Flue','accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9','sec-fetch-site': 'none','sec-fetch-mode': 'navigate','sec-fetch-user': '?1','sec-fetch-dest': 'document','accept-language': 'zh-CN,zh','platform': 'MINI_PROGRAM',}# 会员日活动相关属性self.member_day_black = Falseself.member_day_red_packet_drew_today = Falseself.member_day_red_packet_map = {}self.today = datetime.now().strftime('%Y-%m-%d')self.max_level = 8self.packet_threshold = 1 << (self.max_level - 1)self.login_res = self.login(url)def get_deviceId(self, characters='abcdef0123456789'):"""生成随机设备ID"""result = ''for char in 'xxxxxxxx-xxxx-xxxx':if char == 'x':result += random.choice(characters)else:result += charreturn resultdef login(self, sfurl):"""登录顺丰账号"""try:ress = self.s.get(sfurl, headers=self.headers)self.user_id = self.s.cookies.get_dict().get('_login_user_id_', '')self.phone = self.s.cookies.get_dict().get('_login_mobile_', '')self.mobile = self.phone[:3] + "*" * 4 + self.phone[7:] if self.phone else ''if self.phone:Log(f' 账号{self.index}:【{self.mobile}】登陆成功')return Trueelse:Log(f' 账号{self.index}获取用户信息失败')return Falseexcept Exception as e:Log(f' 登录异常: {str(e)}')return Falsedef getSign(self):"""生成请求签名"""timestamp = str(int(time.time() * 1000))token = 'wwesldfs29aniversaryvdld29'sysCode = 'MCS-MIMP-CORE'data = f'token={token}×tamp={timestamp}&sysCode={sysCode}'signature = hashlib.md5(data.encode()).hexdigest()data = {'sysCode': sysCode,'timestamp': timestamp,'signature': signature}self.headers.update(data)return datadef do_request(self, url, data=None, req_type='post', max_retries=3):"""发送HTTP请求"""self.getSign()for retry_count in range(max_retries):try:if req_type.lower() == 'get':response = self.s.get(url, headers=self.headers, timeout=30)elif req_type.lower() == 'post':response = self.s.post(url, headers=self.headers, json=data or {}, timeout=30)else:raise ValueError(f'Invalid req_type: {req_type}')response.raise_for_status()return response.json()except (requests.exceptions.RequestException, json.JSONDecodeError) as e:Log(f' 请求失败 ({retry_count + 1}/{max_retries}): {str(e)}')if retry_count < max_retries - 1:time.sleep(2)continuereturn {'success': False, 'errorMessage': str(e)}return {'success': False, 'errorMessage': 'All retries failed'}def sign(self):"""执行签到任务"""Log(' 开始执行签到')json_data = {"comeFrom": "vioin", "channelFrom": "WEIXIN"}url = 'https://sf-express.com/mcs-mimp/commonPost/~memberNonactivity~integralTaskSignPlusService~automaticSignFetchPackage'response = self.do_request(url, data=json_data)if response.get('success'):count_day = response.get('obj', {}).get('countDay', 0)if response.get('obj', {}).get('integralTaskSignPackageVOList'):packet_name = response["obj"]["integralTaskSignPackageVOList"][0]["packetName"]Log(f' 签到成功,获得【{packet_name}】,本周累计签到【{count_day + 1}】天')else:Log(f' 今日已签到,本周累计签到【{count_day + 1}】天')else:Log(f' 签到失败!原因:{response.get("errorMessage", "未知错误")}')def get_SignTaskList(self, end=False):"""获取签到任务列表"""Log(' 开始获取签到任务列表' if not end else ' 查询最终积分')json_data = {"channelType": "1", "deviceId": self.get_deviceId()}url = 'https://sf-express.com/mcs-mimp/commonPost/~memberNonactivity~integralTaskStrategyService~queryPointTaskAndSignFromES'response = self.do_request(url, data=json_data)if response.get('success') and response.get('obj'):totalPoint = response["obj"]["totalPoint"]Log(f' {"执行前" if not end else "当前"}积分:【{totalPoint}】')if not end:for task in response["obj"]["taskTitleLevels"]:self.taskId = task["taskId"]self.taskCode = task["taskCode"]self.strategyId = task["strategyId"]self.title = task["title"]status = task["status"]skip_title = ['用行业模板寄件下单', '去新增一个收件偏好', '参与积分活动']if status == 3:Log(f' {self.title}-已完成')continueif self.title in skip_title:Log(f' {self.title}-跳过')continueself.doTask()time.sleep(2)self.receiveTask()def doTask(self):"""完成签到任务"""Log(f' 开始去完成【{self.title}】任务')json_data = {"taskCode": self.taskCode}url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonRoutePost/memberEs/taskRecord/finishTask'response = self.do_request(url, data=json_data)Log(f'✨ 【{self.title}】任务-{"已完成" if response.get("success") else response.get("errorMessage", "失败")}')def receiveTask(self):"""领取签到任务奖励"""Log(f' 开始领取【{self.title}】任务奖励')json_data = {"strategyId": self.strategyId,"taskId": self.taskId,"taskCode": self.taskCode,"deviceId": self.get_deviceId()}url = 'https://sf-express.com/mcs-mimp/commonPost/~memberNonactivity~integralTaskStrategyService~fetchIntegral'response = self.do_request(url, data=json_data)Log(f'✨ 【{self.title}】任务奖励-{"领取成功" if response.get("success") else response.get("errorMessage", "失败")}')def do_honeyTask(self):"""完成丰蜜任务"""Log(f' 开始完成【{self.taskType}】任务')json_data = {"taskCode": self.taskCode}url = 'https://sf-express.com/mcs-mimp/commonPost/~memberEs~taskRecord~finishTask'response = self.do_request(url, data=json_data)Log(f' 【{self.taskType}】任务-{"已完成" if response.get("success") else response.get("errorMessage", "失败")}')def receive_honeyTask(self):"""领取丰蜜任务奖励"""Log(f' 领取【{self.taskType}】丰蜜任务')self.headers.update({'syscode': 'MCS-MIMP-CORE','channel': 'wxwdsj','accept': 'application/json, text/plain, */*','content-type': 'application/json;charset=UTF-8','platform': 'MINI_PROGRAM'})json_data = {"taskType": self.taskType}url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~receiveExchangeIndexService~receiveHoney'response = self.do_request(url, data=json_data)Log(f' 收取任务【{self.taskType}】-{"成功" if response.get("success") else response.get("errorMessage", "失败")}')def get_coupom(self, goods):"""领取优惠券"""json_data = {"from": "Point_Mall","orderSource": "POINT_MALL_EXCHANGE","goodsNo": goods['goodsNo'],"quantity": 1,"taskCode": self.taskCode}url = 'https://sf-express.com/mcs-mimp/commonPost/~memberGoods~pointMallService~createOrder'response = self.do_request(url, data=json_data)return response.get('success')def get_coupom_list(self):"""获取优惠券列表"""json_data = {"memGrade": 2, "categoryCode": "SHTQ", "showCode": "SHTQWNTJ"}url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberGoods~mallGoodsLifeService~list'response = self.do_request(url, data=json_data)if response.get('success'):all_goods = []for obj in response.get("obj", []):all_goods.extend(obj.get("goodsList", []))for goods in all_goods:if goods.get('exchangeTimesLimit', 0) >= 1:if self.get_coupom(goods):Log('✨ 成功领取券,任务结束!')returnLog('📝 所有券尝试完成,没有可用的券或全部领取失败。')else:Log(f'❌ 获取券列表失败!原因:{response.get("errorMessage", "未知错误")}')def get_honeyTaskListStart(self):"""获取丰蜜任务列表"""Log(' 开始获取采蜜换大礼任务列表')self.headers['channel'] = 'wxwdsj'url = 'https://sf-express.com/mcs-mimp/commonPost/~memberNonactivity~receiveExchangeIndexService~taskDetail'response = self.do_request(url, data={})if response.get('success'):for item in response["obj"]["list"]:self.taskType = item["taskType"]status = item["status"]if status == 3:Log(f'✨ 【{self.taskType}】-已完成')continueif "taskCode" in item:self.taskCode = item["taskCode"]if self.taskType == 'DAILY_VIP_TASK_TYPE':self.get_coupom_list()else:self.do_honeyTask()if self.taskType == 'BEES_GAME_TASK_TYPE':self.honey_damaoxian()time.sleep(2)def honey_damaoxian(self):"""执行大冒险任务"""Log('>>> 执行大冒险任务')gameNum = 5for i in range(1, gameNum + 1):json_data = {"gatherHoney": 20}Log(f'>> 开始第{i}次大冒险')url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~receiveExchangeGameService~gameReport'response = self.do_request(url, data=json_data)if response.get('success'):gameNum = response.get('obj')['gameNum']Log(f'> 大冒险成功!剩余次数【{gameNum}】')time.sleep(2)elif response.get("errorMessage") == '容量不足':Log('> 需要扩容')self.honey_expand()else:Log(f'> 大冒险失败!【{response.get("errorMessage", "未知错误")}】')breakdef honey_expand(self):"""容器扩容"""Log('>>> 容器扩容')url = 'https://sf-express.com/mcs-mimp/commonPost/~memberNonactivity~receiveExchangeIndexService~expand'response = self.do_request(url, data={})if response.get('success'):Log(f'> 成功扩容【{response.get("obj", "未知")}】容量')else:Log(f'> 扩容失败!【{response.get("errorMessage", "未知错误")}】')def honey_indexData(self, end=False):"""执行采蜜换大礼任务"""Log(' 开始执行采蜜换大礼任务' if not end else '🍯 查询最终丰蜜')random_invite = random.choice([invite for invite in inviteId if invite != self.user_id])self.headers['channel'] = 'wxwdsj'json_data = {"inviteUserId": random_invite}url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~receiveExchangeIndexService~indexData'response = self.do_request(url, data=json_data)if response.get('success'):usableHoney = response.get('obj').get('usableHoney')activityEndTime = response.get('obj').get('activityEndTime', '')if not end:Log(f' 本期活动结束时间【{activityEndTime}】')Log(f' 执行前丰蜜:【{usableHoney}】')for task in response.get('obj').get('taskDetail', []):self.taskType = task['type']self.receive_honeyTask()time.sleep(2)else:Log(f'🍯 执行后丰蜜:【{usableHoney}】')def member_day_index(self):"""执行会员日活动"""Log(' 会员日活动')invite_user_id = random.choice([invite for invite in inviteId if invite != self.user_id])payload = {'inviteUserId': invite_user_id}url = 'https://sf-express.com/mcs-mimp/commonPost/~memberNonactivity~memberDayIndexService~index'response = self.do_request(url, data=payload)if response.get('success'):lottery_num = response.get('obj', {}).get('lotteryNum', 0)can_receive_invite_award = response.get('obj', {}).get('canReceiveInviteAward', False)if can_receive_invite_award:self.member_day_receive_invite_award(invite_user_id)self.member_day_red_packet_status()Log(f' 会员日可以抽奖{lottery_num}次')for _ in range(lottery_num):self.member_day_lottery()if self.member_day_black:returnself.member_day_task_list()if self.member_day_black:returnself.member_day_red_packet_status()else:error_message = response.get('errorMessage', '无返回')Log(f' 查询会员日失败: {error_message}')if '没有资格参与活动' in error_message:self.member_day_black = TrueLog(' 会员日任务风控')def member_day_receive_invite_award(self, invite_user_id):"""领取会员日邀请奖励"""payload = {'inviteUserId': invite_user_id}url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~memberDayIndexService~receiveInviteAward'response = self.do_request(url, data=payload)if response.get('success'):product_name = response.get('obj', {}).get('productName', '空气')Log(f' 会员日奖励: {product_name}')else:error_message = response.get('errorMessage', '无返回')Log(f' 领取会员日奖励失败: {error_message}')if '没有资格参与活动' in error_message:self.member_day_black = TrueLog(' 会员日任务风控')def member_day_lottery(self):"""会员日抽奖"""url = 'https://sf-express.com/mcs-mimp/commonPost/~memberNonactivity~memberDayLotteryService~lottery'response = self.do_request(url, data={})if response.get('success'):product_name = response.get('obj', {}).get('productName', '空气')Log(f' 会员日抽奖: {product_name}')else:error_message = response.get('errorMessage', '无返回')Log(f' 会员日抽奖失败: {error_message}')if '没有资格参与活动' in error_message:self.member_day_black = TrueLog(' 会员日任务风控')def member_day_task_list(self):"""获取会员日任务列表"""payload = {'activityCode': 'MEMBER_DAY', 'channelType': 'MINI_PROGRAM'}url = 'https://sf-express.com/mcs-mimp/commonPost/~memberNonactivity~activityTaskService~taskList'response = self.do_request(url, data=payload)if response.get('success'):task_list = response.get('obj', [])for task in task_list:if task['status'] == 1:if self.member_day_black:returnself.member_day_fetch_mix_task_reward(task)elif task['status'] == 2 and task['taskType'] not in ['SEND_SUCCESS', 'INVITEFRIENDS_PARTAKE_ACTIVITY', 'OPEN_SVIP','OPEN_NEW_EXPRESS_CARD', 'OPEN_FAMILY_CARD', 'CHARGE_NEW_EXPRESS_CARD','INTEGRAL_EXCHANGE', 'OPEN_SUPER_CARD' # 添加购买至尊会员到跳过列表]:for _ in range(task['restFinishTime']):if self.member_day_black:returnself.member_day_finish_task(task)else:error_message = response.get('errorMessage', '无返回')Log(f'📝 查询会员日任务失败: {error_message}')if '没有资格参与活动' in error_message:self.member_day_black = TrueLog('📝 会员日任务风控')def member_day_finish_task(self, task):"""完成会员日任务 - 修复版本"""task_name = task.get("taskName", "未知任务")task_type = task.get("taskType", "")# 检查任务是否应该被跳过skip_task_types = ['SEND_SUCCESS', 'INVITEFRIENDS_PARTAKE_ACTIVITY', 'OPEN_SVIP','OPEN_NEW_EXPRESS_CARD', 'OPEN_FAMILY_CARD', 'CHARGE_NEW_EXPRESS_CARD','INTEGRAL_EXCHANGE', 'OPEN_SUPER_CARD']if task_type in skip_task_types:Log(f' 会员日任务[{task_name}]-跳过执行({task_type})')return# 智能获取任务代码task_code = Noneif 'taskCode' in task:task_code = task['taskCode']elif 'taskType' in task:task_code = task['taskType'] # 某些任务使用taskType作为taskCodeelse:Log(f' 任务[{task_name}]缺少必要字段,跳过执行')Log(f' 任务详情: {json.dumps(task, ensure_ascii=False, indent=2)}')return# 执行任务payload = {'taskCode': task_code}url = 'https://sf-express.com/mcs-mimp/commonPost/~memberEs~taskRecord~finishTask'response = self.do_request(url, data=payload)if response.get('success'):Log(f' 完成会员日任务[{task_name}]: 成功')self.member_day_fetch_mix_task_reward(task)else:error_message = response.get('errorMessage', '无返回')Log(f' 完成会员日任务[{task_name}]: {error_message}')if '没有资格参与活动' in error_message:self.member_day_black = TrueLog(' 会员日任务风控')def member_day_fetch_mix_task_reward(self, task):"""领取会员日任务奖励"""task_name = task.get("taskName", "未知任务")payload = {'taskType': task['taskType'], 'activityCode': 'MEMBER_DAY', 'channelType': 'MINI_PROGRAM'}url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~activityTaskService~fetchMixTaskReward'response = self.do_request(url, data=payload)if response.get('success'):Log(f' 领取会员日任务[{task_name}]: 成功')else:error_message = response.get('errorMessage', '失败')Log(f' 领取会员日任务[{task_name}]: {error_message}')def member_day_receive_red_packet(self, hour):"""领取会员日红包"""payload = {'receiveHour': hour}url = 'https://sf-express.com/mcs-mimp/commonPost/~memberNonactivity~memberDayTaskService~receiveRedPacket'response = self.do_request(url, data=payload)Log(f' 会员日领取{hour}点红包-{"成功" if response.get("success") else response.get("errorMessage", "失败")}')def member_day_red_packet_status(self):"""查询会员日红包状态"""url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~memberDayPacketService~redPacketStatus'response = self.do_request(url, data={})if response.get('success'):packet_list = response.get('obj', {}).get('packetList', [])self.member_day_red_packet_map = {packet['level']: packet['count'] for packet in packet_list}for level in range(1, self.max_level):count = self.member_day_red_packet_map.get(level, 0)while count >= 2:self.member_day_red_packet_merge(level)count -= 2packet_summary = [f"[{level}]X{count}" for level, count in self.member_day_red_packet_map.items() if count > 0]Log(f" 会员日合成列表: {', '.join(packet_summary) or '无红包'}")if self.member_day_red_packet_map.get(self.max_level):Log(f" 会员日已拥有[{self.max_level}级]红包X{self.member_day_red_packet_map[self.max_level]}")self.member_day_red_packet_draw(self.max_level)else:remaining_needed = sum(1 << (int(level) - 1) for level, count in self.member_day_red_packet_map.items() if count > 0)remaining = self.packet_threshold - remaining_neededLog(f" 会员日距离[{self.max_level}级]红包还差: [1级]红包X{remaining}")else:error_message = response.get('errorMessage', '无返回')Log(f' 查询会员日合成失败: {error_message}')if '没有资格参与活动' in error_message:self.member_day_black = TrueLog(' 会员日任务风控')def member_day_red_packet_merge(self, level):"""合成会员日红包"""payload = {'level': level, 'num': 2}url = 'https://sf-express.com/mcs-mimp/commonPost/~memberNonactivity~memberDayPacketService~redPacketMerge'response = self.do_request(url, data=payload)if response.get('success'):Log(f' 会员日合成: [{level}级]红包X2 -> [{level + 1}级]红包')self.member_day_red_packet_map[level] = self.member_day_red_packet_map.get(level, 0) - 2self.member_day_red_packet_map[level + 1] = self.member_day_red_packet_map.get(level + 1, 0) + 1else:Log(f' 会员日合成[{level}级]红包失败: {response.get("errorMessage", "无返回")}')def member_day_red_packet_draw(self, level):"""提取会员日红包"""payload = {'level': str(level)}url = 'https://sf-express.com/mcs-mimp/commonPost/~memberNonactivity~memberDayPacketService~redPacketDraw'response = self.do_request(url, data=payload)if response.get('success'):coupon_names = [item['couponName'] for item in response.get('obj', [])] or ['空气']Log(f" 会员日提取[{level}级]红包: {', '.join(coupon_names)}")else:Log(f" 会员日提取[{level}级]红包失败: {response.get('errorMessage', '无返回')}")def main(self):"""主执行逻辑"""if not self.login_res:return Falsetime.sleep(random.uniform(1, 3))# 执行签到任务self.sign()# 注释掉超值福利签到(经常失败,影响体验)# self.superWelfare_receiveRedPacket()self.get_SignTaskList()self.get_SignTaskList(True)# 执行丰蜜任务self.get_honeyTaskListStart()self.honey_indexData()self.honey_indexData(True)# 检查活动截止时间activity_end_date = get_quarter_end_date()days_left = (activity_end_date - datetime.now()).daysLog(f"⏰ 采蜜活动截止兑换还有{days_left}天,请及时进行兑换!!")# 会员日任务(每月26-28日)if 26 <= datetime.now().day <= 28:self.member_day_index()else:Log(' 未到指定时间不执行会员日任务')self.sendMsg()return Truedef sendMsg(self, help=False):"""发送通知(实现真正的通知功能)"""global one_msgif hadsend and one_msg:try:# 限制消息长度,避免过长if len(one_msg) > 4000:one_msg = one_msg[-4000:]one_msg = "...(消息过长,已截取后半部分)\n" + one_msgsend(f'顺丰速运账号{self.index}', one_msg.strip())print(f' 账号{self.index}通知发送完成')except Exception as e:print(f' 账号{self.index}通知发送失败: {e}')def get_quarter_end_date():"""计算当前季度结束日期"""current_date = datetime.now()current_month = current_date.monthcurrent_year = current_date.yearnext_quarter_first_day = datetime(current_year, ((current_month - 1) // 3 + 1) * 3 + 1, 1)return next_quarter_first_day - timedelta(days=1)if __name__ == '__main__':"""主程序入口"""APP_NAME = '顺丰速运'ENV_NAME = 'sfsyUrl'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, "顺丰签到")token = os.getenv(ENV_NAME)tokens = token.split('\n') if token else []if tokens:Log(f"🚚 共获取到{len(tokens)}个账号")for index, infos in enumerate(tokens):Log(f" 处理账号{index + 1}")RUN(infos, index).main()# 多账号间随机等待if index < len(tokens) - 1: # 不是最后一个账号delay = random.uniform(10, 30)print(f"💤 随机等待 {delay:.1f} 秒后处理下一个账号...")time.sleep(delay)# 最终汇总通知if hadsend and send_msg:try:# 汇总所有账号的结果summary_msg = f"""🚚 顺丰速运签到汇总📊 总计处理: {len(tokens)}个账号📅 执行时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}详细结果请查看各账号单独通知"""send('顺丰速运汇总', summary_msg)print(' 汇总通知发送完成')except Exception as e:print(f' 汇总通知发送失败: {e}')else:Log(" 未获取到sfsyUrl环境变量")print(f"==== 顺丰速运签到完成 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} ====")
解析
该脚本为顺丰速运自动化脚本,主要作用包括:
自动化登录并签到:基于你抓到并传入的跳转 URL(
sfsyUrl环境变量),自动完成顺丰会员日常签到。自动做任务拿积分/丰蜜:批量遍历"积分任务""采蜜换大礼"任务,自动完成并领取奖励。
自动领券:在"生活特权"专区里循环尝试适配的券并兑换。
会员日玩法:每月 26–28 日自动跑会员日任务、红包合成/抽取/提取。
多账号+随机延迟+通知:支持多账号(换行分隔)、随机等待防风控、通知汇总。
运行与配置
环境变量:
sfsyUrl(必填,支持多行多账号;抓包后 URL 要做 URL 编码)。随机延迟:
MAX_RANDOM_DELAY、RANDOM_SIGNIN控制启动前整体随机等待。
关键方法
通用工具
Log():统一日志累加(兼顾控制台输出、最终消息拼接)。format_time_remaining() / wait_with_countdown():格式化倒计时 & 循环打印倒计时(用于随机延迟可视化)。get_quarter_end_date():计算当季结束日,用于提示"采蜜兑换截止时间"。
账号执行主线:class RUN
初始化与登录
__init__(info, index)
解析单账号参数、初始化会话与请求头、设置会员日状态变量 → 调login()。login(sfurl)
直接 GET 你的抓包 URL,服务器会写回_login_user_id_、_login_mobile_等 cookie,据此判断是否登录成功。
成功会打印掩码手机号作为提示。
通用请求封装
getSign()
构造并追加签名头(sysCode/timestamp/signature),用于后续所有接口。do_request(url, data=None, req_type='post', max_retries=3)
统一的请求发送与 JSON 解析、自动重试与错误封装。
每日积分任务线
sign()
自动签到接口,成功会提示本周连签天数/礼包名。get_SignTaskList(end=False)
拉取"积分任务+签到状态"。end=False:打印当前总积分、过滤已完成/需跳过的任务,逐条执行:doTask()→receiveTask();end=True:只打印执行后的积分。doTask()/receiveTask()
分别是完成任务与领取奖励。
优惠券
get_coupom_list()→get_coupom(goods)
拉取"生活特权"券清单,遍历可兑换的券,命中即下单兑换并提示成功。
采蜜换大礼(丰蜜)
get_honeyTaskListStart()
拉取"采蜜换大礼任务列表",对不同taskType:DAILY_VIP_TASK_TYPE→ 去券中心领券;BEES_GAME_TASK_TYPE→ 触发大冒险honey_damaoxian();其他 →
do_honeyTask()完成。do_honeyTask()/receive_honeyTask()
完成单条丰蜜任务与领取丰蜜。honey_damaoxian()/honey_expand()
批量上报大冒险获得的丰蜜;容量不足时自动扩容。honey_indexData(end=False)
采蜜首页:end=False:打印活动结束时间与执行前丰蜜,遍历任务逐一receive_honeyTask();end=True:打印执行后丰蜜。
(支持随机inviteUserId互助,避免自填自身)
会员日(26–28 日)
member_day_index()
入口:查抽奖次数、邀请奖励、红包状态 → 抽奖 → 做任务 → 合成/提取红包。遇"无资格"自动标记member_day_black终止分支。member_day_receive_invite_award()/member_day_lottery()
领取邀请奖励、抽奖。member_day_task_list()→member_day_finish_task(task)→member_day_fetch_mix_task_reward(task)
拉任务 → 完成(自动选择taskCode)→ 领取奖励;不自动做需要下单/付费类任务(已在白名单跳过)。红包相关:
member_day_red_packet_status():统计各等级红包数量,能合就合;凑满 8 级阈值后自动member_day_red_packet_draw()提取;member_day_red_packet_merge(level):两两合成升级;member_day_receive_red_packet(hour):按小时领取(脚本主线里主要是状态/合成/抽取)。
执行编排
main()登录→
sign()→get_SignTaskList()(前后两次,分别统计积分)采蜜任务→采蜜前后统计
提醒兑换截止天数
会员日(26–28 日)才执行会员日链路
末尾
sendMsg()发送本账号汇报。
通知
sendMsg()
对单账号输出结果发送通知;主程序退出前也会发送汇总通知。
程序入口
读取
sfsyUrl,支持多账号(按行分割)。若启用随机模式:整体随机延迟再开始。
逐个账号执行
RUN(...).main();账号间再随机间隔 10–30s。最后发送汇总通知。
注意:
本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。
【相关文章】
没有评论:
发表评论