# cron: 12 8 * * * # new Env("WPS签到") #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ @File : wps签到任务 @CreateTime : 2026/01/17 @UpdateTime : 2026/04/12 @Author : Rex @Version : 3.0.2 @Contact : 2375560790@qq.com @QQ群 : 621124138 备注妖火 @License : MIT @UpdateContent : 1.适配 任务中心新任务。 2.修复 办公助手任务。 3.新增 WPS挑战计划。 4. 增强错误处理。 @Desc : 活动地址: https://personal-act.wps.cn/rubik2/portal/HD2025031821201822/YM2025040908558269?cs_from=web_vipcenter_banner_inpublic&mk_key=4b9deqIfqNO3KCZrgH17WPH1kdzMoKUEvya&position=pc_aty_ban3_kaixue_test_b 核心功能: 1. WPS任务中心:每日签到、自动完成所有任务、自动抽奖 2. 办公助手(办公助手 2026.03.16结束):每日签到、自动完成所有任务、自动抽奖 3. 天天领福利:每日签到、自动完成所有任务、自动抽奖 4. WPS超级会员小程序:签到 5. WPS挑战计划:自动完成所有任务、自动抽奖 使用: 1. cookie 抓取这个接口的请求头cookie字段 https://personal-act.wps.cn/activity-rubik/activity/component_action 2. 青龙配置环境变量 WPS_TASK_CK,格式:备注#cookie,支持多账号,多账号回车换行 2. 青龙面板推荐 cron 0 0 7 * * * 遗留问题: 1.WPS挑战计划:'PDF转换', 'PDF合并', '语音速记', '关注' 后续开发 2.小程序只有签到抽奖等妖友待测 3.WPS任务中心 疑似存在新旧任务列表,任务可以多做,暂时未适配 """ import os import sys import random import time from typing import Optional, Dict, Any, Union, Tuple, List import requests import urllib3 from loguru import logger from requests import Response # ------------------------ 模块加载区 -------------------------- # 1. 获取当前脚本的绝对路径 current_script = os.path.abspath(__file__) # 2. 定位根目录(根据实际结构调整层级) # 假设脚本在根目录的子目录(如 src/)中,根目录是当前脚本目录的上层目录 root_dir = os.path.dirname(os.path.dirname(current_script)) # 3. 将根目录添加到模块搜索路径(确保只添加一次) if root_dir not in sys.path: sys.path.insert(0, root_dir) # 插入到最前面,优先搜索根目录 try: from RnlProxy import RnlProxy except: RnlProxy = None logger.error('未检测到 RnlProxy.py 模块,使用默认ip') try: from rnl_push import rnl_push except: try: import notify if hasattr(notify, 'send'): notify.sendNotify = notify.send rnl_push = notify except: rnl_push = None logger.error('未检测到 rnl_push.py、notify.py 模块,不进行消息推送') # ------------------------ 模块加载区 -------------------------- class Utils: @staticmethod def r_sleep(s=1.0, e=None): """随机休眠函数(外部传秒,内部精确到毫秒)""" try: s = float(s) e = float(e) if e is not None else None except (ValueError, TypeError): raise ValueError("参数 s/e 必须是可转换为浮点数的数字(秒)") if e is None: e = s + 1.0 if s > e: s, e = e, s s = max(s, 0.0) e = max(e, 0.0) s_ms = int(round(s * 1000)) e_ms = int(round(e * 1000)) sleep_ms = random.randint(s_ms, e_ms) sleep_sec = sleep_ms / 1000 time.sleep(sleep_sec) return round(sleep_sec, 3) @staticmethod def dict_cookie_to_string(cookie_dict): cookie_list = [] for key, value in cookie_dict.items(): cookie_list.append(f"{key}={value}") return "; ".join(cookie_list) @staticmethod def string_cookie_to_dict(cookie_str): cookie_dict = {} if not cookie_str: return cookie_dict cookie_pairs = [pair.strip() for pair in cookie_str.split(';') if pair.strip()] for pair in cookie_pairs: key_value = pair.split('=', 1) if len(key_value) == 2: key, value = key_value cookie_dict[key.strip()] = value.strip() else: cookie_dict[key_value[0].strip()] = "" return cookie_dict class RnlRequest: def __init__(self, proxies=None, cookies=None, headers=None): urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) self.session = requests.Session() self.session.trust_env = False self.session.verify = False self.last_response: Optional[Response] = None if proxies: self.session.proxies.update(proxies) self._base_headers = headers or { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36', } self.update_cookies(cookies) @property def status_code(self) -> Optional[int]: return self.last_response.status_code if self.last_response else None @property def ok(self) -> bool: return 200 <= self.status_code < 300 if self.status_code else False @property def json(self) -> Any: if not self.last_response: return None try: return self.last_response.json() except (ValueError, TypeError): return None @property def text(self) -> Optional[str]: return self.last_response.text if self.last_response else None @property def content(self) -> Optional[bytes]: return self.last_response.content if self.last_response else None @property def headers(self) -> Optional[Dict[str, str]]: return dict(self.last_response.headers) if self.last_response else None def update_cookies(self, cookies: Union[str, dict, None]) -> None: if not cookies: return if isinstance(cookies, str): cookies = dict( item.strip().split('=', 1) for item in cookies.split(';') if '=' in item.strip() ) elif not isinstance(cookies, dict): return self.session.cookies.update(cookies) def get_cookies(self) -> Dict[str, str]: return self.session.cookies.get_dict() def update_headers(self, headers: Dict[str, str]) -> None: self._base_headers.update(headers) def raise_for_status(self) -> None: if self.last_response: self.last_response.raise_for_status() def request(self, method, url, params=None, data=None, json=None, headers=None, cookies=None, files=None, auth=None, timeout=None, allow_redirects=True, proxies=None, hooks=None, stream=None, verify=None, cert=None, **kwargs) -> Optional[Response]: self.last_response = None request_headers = {**self._base_headers, **(headers or {})} try: resp = self.session.request( method=method.upper(), url=url, params=params, data=data, json=json, headers=request_headers, cookies=cookies, files=files, auth=auth, timeout=timeout, allow_redirects=allow_redirects, proxies=proxies, hooks=hooks, stream=stream, verify=verify if verify is not None else self.session.verify, cert=cert, **kwargs ) self.last_response = resp return resp except requests.RequestException as e: if hasattr(e, 'response') and e.response: self.last_response = e.response return e.response return None def get(self, url, **kwargs): return self.request(method='GET', url=url, **kwargs) def post(self, url, **kwargs): return self.request(method='POST', url=url, **kwargs) def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.session.close() import json import hashlib import hmac from datetime import datetime, timezone def generate_sign(t: dict, i: str, r: str) -> str: sorted_keys = sorted(t.keys()) n = {key: t[key] for key in sorted_keys} p = json.dumps(n, ensure_ascii=False, separators=(',', ':')) md5_p = hashlib.md5(p.encode('utf-8')).hexdigest() utc_time = datetime.now(timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT') f = i + md5_p + utc_time hmac_obj = hmac.new(r.encode('utf-8'), f.encode('utf-8'), hashlib.sha256) u = hmac_obj.hexdigest() return u class RNL: def __init__(self, c, proxies=None): if isinstance(c, str): new_c = Utils.string_cookie_to_dict(c) else: new_c = c self.act_csrf_token = new_c.get('act_csrf_token') self.user_id = new_c.get('uid') if not self.act_csrf_token or not self.user_id: logger.error(f'[用户{self.user_id or "未知"}] cookie参数不全(缺少act_csrf_token或uid)') exit(1) self.user_id = int(new_c.get('uid')) self.userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0' self.rr = RnlRequest(proxies=proxies, cookies=new_c, headers={'User-Agent': self.userAgent}) self.de = { 'PROMOTIONAL_MATERIAL': "task_center.promotional_material", 'START_TASK': "task_center.start", 'FINISH': "task_center.finish", 'TOKEN_FINISH': "task_center.token_finish", 'REWARD': "task_center.reward" } self.operation_logs = [] self.global_config = { 'task_center': True, # WPS任务中心 'fragment_collect': False, # 办公助手 2026.03.16结束 'lottery3': True, # 天天领福利 'svip_applet': True, # 超级会员applet 'challenge': True, # WPS挑战计划 } # WPS任务中心-获取签到key def get_public_key(self): headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6', 'origin': 'https://personal-act.wps.cn', 'priority': 'u=1, i', 'referer': 'https://personal-act.wps.cn/', 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Microsoft Edge";v="134"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-site', } response = self.rr.get('https://personal-bus.wps.cn/sign_in/v1/encrypt/key', headers=headers) json_data = response.json() if json_data['code'] == 1000000: logger.success(f'[用户{self.user_id}] 获取加密密钥成功') return json_data['data'] logger.error(f'[用户{self.user_id}] 获取加密密钥失败:{json_data["msg"]}') return None # WPS任务中心-签到 def sign_in(self, encryptData): data = { 'encryptData': encryptData, 'userId': self.user_id, } resp = self.rr.post('https://py.leishennb.icu/v1/rnl-2-gather/get-wps-publickey', json=data).json() params_obj = resp['data'] headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6', 'content-type': 'application/json', 'origin': 'https://personal-act.wps.cn', 'priority': 'u=1, i', 'referer': 'https://personal-act.wps.cn/', 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Microsoft Edge";v="134"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-site', 'token': params_obj['token'], } json_data = params_obj['data'] response = self.rr.post('https://personal-bus.wps.cn/sign_in/v1/sign_in', headers=headers, json=json_data) json_data = response.json() if json_data.get('code') == 1000000: rewards = json_data['data']['rewards'][0] sign_msg = f"任务中心签到成功:{rewards['reward_name']}" logger.success(f'[用户{self.user_id}] {sign_msg}') self.operation_logs.append(sign_msg) return True if 'has sign' in json_data.get('msg'): sign_msg = '今天已签到' logger.info(f'[用户{self.user_id}] {sign_msg}') self.operation_logs.append(sign_msg) return True sign_msg = f'任务中心签到失败:{json_data.get("msg", "未知错误")}' logger.error(f'[用户{self.user_id}] {sign_msg}') self.operation_logs.append(sign_msg) return None # WPS任务中心-通用完成任务 def common_component_action(self, task_id, title, component_action=None): headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6', 'content-type': 'application/json', 'origin': 'https://personal-act.wps.cn', 'priority': 'u=1, i', 'referer': 'https://personal-act.wps.cn/rubik2/portal/HD2025031821201822/YM2025040908558269?cs_from=web_vipcenter_banner_inpublic&mk_key=4b9deqIfqNO3KCZrgH17WPH1kdzMoKUEvya&position=pc_aty_ban3_kaixue_test_b', 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Microsoft Edge";v="134"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', 'user-agent': self.userAgent, 'x-act-csrf-token': self.act_csrf_token, } json_data = { 'component_uniq_number': { 'activity_number': 'HD2025031821201822', 'page_number': 'YM2025040908558269', 'component_number': 'ZJ2025040709458367', 'component_node_id': 'FN1744160180RthG', 'filter_params': { 'cs_from': 'web_vipcenter_banner_inpublic', 'mk_key': '4b9deqIfqNO3KCZrgH17WPH1kdzMoKUEvya', 'position': 'pc_aty_ban3_kaixue_test_b', }, }, 'component_type': 35, 'component_action': component_action or self.de['FINISH'], 'task_center': { 'task_id': task_id, }, } try: response = self.rr.post( 'https://personal-act.wps.cn/activity-rubik/activity/component_action', headers=headers, json=json_data, ).json() if response['result'] == 'ok': task_center = response['data']['task_center'] if task_center['success']: task_msg = f'完成任务 [{title}] 成功' logger.success(f'[用户{self.user_id}] {task_msg}') # self.operation_logs.append(task_msg) return task_center.get('token') or True task_msg = f'完成任务 [{title}] 失败:{task_center["reason"]}' logger.error(f'[用户{self.user_id}] {task_msg}') self.operation_logs.append(task_msg) return False task_msg = f'完成任务 [{title}] 失败:{response}' logger.error(f'[用户{self.user_id}] {task_msg}') self.operation_logs.append(task_msg) return False except Exception as e: task_msg = f'完成任务 [{title}] 异常:{str(e)}' logger.error(f'[用户{self.user_id}] {task_msg}') self.operation_logs.append(task_msg) return False # WPS任务中心-通用领取奖励 def common_reward_component_action(self, task_id, title): headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6', 'content-type': 'application/json', 'origin': 'https://personal-act.wps.cn', 'priority': 'u=1, i', 'referer': 'https://personal-act.wps.cn/rubik2/portal/HD2025031821201822/YM2025040908558269?cs_from=web_vipcenter_banner_inpublic&mk_key=4b9deqIfqNO3KCZrgH17WPH1kdzMoKUEvya&position=pc_aty_ban3_kaixue_test_b', 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Microsoft Edge";v="134"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', 'x-act-csrf-token': self.act_csrf_token, } json_data = { 'component_uniq_number': { 'activity_number': 'HD2025031821201822', 'page_number': 'YM2025040908558269', 'component_number': 'ZJ2025040709458367', 'component_node_id': 'FN1744160180RthG', 'filter_params': { 'cs_from': 'web_vipcenter_banner_inpublic', 'mk_key': '4b9deqIfqNO3KCZrgH17WPH1kdzMoKUEvya', 'position': 'pc_aty_ban3_kaixue_test_b', }, }, 'component_type': 35, 'component_action': self.de['REWARD'], 'task_center': { 'task_id': task_id, }, } try: response = self.rr.post( 'https://personal-act.wps.cn/activity-rubik/activity/component_action', headers=headers, json=json_data, ).json() if response['result'] == 'ok': task_center = response['data']['task_center'] if task_center['success']: reward_msg = f'领取 [{title}] 奖励成功' logger.success(f'[用户{self.user_id}] {reward_msg}') self.operation_logs.append(reward_msg) return True reward_msg = f'领取 [{title}] 奖励失败:{task_center["reason"]}' logger.error(f'[用户{self.user_id}] {reward_msg}') self.operation_logs.append(reward_msg) return False reward_msg = f'领取 [{title}] 奖励失败:{response}' logger.error(f'[用户{self.user_id}] {reward_msg}') self.operation_logs.append(reward_msg) return False except Exception as e: reward_msg = f'领取 [{title}] 奖励异常:{str(e)}' logger.error(f'[用户{self.user_id}] {reward_msg}') self.operation_logs.append(reward_msg) return False # WPS任务中心-任务详情 def task_info(self, token): headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6', 'priority': 'u=1, i', 'referer': 'https://personal-act.wps.cn/rubik2/portal/HD2025091109421588/YM2025091121369865?cs_from=android_ucsty_rwzx&positon=ad_rwzx_task', 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Microsoft Edge";v="134"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', 'user-agent': self.userAgent, } start_time = int(time.time()*1000) params = { 'batch_tag': start_time, 'token': token, } try: response = self.rr.get( 'https://personal-act.wps.cn/activity-rubik/user/task_center/task_info', params=params, headers=headers, ).json() if response.get('result') == 'ok': return start_time + response['data']['start_at'] logger.error(response) return None except Exception as e: logger.error(str(e)) return None # WPS任务中心-抽奖handle def lottery_process(self, task_list): if not task_list: return for task in task_list: task_id = task['task_id'] title = task['title'] task_status = task['task_status'] if task_status == 2: logger.info(f'[用户{self.user_id}] 任务 [{title}] 已完成') continue if '浏览' in title: token = self.common_component_action(task_id=task_id, title=title, component_action=self.de['START_TASK']) if token: batch_tag = self.task_info(token=token) if not batch_tag: logger.error('获取浏览任务信息失败,跳过') continue Utils.r_sleep(10, 11) is_done1 = self.task_finish(token=token, title=title, batch_tag=batch_tag) if is_done1: Utils.r_sleep(1) self.common_reward_component_action(task_id=task_id, title=title) Utils.r_sleep(1) continue skip_keywords = ['认证', '上喜马拉雅', '消费', '邀请', '微博', '苏宁易购', '开通会员'] if any(keyword in title for keyword in skip_keywords): logger.info(f'[用户{self.user_id}] 跳过任务 [{title}]') continue is_done = self.common_component_action(task_id=task_id, title=title) if is_done: Utils.r_sleep(1) self.common_reward_component_action(task_id=task_id, title=title) Utils.r_sleep(1) # 天天领福利-任务完成 浏览任务 def task_finish(self, token, title, batch_tag): headers = { 'User-Agent': self.userAgent, 'Accept': 'application/json, text/plain, */*', # 'Accept-Encoding': 'gzip, deflate, br, zstd', 'Content-Type': 'application/json', 'sec-ch-ua-platform': '"Windows"', 'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"', 'sec-ch-ua-mobile': '?0', 'origin': 'https://personal-act.wps.cn', 'sec-fetch-site': 'same-origin', 'sec-fetch-mode': 'cors', 'sec-fetch-dest': 'empty', 'referer': 'https://personal-act.wps.cn/rubik2/portal/HD2025031721339450/YM2025031721331326?cs_from=ad_ucsty_rwzx&position=ad_ucsty_rwzx', 'accept-language': 'zh-CN,zh;q=0.9', 'priority': 'u=1, i', } json_data = { 'batch_tag': batch_tag, 'token': token, } try: response = self.rr.post( 'https://personal-act.wps.cn/activity-rubik/user/task_center/task_finish', headers=headers, json=json_data, ).json() if response.get('result') == 'ok': reward_msg = f'完成任务 [{title}] 成功' logger.success(f'[用户{self.user_id}] {reward_msg}') self.operation_logs.append(reward_msg) return True reward_msg = f'任务 {title} 完成失败:{response}' logger.error(f'[用户{self.user_id}] {reward_msg}') self.operation_logs.append(reward_msg) return False except Exception as e: reward_msg = f'任务 {title} 完成失败:{str(e)}' logger.error(f'[用户{self.user_id}] {reward_msg}') self.operation_logs.append(reward_msg) return False # 天天领福利-签到 def fragment_collect_sign_in(self): headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9', 'cache-control': 'no-cache', 'content-type': 'application/json', 'origin': 'https://personal-act.wps.cn', 'pragma': 'no-cache', 'priority': 'u=1, i', 'referer': 'https://personal-act.wps.cn/rubik2/portal/HD2025031721339450/YM2025031721331326?cs_from=ad_ucsty_rwzx&position=ad_ucsty_rwzx', 'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', 'x-act-csrf-token': self.act_csrf_token, } sign_date = datetime.now().strftime("%Y-%m-%d") json_data = { 'component_uniq_number': { 'activity_number': 'HD2025031721339450', 'page_number': 'YM2025031721331326', 'component_number': 'ZJ2025061815363325', 'component_node_id': 'FN1750234948dBVL', 'filter_params': { 'cs_from': 'ad_ucsty_rwzx', 'position': 'ad_ucsty_rwzx', }, }, 'component_type': 42, 'component_action': 'fragment_collect.sign_in', 'fragment_collect': { 'sign_date': sign_date, 'series_id': '', 'is_new_sign_series': True, }, } try: response = self.rr.post( 'https://personal-act.wps.cn/activity-rubik/activity/component_action', headers=headers, json=json_data, ) json_data = response.json() if json_data.get('result') == 'ok': success = json_data['data']['fragment_collect']['success'] rewards = json_data['data']['fragment_collect']['reason'] if success: sign_msg = f"天天领福利签到成功:{rewards}" logger.success(f'[用户{self.user_id}] {sign_msg}') self.operation_logs.append(sign_msg) return True sign_msg = f"天天领福利签到失败:{rewards}" logger.error(f'[用户{self.user_id}] {sign_msg}') self.operation_logs.append(sign_msg) return False _msg = json_data.get('msg') if 'Duplicate entry' in _msg: sign_msg = f"天天领福利-今日已签到" else: sign_msg = f"天天领福利签到失败:{_msg}" logger.error(f'[用户{self.user_id}] {sign_msg}') self.operation_logs.append(sign_msg) return False except Exception as e: logger.error(str(e)) sign_msg = f"天天领福利签到失败:{str(e)}" self.operation_logs.append(sign_msg) return False # 天天领福利-抽奖 def lottery_v22(self): headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9', 'cache-control': 'no-cache', 'content-type': 'application/json', 'origin': 'https://personal-act.wps.cn', 'pragma': 'no-cache', 'priority': 'u=1, i', 'referer': 'https://personal-act.wps.cn/rubik2/portal/HD2025031721339450/YM2025031721331326?cs_from=ad_ucsty_rwzx&position=ad_ucsty_rwzx', 'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', 'x-act-csrf-token': self.act_csrf_token, } json_data = { 'component_uniq_number': { 'activity_number': 'HD2025031721339450', 'page_number': 'YM2025031721331326', 'component_number': 'ZJ2025092916515917', 'component_node_id': 'FN1761875116m2x8', 'filter_params': { 'cs_from': 'ad_ucsty_rwzx', 'position': 'ad_ucsty_rwzx', }, }, 'component_type': 45, 'component_action': 'lottery_v2.exec', 'lottery_v2': { 'session_id': 3001, }, } try: response = self.rr.post( 'https://personal-act.wps.cn/activity-rubik/activity/component_action', headers=headers, json=json_data, ) json_data = response.json() if json_data['result'] == 'ok': reward_name = json_data['data']['lottery_v2']['reward_name'] lottery_msg = f"天天领福利抽奖成功:{reward_name}" logger.success(f'[用户{self.user_id}] {lottery_msg}') self.operation_logs.append(lottery_msg) return True lottery_msg = f'天天领福利抽奖失败:{json_data.get("msg", "未知错误")}' logger.error(f'[用户{self.user_id}] {lottery_msg}') self.operation_logs.append(lottery_msg) return None except Exception as e: lottery_msg = f'天天领福利抽奖异常:{str(e)}' logger.error(f'[用户{self.user_id}] {lottery_msg}') self.operation_logs.append(lottery_msg) return False # WPS任务中心-抽奖 def lottery_v2(self): headers = { 'sec-ch-ua-platform': '"Windows"', 'Referer': 'https://personal-act.wps.cn/rubik2/portal/HD2025031821201822/YM2025040908558269?cs_from=web_vipcenter_banner_inpublic&mk_key=4b9deqIfqNO3KCZrgH17WPH1kdzMoKUEvya&position=pc_aty_ban3_kaixue_test_b', 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Microsoft Edge";v="134"', 'sec-ch-ua-mobile': '?0', 'User-Agent': self.userAgent, 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json', 'X-Act-Csrf-Token': self.act_csrf_token, } json_data = { 'component_uniq_number': { 'activity_number': 'HD2025031821201822', 'page_number': 'YM2025040908558269', 'component_number': 'ZJ2025092916516585', 'component_node_id': 'FN1762345949vdR1', 'filter_params': { 'cs_from': 'web_vipcenter_banner_inpublic', 'mk_key': '4b9deqIfqNO3KCZrgH17WPH1kdzMoKUEvya', 'position': 'pc_aty_ban3_kaixue_test_b', }, }, 'component_type': 45, 'component_action': 'lottery_v2.exec', 'lottery_v2': { 'session_id': 2, }, } try: response = self.rr.post('https://personal-act.wps.cn/activity-rubik/activity/component_action', headers=headers, json=json_data) json_data = response.json() if json_data['result'] == 'ok': reward_name = json_data['data']['lottery_v2']['reward_name'] lottery_msg = f"抽奖成功:{reward_name}" logger.success(f'[用户{self.user_id}] {lottery_msg}') self.operation_logs.append(lottery_msg) return True lottery_msg = f'抽奖失败:{json_data.get("msg", "未知错误")}' logger.error(f'[用户{self.user_id}] {lottery_msg}') self.operation_logs.append(lottery_msg) return None except Exception as e: lottery_msg = f'抽奖异常:{str(e)}' logger.error(f'[用户{self.user_id}] {lottery_msg}') self.operation_logs.append(lottery_msg) return False # WPS任务中心-活动信息 # https://personal-act.wps.cn/rubik2/portal/HD2025031821201822/YM2025040908558269?cs_from=web_vipcenter_banner_inpublic&mk_key=4b9deqIfqNO3KCZrgH17WPH1kdzMoKUEvya&position=pc_aty_ban3_kaixue_test_b def page_info(self): headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6', 'priority': 'u=1, i', 'referer': 'https://personal-act.wps.cn/rubik2/portal/HD2025031821201822/YM2025040908558269?cs_from=web_vipcenter_banner_inpublic&mk_key=4b9deqIfqNO3KCZrgH17WPH1kdzMoKUEvya&position=pc_aty_ban3_kaixue_test_b', 'sec-ch-ua': '"Chromium";v="134", "Not:A-Brand";v="24", "Microsoft Edge";v="134"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', 'user-agent': self.userAgent, } try: # page_number=YM2025031821202008 response = self.rr.get( 'https://personal-act.wps.cn/activity-rubik/activity/page_info?activity_number=HD2025031821201822&page_number=YM2025040908558269&filter_params=%7B%22cs_from%22:%22web_vipcenter_banner_inpublic%22,%22mk_key%22:%224b9deqIfqNO3KCZrgH17WPH1kdzMoKUEvya%22,%22position%22:%22pc_aty_ban3_kaixue_test_b%22%7D', headers=headers, ).json() if response['result'] == 'ok': lottery_times = None user_integral = None task_list = None for item in response["data"]: if lottery_times is None: if item.get("type") == 45 and item.get("lottery_v2"): for session in item["lottery_v2"].get("lottery_list", []): if session.get("session_id") == 2: lottery_times = session.get("times") continue if user_integral is None: if item.get("task_center_user_info"): user_integral = item["task_center_user_info"].get("integral") elif item.get("integral_waterfall"): user_integral = item["integral_waterfall"].get("user_integral") if task_list is None: if item.get("task_center"): task_list = item["task_center"].get("task_list") if lottery_times and user_integral and task_list: break logger.info(f'[用户{self.user_id}] 积分:{user_integral},抽奖次数:{lottery_times}') return { "lottery_times": lottery_times, "user_integral": user_integral, "task_list": task_list } except Exception as e: logger.error(f'[用户{self.user_id}] 获取用户信息异常:{str(e)}') return None # 办公助手-活动信息 # https://personal-act.wps.cn/rubik2/portal/HD2025031010408781/YM2025061216463517?cs_from=xinchao_activity_lottery&position=xinchao_bgzs_autoreply_2148_cj def page_info2(self): headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9', 'cache-control': 'no-cache', 'pragma': 'no-cache', 'priority': 'u=1, i', 'referer': 'https://personal-act.wps.cn/rubik2/portal/HD2025031010408781/YM2025061216463517?cs_from=xinchao_activity_lottery&position=xinchao_bgzs_autoreply_2148_cj', 'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', } try: response = self.rr.get( 'https://personal-act.wps.cn/activity-rubik/activity/page_info?activity_number=HD2025031010408781&page_number=YM2025061216463517&filter_params=%7B%22cs_from%22:%22xinchao_activity_lottery%22,%22position%22:%22xinchao_bgzs_autoreply_2148_cj%22%7D', headers=headers, ).json() task_list = None lottery_times = None # 遍历data数组,定位包含task_center的元素 for item in response["data"]: if "task_center" in item and "task_list" in item["task_center"]: task_list = item["task_center"]["task_list"] if "lottery" in item and item["lottery"]: lottery = item["lottery"] if "rewards" in lottery and isinstance(lottery["rewards"], list) and len(lottery["rewards"]) > 0: first_reward = lottery["rewards"][0] if "times" in first_reward: lottery_times = first_reward["times"] if lottery_times != None and task_list != None: break return { 'task_list': task_list, 'lottery_times': lottery_times } except Exception as e: logger.error(str(e)) return None # 福利中心-活动信息 def page_info3(self): headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9', 'cache-control': 'no-cache', 'pragma': 'no-cache', 'priority': 'u=1, i', 'referer': 'https://personal-act.wps.cn/rubik2/portal/HD2025031721339450/YM2025031721331326?cs_from=ad_ucsty_rwzx&position=ad_ucsty_rwzx', 'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', } try: response = self.rr.get( 'https://personal-act.wps.cn/activity-rubik/activity/page_info?activity_number=HD2025031721339450&page_number=YM2025031721331326&filter_params=%7B%22cs_from%22:%22ad_ucsty_rwzx%22,%22position%22:%22ad_ucsty_rwzx%22%7D', headers=headers, ).json() if response['result'] == 'ok': lottery_times = None for item in response["data"]: if item.get("lottery_v2"): for session in item["lottery_v2"].get("lottery_list", []): if session.get("times"): lottery_times = session.get("times") break return { "lottery_times": lottery_times, } except Exception as e: logger.error(f'[用户{self.user_id}] 获取用户信息异常:{str(e)}') return None # 办公助手-领取 def components_action2(self, task_id, title): headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9', 'cache-control': 'no-cache', 'content-type': 'application/json', 'origin': 'https://personal-act.wps.cn', 'pragma': 'no-cache', 'priority': 'u=1, i', 'referer': 'https://personal-act.wps.cn/rubik2/portal/HD2025031010408781/YM2025061216463517?cs_from=xinchao_activity_lottery&position=xinchao_bgzs_autoreply_2148_cj', 'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', } json_data = { 'component_uniq_number': { 'activity_number': 'HD2025031010408781', 'page_number': 'YM2025061216463517', 'component_number': 'ZJ2024083022083755', 'component_node_id': 'FN1740387182DaYX', }, 'component_type': 14, 'component_action': self.de['REWARD'], 'task_center': { 'task_id': task_id, }, } try: response = self.rr.post( 'https://personal-act.wps.cn/activity-rubik/activity/component_action', headers=headers, json=json_data, ).json() if response['result'] == 'ok': task_center = response['data']['task_center'] if task_center['success']: reward_msg = f'领取 [{title}] 奖励成功' logger.success(f'[用户{self.user_id}] {reward_msg}') self.operation_logs.append(reward_msg) return True reward_msg = f'领取 [{title}] 奖励失败:{task_center["reason"]}' logger.error(f'[用户{self.user_id}] {reward_msg}') self.operation_logs.append(reward_msg) return False reward_msg = f'领取 [{title}] 奖励失败:{response}' logger.error(f'[用户{self.user_id}] {reward_msg}') self.operation_logs.append(reward_msg) return False except Exception as e: reward_msg = f'领取 [{title}] 奖励异常:{str(e)}' logger.error(f'[用户{self.user_id}] {reward_msg}') self.operation_logs.append(reward_msg) return False # 办公助手-抽奖 def lottery_exec(self): headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9', 'cache-control': 'no-cache', 'content-type': 'application/json', 'origin': 'https://personal-act.wps.cn', 'pragma': 'no-cache', 'priority': 'u=1, i', 'referer': 'https://personal-act.wps.cn/rubik2/portal/HD2025031010408781/YM2025061216463517?cs_from=xinchao_activity_lottery&position=xinchao_bgzs_autoreply_2148_cj', 'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', } json_data = { 'component_uniq_number': { 'activity_number': 'HD2025031010408781', 'page_number': 'YM2025061216463517', 'component_number': 'ZJ2024083022081230', 'component_node_id': 'FN1741940010rC4c', }, 'component_type': 2, 'component_action': 'lottery.exec', 'lottery': { 'pay_source': '', 'integral_source': '', 'position': 'bgzs_tasks_cj', 'source': '', 'ids': '1115,1119,1116,1117,1120,1121,1122,1118', 'sign': '', }, } try: response = self.rr.post( 'https://personal-act.wps.cn/activity-rubik/activity/component_action', headers=headers, json=json_data, ) json_data = response.json() if json_data['result'] == 'ok': reward_name = json_data['data']['lottery']['name'] lottery_msg = f"抽奖成功:{reward_name}" logger.success(f'[用户{self.user_id}] {lottery_msg}') self.operation_logs.append(lottery_msg) return True lottery_msg = f'抽奖失败:{json_data.get("msg", "未知错误")}' logger.error(f'[用户{self.user_id}] {lottery_msg}') self.operation_logs.append(lottery_msg) return None except Exception as e: lottery_msg = f'抽奖异常:{str(e)}' logger.error(f'[用户{self.user_id}] {lottery_msg}') self.operation_logs.append(lottery_msg) return False # 办公助手-执行 def done_task2_handler(self, task_list2, first_task=False): for t2 in task_list2: task_id = t2["task_id"] title = t2["title"] task_status = t2['task_status'] if task_status == 1: logger.info(f'[用户{self.user_id}] 任务 [{title}] 已完成') continue if first_task: if '每日访问当前活动' in title: self.components_action2(task_id=task_id, title=title) Utils.r_sleep(2) return else: if '每日访问当前活动' in title: continue self.components_action2(task_id=task_id, title=title) Utils.r_sleep(2) # applet-wps超级会员签到 def applet_sign(self): s_key = '06196ab4da15c09a3aaee610162ca56f' try: clock_info = self.rr.get('https://personal-bus.wps.cn/activity/clock_in/v1/info').json() s_key = clock_info.get('data',{}).get('s_key') except Exception as e: logger.error(str(e)) ss = '7908b285f33c837d' json_data = { 'client_type': 1, } # 别动,签名算法不能用,固定即可 signature = generate_sign(json_data, s_key, ss) headers = { 'Host': 'personal-bus.wps.cn', 'Connection': 'keep-alive', # 'Content-Length': '17', 'date': 'Tue, 20 Jan 2026 14:42:58 GMT', 'charset': 'utf-8', 'signature': '0d8ff00f5c74de36d0b2e677c82b22a1dd5ab196b0d227cc875fb051eec50156', 'x-csrftoken': '1234567890', 'User-Agent': 'Mozilla/5.0 (Linux; Android 14; 23117RK66C Build/UKQ1.230804.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/142.0.7444.173 Mobile Safari/537.36 XWEB/1420153 MMWEBSDK/20240404 MMWEBID/3531 MicroMessenger/8.0.49.2600(0x2800313D) WeChat/arm64 Weixin Android Tablet NetType/WIFI Language/zh_CN ABI/arm64 MiniProgramEnv/android', 'content-type': 'application/json', # 'Accept-Encoding': 'gzip,compress,br,deflate', 'Referer': 'https://servicewechat.com/wx2f333d84a103825d/240/page-frame.html', } try: response = self.rr.post( 'https://personal-bus.wps.cn/activity/clock_in/v1/clock_in', headers=headers, json=json_data, ).json() if response['result'] == 'ok': lottery_msg = f"小程序签到成功" logger.success(f'[用户{self.user_id}] {lottery_msg}') self.operation_logs.append(lottery_msg) return True if 'already clocked in today' in response.get("msg", "未知错误"): lottery_msg = f'小程序签到失败:今日已签到' else: lottery_msg = f'小程序签到失败:{response.get("msg", "未知错误")}' logger.error(f'[用户{self.user_id}] {lottery_msg}') self.operation_logs.append(lottery_msg) return None except Exception as e: lottery_msg = f'小程序签到异常:{str(e)}' logger.error(f'[用户{self.user_id}] {lottery_msg}') self.operation_logs.append(lottery_msg) return False # WPS挑战计划-任务完成or领取 def challenge_component_action(self, title, task_id, component_action=None, action_name=None): component_action = component_action or self.de['FINISH'] if not action_name: if self.de['FINISH'] == component_action: action_name = '完成' elif self.de['REWARD'] == component_action: action_name = '领取' headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9', 'content-type': 'application/json', 'origin': 'https://personal-act.wps.cn', 'priority': 'u=1, i', 'referer': 'https://personal-act.wps.cn/rubik2/portal/HD2025121517384715/YM2025121517381164?cs_from=pc_ucsty_rwzx_task&position=pc_rwzx_task', 'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', 'user-agent': self.userAgent, 'x-act-csrf-token': self.act_csrf_token, } json_data = { 'component_uniq_number': { 'activity_number': 'HD2025121517384715', 'page_number': 'YM2025121517381164', 'component_number': 'ZJ2025031817022062', 'component_node_id': 'FN17642133971jKe', 'filter_params': { 'cs_from': 'pc_ucsty_rwzx_task', 'position': 'pc_rwzx_task', }, }, 'component_type': 35, 'component_action': component_action, 'task_center': { 'task_id': task_id, }, } try: response = self.rr.post( 'https://personal-act.wps.cn/activity-rubik/activity/component_action', headers=headers, json=json_data, ).json() if response['result'] == 'ok': task_center = response['data']['task_center'] if task_center['success']: task_msg = f'{action_name}任务 [{title}] 成功' logger.success(f'[用户{self.user_id}] {task_msg}') if action_name == '领取': self.operation_logs.append(task_msg) return task_center.get('token') or True task_msg = f'{action_name}任务 [{title}] 失败:{task_center["reason"]}' logger.error(f'[用户{self.user_id}] {task_msg}') self.operation_logs.append(task_msg) return False task_msg = f'{action_name}任务 [{title}] 失败:{response}' logger.error(f'[用户{self.user_id}] {task_msg}') self.operation_logs.append(task_msg) return False except Exception as e: task_msg = f'{action_name}任务 [{title}] 异常:{str(e)}' logger.error(f'[用户{self.user_id}] {task_msg}') self.operation_logs.append(task_msg) return False # WPS挑战计划-任务信息 def challenge_page_info(self): headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh-CN,zh;q=0.9', 'priority': 'u=1, i', 'referer': 'https://personal-act.wps.cn/rubik2/portal/HD2025121517384715/YM2025121517381164?cs_from=pc_ucsty_rwzx_task&position=pc_rwzx_task', 'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', 'user-agent': self.userAgent, } try: response = self.rr.get( 'https://personal-act.wps.cn/activity-rubik/activity/page_info?activity_number=HD2025121517384715&page_number=YM2025121517381164&filter_params=%7B%22cs_from%22:%22pc_ucsty_rwzx_task%22,%22position%22:%22pc_rwzx_task%22%7D', headers=headers, ).json() if response['result'] == 'ok': lottery_times = None task_list = None for item in response["data"]: if item.get("task_center"): _task_list = item["task_center"].get("task_list", []) if _task_list: task_list = _task_list if task_list and lottery_times: break return { "task_list": task_list, "lottery_times": lottery_times, } except Exception as e: logger.error(f'[用户{self.user_id}] 获取WPS挑战计划任务列表异常:{str(e)}') return None # WPS挑战计划-任务执行 def challenge_exec(self, task_list): if not task_list: return for task in task_list: task_id = task['task_id'] title = task['title'] task_status = task['task_status'] if task_status == 2: logger.info(f'[用户{self.user_id}] 任务 [{title}] 已完成') continue skip_keywords = ['邀请', 'PDF转换', 'PDF合并', '语音速记', '关注', '认证', '消费', '开通会员'] if any(keyword in title for keyword in skip_keywords): logger.info(f'[用户{self.user_id}] 跳过任务 [{title}]') continue is_done = self.challenge_component_action(task_id=task_id, title=title, component_action=self.de['FINISH']) if is_done: Utils.r_sleep(1) self.challenge_component_action(task_id=task_id, title=title, component_action=self.de['REWARD']) Utils.r_sleep(1) def main(self): self.operation_logs = [] user_id = self.user_id # ================ WPS任务中心 ================= if self.global_config.get('task_center'): tip = '# 开始执行 WPS任务中心 任务' self.operation_logs.append(tip) logger.info(tip) page_data = self.page_info() if not page_data: error_msg = f'[用户{user_id}] 获取用户信息失败:活动结束或cookie过期' logger.error(error_msg) self.operation_logs.append(error_msg) # 返回None和消息 return None, f'用户ID:{user_id}\n' + '\n'.join(self.operation_logs) task_list = page_data.get("task_list") or [] Utils.r_sleep(1) # 签到 public_data = self.get_public_key() if public_data: self.sign_in(public_data) else: self.operation_logs.append(f'[用户{user_id}] 获取签到密钥失败,终止任务') return None, f'用户ID:{user_id}\n' + '\n'.join(self.operation_logs) Utils.r_sleep(1) # 完成领取任务 self.lottery_process(task_list=task_list) Utils.r_sleep(1.5) # 重试 page_data = self.page_info() if page_data: self.lottery_process(task_list=page_data.get("task_list") or []) Utils.r_sleep(1.5) page_data = self.page_info() lottery_times = page_data.get("lottery_times") if page_data else 0 # 抽奖 if lottery_times and lottery_times > 0: logger.info(f'[用户{user_id}] 开始执行抽奖(剩余次数:{lottery_times})') for i in range(lottery_times): lottery_result = self.lottery_v2() if not lottery_result: logger.info(f'[用户{user_id}] 抽奖第{i+1}次失败,终止抽奖') break Utils.r_sleep(1) logger.info('# 执行完成 WPS任务中心 任务') # ============== 天天领福利 ============= if self.global_config.get('lottery3'): tip = '# 开始执行 天天领福利 任务' self.operation_logs.append(tip) logger.info(tip) Utils.r_sleep(1) self.fragment_collect_sign_in() Utils.r_sleep(1) page_info3 = self.page_info3() if page_info3: lottery_times3 = page_info3.get('lottery_times') or 0 if lottery_times3 > 0: for i3 in range(lottery_times3): lottery_result3 = self.lottery_v22() if not lottery_result3: logger.info(f'[用户{user_id}] 抽奖第{i3+1}次失败,终止抽奖') break Utils.r_sleep(1) logger.info('# 执行完成 天天领福利 任务') # ============== WPS办公助手(默认关闭) ============= if self.global_config.get('fragment_collect'): tip = '# 开始执行 WPS办公助手 任务' self.operation_logs.append(tip) logger.info(tip) page_result = self.page_info2() if page_result: task_list2 = page_result.get("task_list") or [] self.done_task2_handler(task_list2, first_task=True) self.done_task2_handler(task_list2) page_result = self.page_info2() lottery_times = page_result.get("lottery_times") or 0 Utils.r_sleep(1) if lottery_times > 0: for i2 in range(lottery_times): lottery_result2 = self.lottery_exec() if not lottery_result2: logger.info(f'[用户{user_id}] 抽奖第{i2+1}次失败,终止抽奖') break Utils.r_sleep(1) logger.info('# 执行完成 WPS办公助手 任务') else: logger.error("WPS办公助手数据异常,跳过") # ============== WPS挑战计划 ============= if self.global_config.get('challenge'): tip = '# 开始执行 WPS挑战计划 任务' self.operation_logs.append(tip) logger.info(tip) challenge_data = self.challenge_page_info() if challenge_data: self.challenge_exec(challenge_data.get('task_list') or []) # ============== wps超级会员小程序 ============= if self.global_config.get('svip_applet'): tip = '# 开始执行 wps超级会员小程序 任务' self.operation_logs.append(tip) logger.info(tip) self.applet_sign() logger.info('# 执行完成 wps超级会员小程序 任务') # ---------- 构建统计信息 ---------- stats = { 'user_id': user_id, 'task_center_checkin': any('任务中心签到成功' in log or '今天已签到' in log for log in self.operation_logs), 'fragment_sign': any('天天领福利签到成功' in log for log in self.operation_logs), 'applet_sign': any('小程序签到成功' in log for log in self.operation_logs), 'completed_tasks': sum(1 for log in self.operation_logs if '完成任务' in log and '成功' in log), 'lottery_results': [log for log in self.operation_logs if '抽奖成功' in log], } final_msg = f'用户ID:{user_id}\n' + '\n'.join(self.operation_logs) return stats, final_msg def print_wps_table(stats_list): """打印 WPS 单账户明细表格""" if not stats_list: return print("\n" + "=" * 80) print("📊 单账户明细:") header = "┌──────┬──────────────┬──────────────┬──────────────┬──────────────┬──────────────┐" title = "│ 序号 │ 用户ID │ 任务中心签到 │ 天天领福利 │ 小程序签到 │ 完成任务数 │" split_line = "├──────┼──────────────┼──────────────┼──────────────┼──────────────┼──────────────┤" footer = "└──────┴──────────────┴──────────────┴──────────────┴──────────────┴──────────────┘" print(header) print(title) print(split_line) for idx, s in enumerate(stats_list, 1): uid = str(s.get('user_id', '?'))[:12] checkin = '✅' if s.get('task_center_checkin') else '❌' frag = '✅' if s.get('fragment_sign') else '❌' applet = '✅' if s.get('applet_sign') else '❌' tasks = s.get('completed_tasks', 0) line = f"│ {idx:^4} │ {uid:^12} │ {checkin:^12} │ {frag:^12} │ {applet:^12} │ {tasks:^12} │" print(line) print(footer) # 汇总统计 total = len(stats_list) success_count = sum(1 for s in stats_list if s.get('task_center_checkin') or s.get('fragment_sign') or s.get('applet_sign')) print("\n📊 账号汇总:") print(f" 总账号: {total}") print(f" 成功: {success_count} 失败: {total - success_count}") print("=" * 80) def read_users_from_env(): users_env = os.getenv('WPS_TASK_CK', '') users = [] for line in users_env.strip().split('\n'): if line.strip(): parts = line.split('#') if len(parts) >= 2: user_info = { 'username': parts[0].strip(), 'cookie': parts[1].strip(), } users.append(user_info) return users if __name__ == "__main__": users = read_users_from_env() if not users: print("未配置用户信息,请设置 WPS_TASK_CK 环境变量,格式:备注#cookie") exit(1) print(f"共读取到 {len(users)} 个用户") logger.info('随机等待30-600s') Utils.r_sleep(30, 600) rnlProxy = None if RnlProxy: rnlProxy = RnlProxy() all_stats = [] all_push_msgs = [] for i, user in enumerate(users, 1): proxies = None if rnlProxy: proxies = rnlProxy.get_valid_proxy() print(f'使用代理:{proxies}') username = user['username'] cookies = user['cookie'] print(f"\n===== 正在处理第 {i} 个用户:{username} =====") try: stats, msg = RNL(cookies, proxies=proxies).main() if stats: all_stats.append(stats) all_push_msgs.append(f"【{username}】\n{msg}") except Exception as e: error_msg = f"【{username}】处理异常:{str(e)}" logger.error(error_msg) all_push_msgs.append(error_msg) all_stats.append({ 'user_id': 'error', 'task_center_checkin': False, 'fragment_sign': False, 'applet_sign': False, 'completed_tasks': 0 }) # 输出表格与汇总 print_wps_table(all_stats) # 推送(捕获异常避免中断) if rnl_push and all_push_msgs: try: push_title = "WPS任务执行结果" push_content = '\n\n'.join(all_push_msgs) rnl_push.sendNotify(push_title, push_content) print(f"\n推送消息已发送:\n{push_content}") except Exception as e: logger.error(f"推送消息失败: {e}") elif not rnl_push: print("\n推送功能未启用,跳过消息推送") else: print("\n无推送消息可发送")