1. 掘金签到这件事,为什么值得用 Chrome 插件自动化
掘金每天签到能领矿石,连续签到天数越多,单日到手的矿石越多,攒够之后可以去幸运抽奖页面抽实物奖品。问题在于手动签到太容易断——加班到深夜想起来、周末出门忘了、出差换电脑登录状态丢了,连续签到一断,矿石数量直接掉档。我试过设手机闹钟提醒,坚持了不到两周就放弃了,因为提醒响了也不一定在电脑前。
这类「每天固定时间、固定页面、固定几个点击」的重复动作,天然适合交给浏览器插件。相比引入第三方 RPA 软件,Chrome 插件有几个实际好处:不用额外装软件、跟着浏览器启动、能直接复用浏览器里已有的登录态、定时任务用chrome.alarms就能跑。你只需要在扩展程序管理页加载一次,之后它自己按设定时间干活。
这篇要交付的是一套可跟做的流程:用 Trae 生成「掘金自动签到助手」插件的骨架,拿到可复制的manifest.json和 content script,把签到、抽奖、定时、随机延迟这几件事串起来,最后在浏览器里验证签到成功、矿石到账。面向的是想用 AI 编程提效的前端开发者,也适合刚接触 Chrome 插件、想拿一个真实小项目练手的人。核心检索词就三个:Trae、Chrome 插件、AI 编程,全文围绕它们展开。
需要提前说清楚一个边界:插件模拟的是你自己账号在浏览器里的正常操作,签到按钮、去抽奖按钮、单抽按钮的定位都基于掘金页面当前的 DOM 结构。页面元素一旦改版,选择器就会失效,这是所有基于元素定位的自动化方案的通病,后面排障章节会专门讲怎么快速修。
另外,AI 编程工具不止 Trae 一家,Cursor、Windsurf、Cline 都能做。选 Trae 是因为它对中文提示词的理解比较稳,Builder 智能体可以直接在项目里读写文件、跑命令,对「新建文件夹→生成插件→改配置」这种连续动作比较友好。下面从环境准备开始,一步步走完。
2. 用 Trae 生成插件骨架:manifest.json 与 content script 怎么落地
先在本地建一个空文件夹,命名随意,比如juejin-auto-checkin,然后用 Trae 打开这个文件夹。Trae 的项目视图会把这个空目录当成工作区,后续生成的manifest.json、background.js、content.js、popup.html都会落在这里。这一步不要省,直接在 Trae 里新建项目比在已有大项目里加插件目录更干净,避免 AI 把无关文件也扫进去。
接下来是关键:提示词怎么写。很多人用 AI 编程效果差,不是模型不行,是提示词太笼统。你要把「做什么、在哪做、用什么做、元素怎么定位、异常怎么处理」都写进去。下面是我实测下来生成质量比较稳的一版提示词模板,你可以直接改:
我想创建一个 Chrome 浏览器插件「掘金自动签到助手」,Manifest V3。 功能: 1. 每天在用户设定的时间(默认 21:00)自动打开掘金签到页 https://juejin.cn/user/center/signin?from=sign_in_menu_bar 2. 签到前先判断是否登录,未登录则跳过并记录日志 3. 登录状态下点击签到按钮,定位 button.signedin.btn 4. 签到后进入幸运抽奖页,点击「去抽奖」按钮 button.btn 5. 在抽奖页点击单抽按钮 div#turntable-item-0.turntable-item.lottery 6. 执行时间在设定值基础上加 0~30 分钟随机延迟 7. 执行完成后关闭自动打开的标签页 8. 签到时间和是否抽奖可在 popup 中自定义,配置存 chrome.storage 技术约束: - 使用 chrome.alarms 做定时,不用 setInterval - background 用 Service Worker - 页面操作放在 content script,通过 chrome.tabs.sendMessage 通信 - 权限遵循最小化原则 请生成完整文件:manifest.json、background.js、content.js、popup.html、popup.js提示词里我特意把三个选择器写死了:签到按钮button.signedin.btn、去抽奖按钮button.btn、单抽按钮div#turntable-item-0.turntable-item.lottery。这是从掘金页面上手动复制下来的,AI 拿到精确选择器后,生成的选择器匹配逻辑基本一次就对。如果你不写,AI 会自己猜,猜出来的querySelector经常匹配不到,后面就得反复调。
Trae 的 Builder 智能体会根据提示词直接创建文件。生成完之后,先看manifest.json,这是插件的入口,结构必须对。一个可用的 MV3 版本大概长这样:
{ "manifest_version": 3, "name": "掘金自动签到助手", "version": "1.0.0", "description": "每天自动完成掘金签到与抽奖", "permissions": ["alarms", "storage", "tabs", "scripting"], "host_permissions": ["https://juejin.cn/*"], "background": { "service_worker": "background.js" }, "action": { "default_popup": "popup.html", "default_icon": { "16": "images/icon16.png", "48": "images/icon48.png", "128": "images/icon128.png" } }, "content_scripts": [ { "matches": ["https://juejin.cn/*"], "js": ["content.js"], "run_at": "document_idle" } ], "icons": { "16": "images/icon16.png", "48": "images/icon48.png", "128": "images/icon128.png" } }注意permissions里alarms负责定时、storage存配置、tabs开标签页、scripting注入脚本,host_permissions只给掘金域名,别写成<all_urls>,权限越大审核越麻烦,也没必要。
content script 是真正干活的,它跑在掘金页面上下文里,负责找按钮、点击、回报结果。骨架逻辑是:等页面加载完 → 判断登录 → 点签到 → 跳抽奖 → 点单抽 → 回报。核心片段:
// content.js function waitFor(selector, timeout = 10000) { return new Promise((resolve, reject) => { const start = Date.now(); const timer = setInterval(() => { const el = document.querySelector(selector); if (el) { clearInterval(timer); resolve(el); } else if (Date.now() - start > timeout) { clearInterval(timer); reject(new Error('元素未找到: ' + selector)); } }, 300); }); } async function doCheckin() { const signBtn = await waitFor('button.signedin.btn'); if (signBtn.textContent.includes('已签到')) { return { ok: true, msg: '今日已签到' }; } signBtn.click(); return { ok: true, msg: '签到完成' }; } chrome.runtime.onMessage.addListener((req, sender, sendResponse) => { if (req.action === 'checkin') { doCheckin() .then(sendResponse) .catch((e) => sendResponse({ ok: false, msg: e.message })); return true; } });waitFor这个轮询函数很关键。掘金页面是异步渲染的,直接document.querySelector很可能拿到 null,加个超时轮询能大幅降低「元素未找到」的报错率。background.js 里用chrome.alarms.create注册定时任务,触发时用chrome.tabs.create打开签到页,再chrome.tabs.sendMessage通知 content script 执行。随机延迟用Math.random() * 30 * 60 * 1000算出来加到 alarm 时间上。
生成完第一版后,Trae 里可以继续对话优化。比如让它「把签到和抽奖拆成两个独立函数,抽奖失败不影响签到结果记录」,或者「在 popup 里加一个立即执行按钮,方便手动测试」。多轮对话比一次性写超长提示词更可控。
3. 可复制配置:popup 设置项与 storage 结构
插件装好后,用户要能改签到时间、开关抽奖。这部分配置存在chrome.storage.sync里,popup 页面负责读写。先定义清楚 storage 的数据结构,不然后面 background 和 popup 对不上字段名,调试很痛苦。建议用这样一份配置:
{ "enabled": true, "checkinTime": "21:00", "randomDelayMinutes": 30, "doLottery": true, "lastRunDate": "", "lastResult": "" }字段含义:enabled总开关,checkinTime每日执行时间(24 小时制),randomDelayMinutes随机延迟上限,doLottery是否抽奖,lastRunDate记录上次执行日期用来防重复,lastResult存最近一次结果方便在 popup 里展示。
popup.html 里放一个时间输入框、一个数字输入框、两个开关、一个「立即执行」按钮。popup.js 读取和保存配置:
// popup.js const DEFAULTS = { enabled: true, checkinTime: '21:00', randomDelayMinutes: 30, doLottery: true }; async function loadConfig() { const cfg = await chrome.storage.sync.get(DEFAULTS); document.getElementById('time').value = cfg.checkinTime; document.getElementById('delay').value = cfg.randomDelayMinutes; document.getElementById('enabled').checked = cfg.enabled; document.getElementById('lottery').checked = cfg.doLottery; } async function saveConfig() { await chrome.storage.sync.set({ checkinTime: document.getElementById('time').value, randomDelayMinutes: Number(document.getElementById('delay').value), enabled: document.getElementById('enabled').checked, doLottery: document.getElementById('lottery').checked }); chrome.runtime.sendMessage({ action: 'reschedule' }); } document.addEventListener('DOMContentLoaded', loadConfig); document.getElementById('save').addEventListener('click', saveConfig);background.js 里监听reschedule消息,重新计算下一次 alarm 时间。计算逻辑:把checkinTime解析成当天的时和分,加上随机延迟,如果算出来的时间已经过了当前时刻,就顺延到明天。用chrome.alarms.create('juejinCheckin', { when: nextTs })注册。Service Worker 会被浏览器休眠,所以不能靠内存变量记状态,每次触发都从 storage 读配置重新算,这是 MV3 和 MV2 最大的区别,很多人踩坑就踩在这。
如果你在 Trae 里让 AI 生成这部分,记得在提示词里强调「Service Worker 可能随时被回收,所有状态必须持久化到 chrome.storage」。不强调的话,AI 有时会生成依赖全局变量的代码,测试时正常,过几小时 alarm 触发就失效。
关于模型选择,Trae 里可以切换不同模型。生成插件骨架这种需要一次成型、结构完整的任务,用编程能力强的模型更稳;修具体报错时,换一个擅长定位问题的模型往往更快。我实测下来,生成阶段和排错阶段用不同模型搭配,整体效率比死磕一个模型高。这跟用 TaoToken 做多模型接入的思路一致——不同任务路由到不同模型,成本和效果都能兼顾。
4. 加载插件并验证:签到成功与矿石到账怎么确认
代码写完,进入验证环节。打开 Chrome,地址栏输入chrome://extensions/,右上角打开「开发者模式」,点「加载已解压的扩展程序」,选中你的项目文件夹。加载成功后列表里会出现「掘金自动签到助手」,如果 manifest 有语法错误,这里会直接报红并给出文件名和行号,照着改就行。
加载后先别等定时,点插件图标打开 popup,点「立即执行」手动触发一次。这时候打开掘金签到页,按 F12 看 Console,content script 的日志会打在这里。正常流程你应该看到:页面加载 → 检测到登录 → 点击签到按钮 → 按钮文案变成「今日已签到」→ 跳转抽奖页 → 点击单抽。如果中间卡住,Console 会告诉你卡在哪一步。
验证签到是否真的成功,不能只看插件日志,要去掘金「成长福利」页面看矿石余额。签到前记一下当前矿石数,执行后再看,数字应该增加。连续签到天数也会 +1。抽奖的话,抽奖页会弹出结果动画,中奖记录在抽奖历史里能查到。这两处是最终验收标准,插件日志只是过程参考。
定时任务怎么验证?把checkinTime设成当前时间往后 2 分钟,randomDelayMinutes设成 0,保存后等 2 分钟。background 的 Service Worker 日志在chrome://extensions/里点插件卡片上的「Service Worker」链接能看到,会打印 alarm 触发、打开标签页、发送消息这些步骤。等它自动跑完一轮,说明定时链路通了。验证完记得把时间改回你真正想要的值,随机延迟也调回去。
有个细节:lastRunDate防重复。如果同一天 alarm 因为浏览器重启等原因触发多次,靠这个字段判断今天是否已经跑过,跑过就跳过。实现上在 background 触发时先读lastRunDate,等于今天日期就直接 return。这个字段在手动「立即执行」时不检查,方便你随时测试。
验证通过后,插件就可以日常挂着用了。建议把执行时间设在你每天大概率开着电脑的时间段,比如晚上八九点,这样 alarm 触发时浏览器是活的,标签页能正常打开。如果设成凌晨,电脑关机状态下 alarm 不会补跑,当天就漏签了。
5. 常见报错排查:从 401 到元素定位失效
插件开发过程中有几类报错出现频率特别高,提前知道怎么处理能省很多时间。
第一类:Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.这个报错的意思是 background 给某个标签页发消息,但那个标签页里没有 content script 在监听。常见原因有两个:一是标签页还没加载完 content script 就发了消息,二是标签页 URL 不在content_scripts.matches范围内。解决办法是在 background 里发消息前先确认标签页已加载完成,用chrome.tabs.onUpdated监听status === 'complete'再发;同时检查matches有没有覆盖到实际页面。把这段报错原文复制给 Trae,让它定位到具体是哪次sendMessage调用,通常几轮就能修好。
第二类:元素未找到: button.signedin.btn。这是选择器失效。掘金页面改版、按钮 class 变了、或者页面结构异步渲染导致轮询超时,都会报这个。排查步骤:打开签到页,F12 用 Elements 面板找到签到按钮,右键 Copy → Copy selector,看复制出来的选择器和代码里写的是否一致。不一致就更新代码里的选择器。如果一致但还是找不到,可能是按钮在 iframe 里,需要先切 iframe 再查。这类问题没有一劳永逸的解法,页面一改就得跟着改,所以插件代码里把选择器集中定义在文件顶部,改起来方便。
第三类:登录态判断出错。插件判断是否登录,常见做法是查页面上有没有用户头像元素,或者调掘金的用户信息接口看返回。如果判断逻辑写错,会出现「明明登录了却跳过签到」或者「没登录还去点按钮」。排查时在 Console 里手动执行判断语句,看返回值是否符合预期。登录态相关的接口如果返回 401,说明 cookie 过期,需要用户重新登录掘金,插件这边记录日志跳过即可,不要反复重试。
第四类:chrome.alarms不触发。MV3 的 Service Worker 会被回收,如果 alarm 注册代码写在 Service Worker 顶层但没在安装时执行,或者注册后又被覆盖,就会不触发。检查方法:在chrome://extensions/打开 Service Worker 控制台,执行chrome.alarms.getAll(console.log),看有没有你注册的 alarm、scheduledTime是不是预期值。没有就说明注册失败,检查chrome.runtime.onInstalled和onStartup里有没有重新注册。
第五类:OAuth 或第三方登录跳转导致 content script 丢失。如果你的掘金账号是用第三方方式登录的,签到过程中可能跳转到登录页,content script 在新页面里重新注入,但原来的消息通道断了。处理办法是在 content script 里监听页面 URL 变化,跳转到登录页就中止当前任务并回报「需要重新登录」。
排查这些问题的通用思路:先看报错原文,定位到文件和行号;再在 Console 里手动复现那一步操作;最后把报错和上下文一起丢给 Trae 让它修。AI 排错比人快的地方在于它能同时看多个文件,但前提是你给的报错信息要完整,别只截一半。
6. 把插件跑稳之后:模型搭配与后续维护
插件能跑起来只是第一步,长期稳定用下去还有几件事要做。
图标问题。AI 生成的插件默认图标经常是占位图或者 svg 格式,Chrome 加载时可能显示不出来。你需要准备 16x16、48x48、128x128 三个尺寸的 png,放到images目录,manifest.json里的路径要对上。图标可以用在线工具生成,也可以用 AI 画图工具出图后自己裁尺寸。改完图标记得在扩展管理页点「重新加载」才生效。
README 和开源。如果你想把插件分享给别人用,让 Trae 根据项目生成一份 README,写清楚安装步骤、配置说明、已知限制。这一步 AI 写得比手写规范,省事。开源到 GitHub 的话,注意别把个人配置、cookie 之类的敏感信息提交上去。
模型搭配的经验。整个开发过程里,生成骨架、写完整文件适合用结构能力强的模型;修具体报错、定位选择器问题适合用推理细致的模型。Trae 支持切换模型,别一个模型用到底。如果你同时用多个 AI 编程工具,或者想把不同模型的调用统一管理,可以用 TaoToken 这类聚合接入的方式,一个 Key 走多个模型,省去分别配置的麻烦。它的 API 地址是https://taotoken.net/api,接入文档在官网能查到,模型对话、Coding Plan、API Keys 都有对应入口。
页面改版的应对。前面反复强调过,基于元素定位的自动化,页面一改就失效。降低维护成本的做法:把所有选择器集中在一个selectors.js里导出,content script 引用它;加一个「自检」功能,插件启动时检查关键选择器是否存在,不存在就在 popup 里提示「页面可能已改版,请更新选择器」。这样你不用等签到失败才发现问题。
最后一点,AI 编程有随机性,同样的提示词两次生成结果可能不同。遇到生成质量差的时候,别硬改,重新生成一版往往更快。如果反复生成都不理想,可以在 Trae 里配置项目规则,把 Chrome 插件开发的规范(MV3、Service Worker、最小权限、chrome.alarms 定时等)写进去约束 AI,减少它自由发挥导致的结构错误。规则写一次,后续所有生成都受益。
想动手的话,现在就可以建个空文件夹,把第 2 节的提示词贴进 Trae,五分钟能看到第一版插件跑起来。签到时间设成你每天开着电脑的时段,剩下的交给 alarm。