Summary: This script automatically logs into the Old Beijing Forum (obj.cc) and completes daily sign-in. It first tries known Discuz plugin URLs, then searches the page for sign-in buttons. It saves a screenshot for verification. The script requires Python with Playwright and environment variables for credentials.
阿里云:
服务器购买地址
https://t.aliyun.com/U/kcPAeY若失效,可用地址
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=2019052.部署教程
3.代码如下
# -*- coding: utf-8 -*-import osimport reimport sysimport timefrom urllib.parse import urljoinfrom playwright.sync_api import sync_playwright, TimeoutError as PWTimeoutErrorclass ObjForumSignIn:def __init__(self):self.base_url = os.getenv("OBJ_BASE_URL", "http://www.obj.cc/").strip()self.username = os.getenv("OBJ_USERNAME", "").strip()self.password = os.getenv("OBJ_PASSWORD", "").strip()if not self.username or not self.password:print("❌ 缺少环境变量 OBJ_USERNAME / OBJ_PASSWORD")sys.exit(1)# 常见的 Discuz 登录入口(不保证命中,但可作为导航参考)self.common_login_paths = ["member.php?mod=logging&action=login","member.php?mod=logging&action=login&loginsubmit=yes",]# Discuz 常见签到插件(非常多站点用这个)self.common_signin_paths = ["plugin.php?id=dsu_paulsign:sign", # dsu_paulsign"plugin.php?id=k_misign:sign", # 另一种常见签到插件"plugin.php?id=dc_signin:signin", # 另一种可能]def run(self):with sync_playwright() as p:browser = p.chromium.launch(headless=True)context = browser.new_context()page = context.new_page()print(f"🌐 打开站点:{self.base_url}")page.goto(self.base_url, wait_until="domcontentloaded", timeout=60_000)# 1) 登录self.login(page)# 2) 尝试签到(先走插件直达,再走页面找按钮)ok = self.try_signin_by_common_plugin_url(page)if not ok:ok = self.try_signin_by_ui_search(page)# 3) 输出结果 + 保存截图ts = time.strftime("%Y%m%d_%H%M%S")shot = f"obj_signin_{ts}.png"page.screenshot(path=shot, full_page=True)if ok:print(f"✅ 签到流程已执行(不代表100%成功,以页面提示为准),截图:{shot}")else:print(f"⚠️ 未能确认签到成功/未找到签到入口,截图:{shot}")context.close()browser.close()def login(self, page):"""自动登录:优先尝试识别"登录/用户名/密码"输入框"""print("🔐 开始登录检测...")# 先尝试点"登录/登陆"self.safe_click_by_text(page, ["登录", "登陆", "立即登录", "帐号登录"], soft=True)# 等待可能出现的输入框# 常见用户名输入框:name=username / id=username / placeholder 含 用户名/账号/邮箱/手机user_locator = page.locator("input[name='username'], input#username, input[name='account'], input[name='email'], ""input[placeholder*='用户名'], input[placeholder*='账号'], input[placeholder*='邮箱'], input[placeholder*='手机']")pass_locator = page.locator("input[type='password'], input[name='password'], input#password, input[placeholder*='密码']")# 如果首页没找到,就跳登录页常见地址试试if user_locator.count() == 0 or pass_locator.count() == 0:for path in self.common_login_paths:url = urljoin(self.base_url, path)try:page.goto(url, wait_until="domcontentloaded", timeout=30_000)user_locator = page.locator("input[name='username'], input#username, input[name='account'], input[name='email'], ""input[placeholder*='用户名'], input[placeholder*='账号'], input[placeholder*='邮箱'], input[placeholder*='手机']")pass_locator = page.locator("input[type='password'], input[name='password'], input#password, input[placeholder*='密码']")if user_locator.count() > 0 and pass_locator.count() > 0:breakexcept Exception:continueif user_locator.count() == 0 or pass_locator.count() == 0:print("⚠️ 未识别到登录输入框:可能已登录/站点结构不同/需要验证码")return# 填写账号密码user_locator.first.fill(self.username)pass_locator.first.fill(self.password)# 提交:常见 submit / button 文案clicked = self.safe_click_by_text(page, ["登录", "登陆", "提交", "立即登录"], soft=True)if not clicked:# 兜底:按 Enterpass_locator.first.press("Enter")# 等待跳转/刷新page.wait_for_timeout(3000)# 简单判断:页面出现"退出/注销/我的/个人中心"之一if self.page_has_any_text(page, ["退出", "注销", "我的", "个人中心", "设置"]):print("✅ 登录疑似成功(检测到登录态关键词)")else:print("⚠️ 登录状态未能确认:可能需要验证码/滑块/二次验证,请看截图或手动排查")def try_signin_by_common_plugin_url(self, page) -> bool:"""直达常见签到插件 URL,命中率高(Discuz 常见)"""print("🧭 尝试通过常见签到插件URL直达签到...")for path in self.common_signin_paths:url = urljoin(self.base_url, path)try:page.goto(url, wait_until="domcontentloaded", timeout=30_000)page.wait_for_timeout(1500)# 如果页面出现"签到成功/已签到/今日已签到/获得/奖励"等if self.page_has_any_text(page, ["签到成功", "已签到", "今日已签到", "签到完成", "奖励", "获得"]):# 有些插件需要点按钮self.safe_click_by_text(page, ["签到", "立即签到", "打卡"], soft=True)page.wait_for_timeout(1500)if self.page_has_any_text(page, ["签到成功", "已签到", "今日已签到", "签到完成"]):print(f"✅ 命中签到页并检测到成功提示:{url}")return True# 如果存在"签到"按钮也尝试点一下if self.safe_click_by_text(page, ["签到", "立即签到", "打卡"], soft=True):page.wait_for_timeout(1500)if self.page_has_any_text(page, ["签到成功", "已签到", "今日已签到", "签到完成"]):print(f"✅ 通过插件页按钮签到成功:{url}")return Trueexcept PWTimeoutError:continueexcept Exception:continueprint("ℹ️ 插件直达未命中(可能不是Discuz/插件名不同/站点关闭签到)")return Falsedef try_signin_by_ui_search(self, page) -> bool:"""页面找"签到/打卡"入口点击(适合非 Discuz 或者入口藏在导航/用户菜单里)"""print("🔎 尝试在页面中搜索"签到/打卡"入口...")# 回首页try:page.goto(self.base_url, wait_until="domcontentloaded", timeout=30_000)page.wait_for_timeout(1500)except Exception:pass# 先点"我的/个人中心/用户"展开菜单self.safe_click_by_text(page, ["我的", "个人中心", "用户中心", "头像", "账户"], soft=True)# 多轮尝试:可能入口在顶部/侧边栏/弹层里for _ in range(3):if self.safe_click_by_text(page, ["签到", "打卡", "每日签到", "签到领", "签到有礼"], soft=True):page.wait_for_timeout(2000)if self.page_has_any_text(page, ["签到成功", "已签到", "今日已签到", "签到完成", "获得", "奖励"]):print("✅ UI入口签到:检测到成功/奖励关键词")return True# 尝试滚动,触发懒加载或露出入口page.mouse.wheel(0, 800)page.wait_for_timeout(800)print("⚠️ 未找到可点击的签到入口或无法确认成功")return Falsedef safe_click_by_text(self, page, texts, soft=False) -> bool:"""安全点击:按文本匹配按钮/链接soft=True:找不到不报错"""for t in texts:try:# button / a / div role=button 等locator = page.get_by_text(t, exact=False)if locator.count() > 0:locator.first.click(timeout=2000)page.wait_for_timeout(500)return Trueexcept Exception:continueif not soft:raise RuntimeError(f"未找到可点击元素:{texts}")return Falsedef page_has_any_text(self, page, keywords) -> bool:"""检测页面是否包含关键词(用于判定是否签到成功/是否登录)"""try:html = page.content()except Exception:return Falsefor k in keywords:if k in html:return Truereturn Falseif __name__ == "__main__":ObjForumSignIn().run()
自动打开老北京论坛(obj.cc)
自动完成登录(用户名/密码)
自动完成签到:
1)优先尝试 Discuz 常见签到插件 URL(命中率高)
2)若失败,则在页面里自动寻找"签到/打卡/每日签到"等入口点击最后自动截图保存,便于你确认是否签到成功/是否弹验证码
主要方法
run→ 程序总入口:启动浏览器、打开站点、执行登录与签到、保存截图并退出login→ 自动识别登录入口与用户名/密码输入框,填充后提交,尽量确认登录态try_signin_by_common_plugin_url→ 通过常见 Discuz 签到插件路径直达签到页并执行签到try_signin_by_ui_search→ 在页面中搜索"签到/打卡"等入口并点击,适配非 Discuz 或入口不固定的站点safe_click_by_text→ 按文本模糊匹配点击按钮/链接,找不到时可选择静默失败page_has_any_text→ 从页面 HTML 中判断是否包含"签到成功/已签到"等关键词,用于结果确认
注意:
本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。
没有评论:
发表评论