2025年11月23日星期日

联想智选任务脚本

1.购买服务器阿里云:服务器购买地址https://t.aliyun.com/U/Bg6shY若失效,可用地址

1.购买服务器

阿里云:

服务器购买地址

https://t.aliyun.com/U/Bg6shY

若失效,可用地址

https://www.aliyun.com/daily-act/ecs/activity_selection?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=201905

2.部署教程

2024年最新青龙面板跑脚本教程(一)持续更新中

3.代码如下

#!/usr/bin/env python3# -*- coding: utf-8 -*-import base64import jsonimport loggingimport osimport randomimport reimport smtplibfrom email.header import Headerfrom email.mime.text import MIMETextfrom email.utils import formataddrfrom smtplib import SMTP_SSLfrom sys import exitfrom time import sleep
import requestsimport tomlfrom requests.utils import cookiejar_from_dict, dict_from_cookiejar
USER_AGENT = [    "Mozilla/5.0 (Linux; U; Android 11; zh-cn; PDYM20 Build/RP1A.200720.011) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36 HeyTapBrowser/40.7.24.9",    "Mozilla/5.0 (Linux; Android 12; Redmi K30 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Mobile Safari/537.36"]

class Push_messages:    class Server_chan:        def __init__(self, send_key: str) -> None:            self.send_key = send_key
        def send_message(self, content: str) -> bool:            data = {"title""联想签到""desp": content}            response = requests.post(                f"https://sctapi.ftqq.com/{self.send_key}.send", data=data            )            res_data = response.json().get("data")            pushid = res_data.get("pushid")            readkey = res_data.get("readkey")            result = requests.get(                f"https://sctapi.ftqq.com/push?id={pushid}&readkey={readkey}"            )            return True if result.json().get("code") == 0 else False
    class Wechat_message:        def __init__(self, corpid: str, corpsecret: str, agentid: str) -> None:            self.corpid = corpid            self.corpsecret = corpsecret            self.agentid = agentid            self.token = (                requests.get(                    f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={self.corpid}&corpsecret={self.corpsecret}"                )                .json()                .get("access_token")            )
        def send_message(self, content: str) -> bool:            data = {                "touser""@all",                "msgtype""text",                "agentid"self.agentid,                "text": {"content": content},                "safe"0,            }            response = requests.post(                f"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={self.token}",                data=json.dumps(data),            )            return True if response.json().get("errcode") == 0 else False
    class Dingtalk_message:        def __init__(self, ding_accesstoken: str) -> None:            self.ding_accesstoken = ding_accesstoken
        def send_message(self, content: str) -> bool:            data = {                "msgtype""text",                "text": {"content": content},                "at": {"isAtAll"True},            }            response = requests.post(                f"https://oapi.dingtalk.com/robot/send?access_token={self.ding_accesstoken}",                data=json.dumps(data),            )            return True if response.json().get("errcode") == 0 else False
    class Email_message:        def __init__(self, sender_email: str, sender_password: str, receiver_email: str, smtp_server: str,                     smtp_port: int) -> None:            self.sender_email = sender_email            self.sender_password = sender_password            self.receiver_email = receiver_email            self.smtp_server = smtp_server            self.smtp_port = smtp_port
        def send_message(self, content: str) -> bool:            receiver_email = [self.receiver_email]
            message = MIMEText(content, 'plain''utf-8')            message['Subject'] = Header("联想智选定时签到结果""utf-8")            message['From'] = Header("联想智选定时签到程序""utf-8")            message['To'] = receiver_email[0]
            try:                smtp = SMTP_SSL(self.smtp_server, self.smtp_port)                smtp.login(self.sender_email, self.sender_password)                smtp.sendmail(                    self.sender_email, receiver_email, message.as_string())                smtp.quit()                return True            except smtplib.SMTPException as e:                print('send email error', e)                return False
    class QQEmail_message:        def __init__(self, sender_email: str, sender_password: str, receiver_email: str, smtp_server: str,                     smtp_port: int) -> None:            self.sender_email = sender_email            self.sender_password = sender_password            self.receiver_email = receiver_email            self.smtp_server = smtp_server            self.smtp_port = smtp_port
        def send_message(self, content: str) -> bool:            tmp = self.receiver_email.split(",")            receiver_email = tmp            subject = "联想智选定时签到结果"            from_head = "联想智选定时签到程序"            message = MIMEText(content, 'plain''utf-8')
            #  使用 formataddr + Header 自动处理编码            message['From'] = formataddr((str(Header(from_head, 'utf-8')), self.sender_email))            message['Subject'] = Header(subject, 'utf-8')
            try:                smtp = SMTP_SSL(self.smtp_server, self.smtp_port)                smtp.login(self.sender_email, self.sender_password)                for i in range(len(receiver_email)):                    message['To'] = formataddr((str(Header(receiver_email[i], 'utf-8')), self.receiver_email))                    smtp.sendmail(                        self.sender_email, receiver_email[i], message.as_string())                smtp.quit()                return True            except smtplib.SMTPException as e:                print('send qq email error', e)                return False

def set_push_type():    for type, key in config.get("message_push").items():        key_list = key.values()        if "".join(key_list):            return getattr(Push_messages(), type)(*key_list).send_message    else:        return logger

def login(username, password):    def get_cookie():        session.headers = {            "user-agent": ua,            "Content-Type""application/x-www-form-urlencoded; charset=UTF-8",        }        session.get(url="https://reg.lenovo.com.cn/auth/rebuildleid")        session.get(            url="https://reg.lenovo.com.cn/auth/v1/login?ticket=5e9b6d3d-4500-47fc-b32b-f2b4a1230fd3&ru=https%3A%2F%2Fmclub.lenovo.com.cn%2F"        )        data = f"account={username}&password={base64.b64encode(str(password).encode()).decode()}\            &ps=1&ticket=5e9b6d3d-4500-47fc-b32b-f2b4a1230fd3&codeid=&code=&slide=v2&applicationPlatform=2&shopId=\                1&os=web&deviceId=BIT%2F8ZTwWmvKpMsz3bQspIZRY9o9hK1Ce3zKIt5js7WSUgGQNnwvYmjcRjVHvJbQ00fe3T2wxgjZAVSd\                    OYl8rrQ%3D%3D&t=1655187183738&websiteCode=10000001&websiteName=%25E5%2595%2586%25E5%259F%258E%25E\                        7%25AB%2599&forwardPageUrl=https%253A%252F%252Fmclub.lenovo.com.cn%252F"        login_response = session.post(            url="https://reg.lenovo.com.cn/auth/v2/doLogin", data=data        )        if login_response.json().get("ret") == "1":            logger(f"{username}账号或密码错误")            return None        ck_dict = dict_from_cookiejar(session.cookies)        config["cookies"][username] = f"{ck_dict}"        toml.dump(config, open(config_file, "w"))        session.cookies = cookiejar_from_dict(ck_dict)        return session
    session = requests.Session()    session.headers = {        "user-agent": ua,        "Content-Type""application/x-www-form-urlencoded; charset=UTF-8",    }    if cookie_dict := config.get("cookies").get(username):        session.cookies = cookiejar_from_dict(eval(cookie_dict))        ledou = session.post(            "https://i.lenovo.com.cn/info/uledou.jhtml",            data={"sts""b044d754-bda2-4f56-9fea-dcf3aecfe782"},        )        try:            int(ledou.text)        except ValueError:            logger(f"{username} ck有错,重新获取ck并保存")            session = get_cookie()            return session        logger(f"{username} ck没有错")        return session    else:        logger(f"{username} ck为空,重新获取ck并保存")        session = get_cookie()        return session

def sign(session):    res = session.get(url="https://mclub.lenovo.com.cn/signlist/")    token = re.findall('token\s=\s"(.*?)"', res.text)[0]    data = f"_token={token}&memberSource=1"    headers = {        "Host""mclub.lenovo.com.cn",        "pragma""no-cache",        "cache-control""no-cache",        "accept""application/json, text/javascript, */*; q=0.01",        "origin""https://mclub.lenovo.com.cn",        "x-requested-with""XMLHttpRequest",        "user-agent": ua                      + "/lenovoofficialapp/16554342219868859_10128085590/newversion/versioncode-1000080/",        "content-type""application/x-www-form-urlencoded; charset=UTF-8",        "referer""https://mclub.lenovo.com.cn/signlist?pmf_group=in-push&pmf_medium=app&pmf_source=Z00025783T000",        "accept-language""zh-CN,en-US;q=0.8",    }    sign_response = session.post(        "https://mclub.lenovo.com.cn/signadd", data=data, headers=headers    )    sign_days = (        session.get(url="https://mclub.lenovo.com.cn/getsignincal")        .json()        .get("signinCal")        .get("continueCount")    )    sign_user_info = session.get("https://mclub.lenovo.com.cn/signuserinfo")    try:        serviceAmount = sign_user_info.json().get("serviceAmount")        ledou = sign_user_info.json().get("ledou")    except Exception as e:        logger(sign_user_info.headers["content-type"])        logger(sign_user_info.status_code)        logger(e)        serviceAmount, ledou = NoneNone    session.close()    if sign_response.json().get("success"):        return f"\U00002705账号{username}签到成功, \U0001F4C6连续签到{sign_days}天, \U0001F954共有乐豆{ledou}个, \U0001F4C5共有延保{serviceAmount}天\n"    else:        return f"\U0001F6AB账号{username}今天已经签到, \U0001F4C6连续签到{sign_days}天, \U0001F954共有乐豆{ledou}个, \U0001F4C5共有延保{serviceAmount}天\n"

def main():    global logger, config_file, config, ua, username    logging.basicConfig(        level=logging.INFO, format="%(asctime)s - %(levelname)s: %(message)s"    )    logger = logging.getLogger(__name__).info    # config_file = r"../private-config/config.toml"    # config = toml.load(config_file)    # 读取CI指定的配置    config_file = os.getenv("CONFIG_FILE""config.toml")    config = toml.load(config_file)    account = config.get("account")    if not account:        exit(1)    if not (ua := config.get("browser").get("ua")):        ua = random.choice(USER_AGENT)        config["browser"]["ua"] = ua    push = set_push_type()    message = "联想签到: \n"    for username, password in account.items():        session = login(username, password)        if not session:            continue        message += sign(session)        sleep(random.randint(0,20))    push(message)

if __name__ == "__main__":    sleep(random.randint(0,120)) # 延时 0-120s    main()
解析

这是一个 联想智选自动签到脚本,主要功能包括:

  1. 多账号自动登录联想账号

    • 从 config.toml 里读取多个账号密码。

    • 支持复用历史 Cookie,如果 Cookie 失效则自动重新登录并刷新 Cookie。

  2. 自动完成联想俱乐部签到

    • 调用联想俱乐部签到接口(signadd 等),完成每天的签到操作。

    • 查询连续签到天数、乐豆数量、延保天数等信息。

  3. 汇总所有账号的签到结果并推送通知

    • 根据配置选择一种推送方式(Server酱 / 企业微信 / 钉钉机器人 / 邮件 / QQ 邮箱)。

    • 统一生成一条汇总消息,比如:每个账号是否签到成功、连续签到天数、乐豆数量和延保天数等。

  4. 适配青龙面板 / CI 场景

    • 通过环境变量 CONFIG_FILE 指定配置文件路径;

    • 脚本启动时会随机延时 0–120 秒,再对每个账号之间随机 sleep 0–20 秒,降低被风控的概率。

一句话概括:

"定时批量登录联想账号 → 自动签到 → 统计乐豆/延保/连续天数 → 通过你配置的渠道发一条汇总通知。"

主要函数

1. Push_messages 类及其子类们

Push_messages 是一个"通知发送器的集合",里面嵌套了多种推送方式,每种方式都是一个小类,负责把签到结果发出去:

  • Push_messages.Server_chan

    • 使用 Server酱(sctapi.ftqq.com) 推送签到结果。

    • 发送标题为「联想签到」的消息,并通过接口查询推送是否成功。

  • Push_messages.Wechat_message

    • 使用 企业微信应用消息 推送结果。

    • 持有 corpidcorpsecretagentid,先获取 access_token,再发送文本消息给 @all

  • Push_messages.Dingtalk_message

    • 使用 钉钉机器人 Webhook 推送结果。

    • 发送一个 text 类型的消息,并 @所有人。

  • Push_messages.Email_message

    • 通过 SMTP 发送普通邮件(单收件人版本)。

    • 可配置发件人邮箱、授权码、收件人、SMTP 服务器与端口。

    • 邮件标题是「联想智选定时签到结果」。

  • Push_messages.QQEmail_message

    • 针对 QQ邮箱 / 多收件人 的邮件推送实现。

    • 支持多个收件人(逗号分隔),逐个发送。

    • 用 formataddr + Header 解决中文显示和编码问题。

这些子类的共同点:都实现了 send_message(self, content: str) -> bool 接口,用来发一段文本内容。

2. set_push_type()

作用:根据配置文件选择推送方式,返回一个"发送函数"。

  • 从 config["message_push"] 中读取各类推送配置(Server酱、企业微信、钉钉、邮箱等)。

  • 按配置中是否填写了对应字段来判断某种推送方式是否启用:

    • 找到第一个有完整配置的推送方式,就实例化对应的 Push_messages.* 类,返回它的 send_message 方法。

  • 如果没有任何推送方式配置,则退而求其次,返回 logger(也就是仅打印日志,不推送)。

后面主流程里会调用:push = set_push_type(),然后 push(message),完全不关心背后具体用的是哪种通知渠道。

3. login(username, password)

作用:负责单个账号的登录与 Cookie 管理,返回一个已登录的 requests.Session 会话。

主要逻辑

  1. 先尝试从 config["cookies"] 中读取保存过的 Cookie:

    • 直接走"重新获取 Cookie"的流程。

    • 将 Cookie 转为 cookiejar 并挂到 Session 上;

    • 调用一个接口(如 uledou)测试 Cookie 是否有效:

    • 如果能正常返回数字,说明 Cookie 有效 → 直接复用。

    • 如果无效,说明 Cookie 过期或错误 → 打日志提示,转为重新获取 Cookie。

    • 如果有:

    • 如果没有 Cookie:

  2. 内部的 get_cookie() 子函数:

    • 如果返回表示账号或密码错误 → 记日志,返回 None

    • 否则认为登录成功:

    • 从 Session 中取出 Cookie,存入 config["cookies"][username],并写回 config.toml

    • 返回这个 Session。

    • 设置请求头(UA、Content-Type 等);

    • 访问一些预登陆页面建立会话;

    • 把密码做 base64 之后放入表单中;

    • 构造登录请求:

    • 调用联想的登录接口:

最终,login() 返回一个已经带有有效 Cookie 的 session,供后续签到使用;如果完全失败则返回 None

4. sign(session)

作用:使用已登录的 Session 执行真正的"联想俱乐部签到",并返回一行描述结果的字符串。

流程概述:

  1. 访问签到页面,解析页面中的 _token(表单防 CSRF 的 token)。

  2. 构造签到请求参数(_token + 固定字段),带上移动端 UA 等请求头,向 signadd 接口发起签到请求。

  3. 再请求:

    • 当前乐豆数 ledou

    • 当前延保天数 serviceAmount

    • 签到日历接口,获取连续签到天数

    • 用户信息接口,获取:

  4. 根据签到接口返回的 JSON 中 success 字段:

    • 若签到成功:返回一段带表情的文案,例如:

      账号xxx签到成功, 📆连续签到X天, 🥔共有乐豆Y个, 📅共有延保Z天

    • 若提示已签到:返回相似文案,但文本改成"今天已经签到"。

这个函数不做推送,只返回文字结果;汇总和发送由 main() 统一处理。

5. main()

作用:主流程调度,总控逻辑。

主要步骤:

  1. 初始化日志系统,并把 logger 设为全局可用(方便其他函数调用)。

  2. 确定配置文件路径:

    • 优先从环境变量 CONFIG_FILE 取;

    • 否则默认使用当前目录下的 config.toml

  3. 加载配置 config = toml.load(config_file),读取:

    • account:账号密码字典 {username: password}

    • browser.ua:自定义 UA;如果没配置,就从预设的 USER_AGENT 列表里随机选一个,并回写到 config。

  4. 调用 set_push_type() 获取一个 push 函数(可能是 Server酱、企业微信、钉钉、邮件等,也可能只是 logger)。

  5. 构建汇总消息字符串 message = "联想签到: \n"

  6. 遍历所有账号:

    • 调用 login(username, password) 拿到登录 Session;

    • 若登录失败 session is None,跳过该账号;

    • 否则调用 sign(session),拿到该账号的一行签到结果字符串,拼接到 message

    • 每个账号之间 sleep(random.randint(0,20)),随机等待 0–20 秒。

  7. 所有账号处理完后,调用 push(message) 发送汇总结果。


注意

本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。


历史脚本txt文件获取>>
服务器搭建,人工服务咨询>>

没有评论:

发表评论

Facebook像素(Pixel)介绍

点击上方蓝字关注我Facebook Pixel就是我们常说的像素,它是一段代码,可以帮助我们追踪、衡量广告受众 点击上方 蓝字 关注我 Facebook Pixel就是我们常说的像素,它是一段代码,可以帮助我们追踪、衡量广告受众, 了解用户在网站上采取的各种行为,例如查看网页...