2026年1月3日星期六

天府论坛任务脚本

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

1.购买服务器

阿里云:

服务器购买地址

https://t.aliyun.com/U/55RK8C

若失效,可用地址

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.代码如下

# -*- coding: utf-8 -*-
import osimport reimport timeimport tracebackfrom dataclasses import dataclassfrom typing import OptionalListTuple
import requestsfrom lxml import etree
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.chrome.options import Optionsfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as EC
try:    from webdriver_manager.chrome import ChromeDriverManager    from selenium.webdriver.chrome.service import Service    USE_WDM = Trueexcept Exception:    USE_WDM = False

BASE_URL = "https://bbs.scol.com.cn/"LOGIN_URL_CANDIDATES = [    "member.php?mod=logging&action=login",    "member.php?mod=logging&action=login&mobile=2",    "member.php?mod=logging&action=login&infloat=yes&handlekey=login",]
# 常见签到入口候选(Discuz常见)SIGN_URL_CANDIDATES = [    "plugin.php?id=dsu_paulsign:sign",    "plugin.php?id=dsu_paulsign:sign&operation=qiandao",    "plugin.php?id=k_misign:sign",    "plugin.php?id=qiandao",    "home.php?mod=task",    "home.php?mod=space",    "forum.php",]
# 页面关键词(用于扫描链接文本)KEYWORDS = ["签到""每日签到""打卡""签 到""Check in""checkin""sign""任务"]

@dataclassclass SignResult:    ok: bool    title: str    detail: str    raw_url: str = ""

def env(name: str, default: str = "") -> str:    v = os.getenv(name)    return v.strip() if v is not None else default

def pushplus_send(token: str, title: str, content: str) -> None:    if not token:        return    try:        requests.get(            "https://www.pushplus.plus/send",            params={"token": token, "title": title, "content": content, "template""txt"},            timeout=10,        )    except Exception:        pass

class ScolBbsSigner:    def __init__(self, username: str, password: str, headless: bool = True, timeout: int = 20):        self.username = username        self.password = password        self.headless = headless        self.timeout = timeout
        self.driver = self._build_driver()        self.wait = WebDriverWait(self.driver, self.timeout)
    # ------------------ 核心:浏览器初始化 ------------------    def _build_driver(self) -> webdriver.Chrome:        chrome_options = Options()        if self.headless:            chrome_options.add_argument("--headless=new")        chrome_options.add_argument("--no-sandbox")        chrome_options.add_argument("--disable-dev-shm-usage")        chrome_options.add_argument("--disable-gpu")        chrome_options.add_argument("--window-size=1280,900")        chrome_options.add_argument("--lang=zh-CN")        chrome_options.add_argument(            "--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) "            "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"        )
        if USE_WDM:            service = Service(ChromeDriverManager().install())            return webdriver.Chrome(service=service, options=chrome_options)        return webdriver.Chrome(options=chrome_options)
    # ------------------ 工具:安全打开页面 ------------------    def open(self, url: str) -> None:        if not url.startswith("http"):            url = BASE_URL.rstrip("/") + "/" + url.lstrip("/")        self.driver.get(url)
    # ------------------ 工具:是否已登录 ------------------    def is_logged_in(self) -> bool:        html = self.driver.page_source        # Discuz 常见:退出/注销        if re.search(r"(退出|退出登录|注销|Log\s*out)", html, re.I):            return True        # 常见:设置/消息/提醒/个人资料        if re.search(r"(设置|消息|提醒|个人资料|空间)", html):            return True        return False
    # ------------------ 工具:找输入框 ------------------    def _find_any_input(self, locators):        for by, value in locators:            try:                ele = self.wait.until(EC.presence_of_element_located((by, value)))                if ele:                    return ele            except Exception:                continue        return None
    # ------------------ 工具:找可点击元素 ------------------    def _find_any_clickable(self, locators):        for by, value in locators:            try:                ele = self.wait.until(EC.element_to_be_clickable((by, value)))                if ele:                    return ele            except Exception:                continue        return None
    # ------------------ 主要方法:登录 ------------------    def login(self) -> bool:        """        多入口尝试登录页 -> 填账号密码 -> 点击登录 -> 回首页验证是否登录成功        """        self.open(BASE_URL)        time.sleep(2)
        if self.is_logged_in():            return True
        last_err = ""        for path in LOGIN_URL_CANDIDATES:            try:                self.open(path)                time.sleep(2)
                user_input = self._find_any_input([                    (By.NAME, "username"),                    (By.ID, "username"),                    (By.CSS_SELECTOR, "input[name='username']"),                    (By.XPATH, "//input[contains(@placeholder,'用户名') or contains(@placeholder,'账号') or contains(@placeholder,'邮箱') or contains(@placeholder,'手机')]"),                ])                pwd_input = self._find_any_input([                    (By.NAME, "password"),                    (By.ID, "password"),                    (By.CSS_SELECTOR, "input[type='password']"),                    (By.XPATH, "//input[@type='password']"),                ])
                if not user_input or not pwd_input:                    continue
                user_input.clear()                user_input.send_keys(self.username)                pwd_input.clear()                pwd_input.send_keys(self.password)
                submit_btn = self._find_any_clickable([                    (By.CSS_SELECTOR, "button[type='submit']"),                    (By.CSS_SELECTOR, "input[type='submit']"),                    (By.XPATH, "//*[self::button or self::a or self::span][contains(.,'登录') or contains(.,'登 录')]"),                ])                if submit_btn:                    submit_btn.click()                else:                    pwd_input.submit()
                time.sleep(3)                self.open(BASE_URL)                time.sleep(2)
                if self.is_logged_in():                    return True
            except Exception as e:                last_err = str(e)                continue
        print(f"❌ 登录失败: {last_err}")        return False
    # ------------------ 主要方法:发现签到入口 ------------------    def discover_sign_url(self) -> Optional[str]:        """        1) 常见签到插件URL试探(dsu_paulsign/k_misign/task)        2) 首页/任务中心/空间扫描"签到/打卡"等链接        3) 源码提取疑似签到链接        """        # 1) 插件URL试探        for p in SIGN_URL_CANDIDATES:            url = BASE_URL.rstrip("/") + "/" + p            if self._url_looks_like_sign_page(url):                return url
        # 2) 扫描页面        for page in [BASE_URL, "home.php?mod=task""home.php?mod=space""forum.php"]:            try:                self.open(page)                time.sleep(2)                u = self._scan_page_for_sign_link()                if u:                    return u            except Exception:                pass
        return None
    def _url_looks_like_sign_page(self, url: str) -> bool:        try:            self.open(url)            time.sleep(2)            html = self.driver.page_source            if any(k in html for k in ["签到""已签到""签到成功""今日已签到""补签""任务"]):                return True        except Exception:            pass        return False
    def _scan_page_for_sign_link(self) -> Optional[str]:        html = self.driver.page_source        doc = etree.HTML(html)        if doc is None:            return None
        # 2.1 找链接文本包含关键词        for kw in KEYWORDS:            nodes = doc.xpath(f"//a[contains(normalize-space(.), '{kw}')]/@href")            if nodes:                return self._abs_url(nodes[0])
        # 2.2 找 href 含关键字        hrefs = doc.xpath("//a/@href"or []        for href in hrefs:            if not href:                continue            if re.search(r"(dsu_paulsign|k_misign|qiandao|checkin|sign|task|mission)", href, re.I):                return self._abs_url(href)
        return None
    def _abs_url(self, href: str) -> str:        href = href.strip()        if href.startswith("http"):            return href        if href.startswith("//"):            return "https:" + href        return BASE_URL.rstrip("/") + "/" + href.lstrip("/")
    # ------------------ 主要方法:执行签到 ------------------    def do_sign(self, sign_url: str) -> SignResult:        """        打开签到页 -> 点击签到按钮 -> 解析结果        """        self.open(sign_url)        time.sleep(2)
        clicked = False
        # 优先点明确"签到/打卡/立即签到"的按钮/链接        btn = self._find_any_clickable([            (By.XPATH, "//*[self::a or self::button or self::span][contains(.,'签到') or contains(.,'打卡') or contains(.,'立即签到')]"),        ])        if btn:            try:                btn.click()                clicked = True                time.sleep(3)            except Exception:                pass
        html = self.driver.page_source        title, detail, ok = self._parse_sign_result(html, clicked, sign_url)        return SignResult(ok=ok, title=title, detail=detail, raw_url=sign_url)
    def _parse_sign_result(self, html_text: str, clicked: bool, url: str) -> Tuple[strstrbool]:        # 成功/已签到关键词        if re.search(r"(签到成功|打卡成功)", html_text):            award = self._extract_award_text(html_text)            return "签到成功", award or "页面提示:签到成功"True
        if re.search(r"(今日已签到|已经签到|已签到)", html_text):            award = self._extract_award_text(html_text)            return "今日已签到", award or "页面提示:今日已签到/无需重复签到"True
        # 点了按钮但未识别到明确字样        if clicked:            return "可能已触发签到""已点击签到按钮,但未识别到明确成功文案(可能是弹窗提示/JS渲染)。建议手动确认一次。"True
        return "签到失败/未找到入口"f"未识别到签到成功/已签到文案,也未能稳定点击签到按钮。URL={url}"False
    def _extract_award_text(self, html_text: str) -> str:        # 提取积分/金币/威望等附近文本        patterns = [            r"(积分[^<\n]{0,40})",            r"(金币[^<\n]{0,40})",            r"(威望[^<\n]{0,40})",            r"(经验[^<\n]{0,40})",            r"(奖励[^<\n]{0,60})",        ]        for p in patterns:            m = re.search(p, html_text)            if m:                return m.group(1)        return ""
    # ------------------ 主流程 ------------------    def run(self) -> SignResult:        try:            if not self.login():                return SignResult(False"登录失败""账号密码错误/站点结构变化/需要验证码等导致无法自动登录", BASE_URL)
            sign_url = self.discover_sign_url()            if not sign_url:                return SignResult(False"未找到签到入口""签到入口可能隐藏在用户中心/任务中心,或需要指定具体签到URL", BASE_URL)
            return self.do_sign(sign_url)
        except Exception as e:            return SignResult(False"程序异常"f"{e}\n\n{traceback.format_exc()}", BASE_URL)        finally:            try:                self.driver.quit()            except Exception:                pass

def main():    username = env("SCOL_USERNAME")    password = env("SCOL_PASSWORD")    headless = env("SCOL_HEADLESS""true").lower() not in ["0""false""off"]    timeout = int(env("SCOL_TIMEOUT""20"))    push_token = env("PUSHPLUS_TOKEN""")
    if not username or not password:        print("❌ 缺少环境变量 SCOL_USERNAME / SCOL_PASSWORD")        print("✅ 示例:")        print("   export SCOL_USERNAME='你的账号'")        print("   export SCOL_PASSWORD='你的密码'")        return
    signer = ScolBbsSigner(username, password, headless=headless, timeout=timeout)    result = signer.run()
    print("=" * 60)    print(f"结果:{result.title}")    print(f"详情:{result.detail}")    print(f"入口:{result.raw_url}")    print("=" * 60)
    # 推送    if push_token:        pushplus_send(push_token, f"四川天府论坛签到 - {result.title}"f"{result.detail}\n\n入口:{result.raw_url}")

if __name__ == "__main__":    main()
解析

该脚本为天府论坛自动签到脚本,主要作用包括:

  • 自动登录四川天府论坛(兼容常见 Discuz 登录页结构)

  • 自动探测签到入口(优先常见插件 URL,失败再从页面"文本+链接"自动搜索)

  • 自动执行签到(点击"签到/打卡/立即签到"按钮)

  • 自动识别结果(成功/已签到/失败,并尝试提取积分等奖励信息)

  • 可选通知推送(PushPlus)

主要方法

1)login()

  • 作用:完成自动登录并判断是否登录成功

  • 关键点

    • 多个登录入口 URL 逐个尝试

    • 多种定位方式查找账号/密码输入框

    • 提交后返回首页,用"退出/设置/消息"等特征判断是否成功登录

2)discover_sign_url()

  • 作用:找到论坛"签到页面"地址

  • 策略

    1. 直接访问常见签到插件 URL(如 dsu_paulsign / k_misign / task

    2. 进入首页/任务中心/空间页,扫描链接文字包含"签到/打卡"等

    3. 若文本找不到,再从所有链接里匹配关键字(href 中含 sign/qiandao/task

3)do_sign(sign_url)

  • 作用:进入签到页并执行签到点击

  • 策略

    • 优先点击包含"签到/打卡/立即签到"的元素(a/button/span)

    • 点击后等待页面更新

    • 调用 _parse_sign_result() 解析结果

4)_parse_sign_result(html_text, clicked, url)

  • 作用:把页面返回内容归类为:

    • 签到成功(含"签到成功/打卡成功")

    • 今日已签到(含"已签到/今日已签到/已经签到")

    • 可能已触发(点了按钮但页面没出现明确文字,多数是弹窗/JS 渲染)

    • 失败(都不满足)


注意

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


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

没有评论:

发表评论

虚拟电话号码平台Hushed:隐私保护、接码验证、支持多国号码选择

Hushed是一款提供虚拟电话号码服务的在线平台,用户可通过邮箱注册,获取美国等多国号码用于通话、短信及语音验证,适用于联盟注册、支付验证等需要保护隐私或分隔工作生活的场景。目前提供30天套餐(5.99美元),支付方式支持信用卡。 Tags: 虚拟电话号码 接码平台 ...