开源一个掘金自动签到的油猴脚本

引言

作为一名掘金的忠实用户,我每天打开网站的第一件事就是签到。最近在写小册《油猴脚本实战指南》的收尾章节---------如何将油猴脚本打包成原生谷歌插件 时,想着既然都提到提到谷歌插件开发了,于是顺手把 Chrome 插件的快速入门教程整理到小册里。

就是因为这几天持续的写作,居然连续忘了好几次掘金签到,难受!作为脚本开发者,这事儿不能忍,必须写一个掘金自动签到脚本干它!

脚本效果与使用方式

要使用这个脚本,必须先通过谷歌商店,下载油猴扩展插件。

如果你无法翻墙下载,可以加我,shc1139874527,群里有学习资料和油猴插件下载地址。

然后,就可以通过脚本地址安装插件并使用。

脚本使用非常简单,当你打开任意网页且掘金没有签到时,它就会自动帮你签到。如下图,当我打开百度页面时,自动打开掘金后台标签,签到完成后,后台标签关闭,首页进行了提示。

实现原理

技术栈

脚本的技术栈很简单,就是将一段签到脚本(javascript代码)通过油猴注入到网页中执行逻辑。

油猴 是一个谷歌扩展程序,你可以在Chrome应用商店中,搜索 "篡改猴"进行安装。

用户可以将自己编写的任何javascript脚本放在油猴中执行,从而实现网页加强的功能。此外,油猴还提供了一些API,实现了突破浏览器限制的JS能力,比如跨域请求无视CSP限制、后台打开标签等。

如果你对脚本开发感兴趣,不妨看看《油猴脚本实战指南》这本小册,目前7折,可冲。

脚本原理

脚本的原理其实非常简单,当用户打开任意网站后,脚本会利用油猴提供的 GM_openInTab API 打开掘金的签到页面:

js 复制代码
const targetPage = "https://juejin.cn/user/center/signin"; // 掘金签到页面地址
const bgTab = GM_openInTab(targetPage); 

在掘金签到页,脚本会通过获取签到按钮的Dom元素文本内容,判断用户是否签到。如果用户没有签到,脚本则模拟用户点击签到按钮。

js 复制代码
const signBtn = document.querySelector(".code-calender button.btn"); // 查找签到按钮
if (signBtn) {
  if (signBtn.innerText.includes("立即签到")) {
    signBtn.click(); // 模拟点击签到按钮
  }
}

完成签到后,脚本会自动关闭该标签页,并通过 GM_setValue 储存签到状态。这样,下一次用户访问其他网页时,脚本会先判断是否已经签过到,避免重复触发,提高效率。

完整代码

下面是脚本的完整代码,大家可以直接复制到油猴的脚本新建页面中使用。

js 复制代码
// ==UserScript==
// @name         掘金自动签到助手
// @namespace    http://tampermonkey.net/
// @version      0.0.1
// @description  掘金自动签到助手,后台打开标签页版本
// @author       石小石Orz
// @match        *://*/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// @grant        GM_getTab
// @grant        GM_getTabs
// @grant        GM_saveTab
// @grant        GM_addElement
// @grant        unsafeWindow
// @grant        GM_openInTab
// @run-at       document-body
// @noframes
// ==/UserScript==

(async function () {
  "use strict";

  const targetPage = "https://juejin.cn/user/center/signin"; // 掘金签到页面地址
  const currentDate = new Date().toLocaleDateString(); // 获取当前日期(本地格式)
  const storedDate = GM_getValue("signTime", ""); // 读取上次签到的日期(默认空字符串)

  // 如果已经签到(存储的日期和今天一样),终止脚本执行
  if (storedDate === currentDate) return;

  // 显示签到成功提示框
  function showSuccessMessage(text = "掘金自动签到成功", duration = 3000) {
    const el = GM_addElement(document.body, "div", {
      textContent: text,
      style: `
            position: fixed;
            top: 20px;
            left: 50%;
            transform: translateX(-50%);
            background-color: #DAF7E1;
            color: #0C9B4A;
            padding: 10px 16px;
            font-size: 14px;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
            z-index: 99999;
            opacity: 0;
            transition: opacity 0.3s ease, transform 0.3s ease;
          `,
    });

    // 动画效果:渐显+下移
    requestAnimationFrame(() => {
      el.style.opacity = "1";
      el.style.transform = "translateX(-50%) translateY(10px)";
    });

    // 指定时间后自动移除提示框
    setTimeout(() => {
      el.style.opacity = "0";
      el.style.transform = "translateX(-50%) translateY(0)";
      setTimeout(() => el.remove(), 300);
    }, duration);
  }

  //   尝试执行签到操作(仅在签到页使用)
  const trySignIn = (close) => {
    unsafeWindow.addEventListener("load", () => {
      setTimeout(() => {
        const signBtn = document.querySelector(".code-calender button.btn"); // 查找签到按钮
        if (signBtn) {
          if (signBtn.innerText.includes("立即签到")) {
            signBtn.click(); // 模拟点击签到按钮
          }
          // 无论是否签到成功,都保存当前日期作为签到日期
          GM_setValue("signTime", currentDate);
          close && window.close();
        }
      }, 1000);
    });
  };

  // 获取当前标签页对象与所有已知标签页
  const [tab, tabs] = await Promise.all([GM.getTab(), GM.getTabs()]);

  // 判断是否已有"主页面"存在(主页面用于协调多个标签页避免重复签到)
  const hasMainPage = Object.values(tabs).some((t) => t?.isMainPage);

  // 如果没有主页面
  if (!hasMainPage) {
    if (location.href.startsWith(targetPage)) {
      // 当前页面就是签到页,直接尝试签到
      trySignIn();
    } else {
      // 当前不是签到页,将本标签页设为主页面,并在后台打开签到页面
      tab.isMainPage = true;
      await GM.saveTab(tab);
      const bgTab = GM_openInTab(targetPage); // 打开后台签到页面
      bgTab.onclose = () => {
        showSuccessMessage(); // 签到页关闭后显示提示
      };
    }
  } else {
    // 如果已有主页面,仅在签到页执行签到逻辑
    if (location.href.startsWith(targetPage)) {
      trySignIn(!tab?.isMainPage); // 主页面不关闭,其他页面签到完关闭
    } else {
      // 非签到页,重复打开一个签到页面进行操作
      const bgTab = GM_openInTab(targetPage);
      bgTab.onclose = () => {
        showSuccessMessage(); // 签到页关闭后显示提示
      };
    }
  }
})();

上述代码中,使用了一些GM_setValueGM_getTabGM_addElementGM_openInTab等一些油猴的API能力,其余代码和普通前端代码是没有任何差异的。

这些API小册中有详细介绍,你也可以参考官方API文档学习。

总结

这篇文章给大家带来了一个非常实用的油猴脚本------掘金自动签到,有需求的同学还不快用起来!JYM,快成为矿石大亨!

油猴脚本开发对前端同学来说非常容易入门,感兴趣的同学可以去学习哇!

相关推荐
Amodoro22 分钟前
nuxt更改页面渲染的html,去除自定义属性、
前端·html·nuxt3·nuxt2·nuxtjs
Wcowin30 分钟前
Mkdocs相关插件推荐(原创+合作)
前端·mkdocs
伍哥的传说1 小时前
CSS+JavaScript 禁用浏览器复制功能的几种方法
前端·javascript·css·vue.js·vue·css3·禁用浏览器复制
lichenyang4531 小时前
Axios封装以及添加拦截器
前端·javascript·react.js·typescript
Trust yourself2431 小时前
想把一个easyui的表格<th>改成下拉怎么做
前端·深度学习·easyui
三口吃掉你2 小时前
Web服务器(Tomcat、项目部署)
服务器·前端·tomcat
Trust yourself2432 小时前
在easyui中如何设置自带的弹窗,有输入框
前端·javascript·easyui
烛阴2 小时前
Tile Pattern
前端·webgl
前端工作日常2 小时前
前端基建的幸存者偏差
前端·vue.js·前端框架
Electrolux2 小时前
你敢信,不会点算法没准你赛尔号都玩不明白
前端·后端·算法