Node.js+Express+Nodemailer+QQ邮箱SMTP:从零实现邮箱验证码模块
1. 从一个真实需求说起为什么邮箱验证码模块值得自己写很多做Web项目的朋友都遇到过这个场景用户注册、登录、找回密码需要发一封验证码邮件。第一反应往往是找第三方短信或邮件服务但短信要钱、要资质邮件反而是成本最低、门槛最小的通道。尤其是面向海外用户或者内部系统邮箱验证码几乎是标配。但真动手写的时候问题就来了。网上一搜Node.js发邮件清一色是nodemailer的官方示例复制过来跑一下本地能发一部署到服务器就报错或者能发出去但进了垃圾箱再或者验证码生成逻辑写得稀烂存在被暴力破解的风险。更别提QQ邮箱这个在国内使用率极高的服务它的授权机制和普通SMTP不太一样很多人卡在授权码这一步就放弃了。这篇内容就是把我自己从零搭一个Web端邮箱验证码模块的完整过程拆开讲。核心目标很明确用Node.js Express Nodemailer QQ邮箱SMTP实现一个能生成验证码、发送邮件、校验验证码、带过期和频率限制的完整模块。适合有一定JavaScript基础、想给自己的项目加上邮箱验证功能的开发者也适合想理解一个验证码从生成到校验到底经历了什么的初学者。我不会只给你一段能跑的代码就完事。我会把每个设计决策背后的原因讲清楚——为什么用QQ邮箱而不是别的、授权码到底是怎么回事、验证码为什么要存Redis而不是内存、频率限制怎么做才不会被绕过。这些才是真正决定你这个模块能不能上生产的关键。2. QQ邮箱SMTP的授权机制为什么不能用登录密码2.1 授权码不是密码这是第一道坎刚开始做的时候我最容易犯的错误就是拿QQ邮箱的登录密码去填SMTP的密码字段。结果就是连接直接被拒报一个535 Authentication failed的错误。当时还以为是端口或者加密方式的问题折腾了半天才发现QQ邮箱以及绝大多数主流邮箱服务早就禁止了用账户密码直接登录SMTP。原因很简单如果你的应用里明文存了邮箱密码一旦服务器被入侵或者代码泄露攻击者拿到的不只是一个发邮件的能力而是你整个邮箱的控制权——能看邮件、能改密码、能发钓鱼邮件。所以邮箱服务商引入了授权码这个概念。授权码本质上是一个专用于第三方客户端的独立密码。它和你的登录密码分离你可以随时在邮箱设置里生成、撤销、重置而不影响你正常登录网页邮箱。即使授权码泄露你只需要重新生成一个旧的就立刻失效。2.2 获取QQ邮箱授权码的完整步骤这一步必须手动在网页端操作没有API可以绕过。具体流程如下登录QQ邮箱网页版点击顶部导航栏的设置。进入账户选项卡找到POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务这一栏。开启IMAP/SMTP服务如果你只需要发邮件开启SMTP就够了但建议一起开。系统会要求你用绑定的手机号发送一条短信进行验证。验证通过后会弹出一个16位的授权码形如abcdefghijklmnop。注意这个授权码只会显示一次关掉弹窗就再也看不到了。一定要立刻复制保存到你的环境变量文件里。如果丢了只能重新生成一个旧的会失效。这里有个细节很多人不知道授权码可以生成多个。你可以给不同的应用生成不同的授权码这样某个应用出问题时只撤销那一个授权码不影响其他应用。这是个很好的安全实践。2.3 SMTP连接参数的正确配置拿到授权码之后连接QQ邮箱SMTP需要以下参数参数值说明hostsmtp.qq.comQQ邮箱SMTP服务器地址port465SSL加密端口推荐securetrue465端口必须设为trueauth.user你的QQ邮箱地址完整地址如xxxqq.comauth.pass授权码不是登录密码也可以用587端口配合STARTTLS但465 SSL是最省事的组合不需要额外配置requireTLS。我实测下来465端口的连接成功率和稳定性都更好尤其是在一些网络环境比较特殊的服务器上。这里要特别提醒授权码不要硬编码在代码里。用dotenv加载环境变量把授权码放在.env文件中并且把.env加入.gitignore。我见过太多项目因为把密钥提交到代码仓库而泄露的案例。3. 验证码生成随机数不是随便写个Math.random就行3.1 验证码的安全要求验证码看起来简单就是生成几个随机数字。但如果用Math.random()来生成那就埋了个大雷。Math.random()是伪随机数生成器它的输出是可以被预测的。攻击者如果知道你的生成算法和大致的时间窗口理论上可以推算出你生成的验证码从而绕过验证。正确的做法是用Node.js内置的crypto模块。crypto.randomInt()是密码学安全的随机数生成器生成的数字不可预测。这是生成验证码的唯一正确选择。const crypto require(crypto); function generateCode(length 6) { // 生成一个6位数字验证码范围100000-999999 const min Math.pow(10, length - 1); const max Math.pow(10, length) - 1; return crypto.randomInt(min, max 1).toString(); }3.2 验证码长度和复杂度的权衡验证码长度是个需要权衡的问题。太短容易被暴力破解太长用户输入体验差。常见的做法是4位纯数字10^4 10000种组合配合频率限制和过期时间安全性够用用户体验最好。适合对安全性要求不高的场景。6位纯数字10^6 100万种组合是主流选择。QQ邮箱、微信、银行App基本都用6位。6位字母数字混合36^6 ≈ 21亿种组合安全性更高但用户输入容易出错尤其是区分大小写和易混淆字符0和O、1和l。我的建议是6位纯数字。配合后面要讲的频率限制和尝试次数限制安全性完全足够。不要为了追求看起来安全而牺牲用户体验。3.3 验证码的存储结构设计验证码生成之后需要存起来等待校验。存储结构的设计直接决定了后续校验逻辑的复杂度。我推荐用Redis的Hash结构来存key的设计如下email:code:{email} - { code: 123456, attempts: 0, createdAt: 1699999999 }为什么用Hash而不是简单的String因为我要同时存验证码、尝试次数、创建时间三个信息。用Hash可以一次性读取和更新减少Redis的往返次数。如果用String存JSON每次更新都要序列化和反序列化性能和可读性都差一些。过期时间用Redis的EXPIRE来设置比如5分钟。这样即使我的应用层忘记清理Redis也会自动删除过期的验证码不会造成内存泄漏。提示如果你不想引入Redis用内存Map也能实现但要注意两点一是多实例部署时内存不共享二是进程重启后验证码全部丢失。生产环境强烈建议用Redis。4. 邮件发送模块的完整实现与踩坑记录4.1 Nodemailer的初始化与连接池Nodemailer是Node.js生态里发邮件的事实标准。但很多人不知道的是默认情况下每次发邮件都会新建一个SMTP连接发完就断开。在高并发场景下这会带来大量的连接开销甚至被SMTP服务器限流。正确的做法是使用连接池const nodemailer require(nodemailer); const transporter nodemailer.createTransport({ host: smtp.qq.com, port: 465, secure: true, auth: { user: process.env.QQ_EMAIL, pass: process.env.QQ_AUTH_CODE }, pool: true, // 启用连接池 maxConnections: 3, // 最大连接数 maxMessages: 100, // 每个连接最多发100封 rateDelta: 1000, // 限流时间窗口1秒 rateLimit: 5 // 每秒最多发5封 });pool: true开启连接池后Nodemailer会复用SMTP连接大幅提升发送效率。maxConnections控制最大并发连接数QQ邮箱对单个账号的连接数有限制设太大反而会被拒绝。我实测下来3个连接是比较稳妥的值。rateLimit和rateDelta是Nodemailer内置的限流机制防止你在短时间内发送过多邮件触发QQ邮箱的风控。这个和应用层的频率限制是两回事应用层限制的是同一个用户多久能请求一次Nodemailer限制的是整个应用每秒最多发多少封。4.2 邮件内容的构造别让验证码进垃圾箱邮件能不能进收件箱而不是垃圾箱内容构造很关键。我踩过的坑包括标题太营销化、正文全是图片、包含大量链接、发件人名称是乱码。正确的做法const mailOptions { from: 验证码服务 ${process.env.QQ_EMAIL}, to: targetEmail, subject: 您的验证码, text: 您的验证码是${code}5分钟内有效。请勿泄露给他人。, html: div stylefont-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; h2 stylecolor: #333;验证码/h2 p您正在进行的操作需要验证身份验证码为/p p stylefont-size: 32px; font-weight: bold; color: #1a73e8; letter-spacing: 4px;${code}/p p stylecolor: #666;验证码5分钟内有效请勿泄露给他人。/p p stylecolor: #999; font-size: 12px;如果这不是您本人的操作请忽略此邮件。/p /div };几个关键点同时提供text和html两个版本。有些邮件客户端不渲染HTML只有text版本才能正常显示。标题不要用免费优惠点击这类营销词汇容易被垃圾邮件过滤器拦截。正文里不要放短链接短链接是垃圾邮件的重灾区。发件人名称用中文比纯邮箱地址更可信。4.3 发送失败的排查链路邮件发送失败是家常便饭关键是要能快速定位问题。我总结了一个排查顺序错误码/现象可能原因排查方法535 Authentication failed授权码错误或未开启SMTP重新生成授权码确认IMAP/SMTP服务已开启ETIMEDOUT端口被封或网络不通换465端口检查服务器出站规则550 Mailbox not found收件地址不存在校验邮箱格式确认地址拼写554 邮件被拒内容触发风控检查标题和正文去掉链接和敏感词连接数超限并发太高降低maxConnections加发送队列我遇到最多的是535错误基本都是授权码的问题。有一次是授权码复制的时候多了个空格排查了半小时才发现。所以复制授权码后一定要trim一下。5. 频率限制与防刷让验证码接口不被滥用5.1 为什么频率限制是必须的没有频率限制的验证码接口等于给攻击者开了一扇门。他们可以用你的接口给任意邮箱发验证码把你的邮箱账号变成垃圾邮件发送器轻则被QQ邮箱封禁重则被列入黑名单。而且每次发邮件都消耗你的配额成本是实打实的。频率限制要分两个维度同一邮箱的发送频率和同一IP的请求频率。前者防止针对某个邮箱的轰炸后者防止攻击者用脚本批量请求不同邮箱。5.2 基于Redis的滑动窗口限流固定窗口限流比如每分钟最多1次有个问题如果在第59秒发了一次第61秒又发一次实际上两次只间隔了2秒但固定窗口认为这是两个不同的窗口都放行了。滑动窗口能解决这个问题。async function checkRateLimit(email, ip) { const now Date.now(); const windowSize 60 * 1000; // 1分钟窗口 const maxRequests 1; // 窗口内最多1次 const emailKey rate:email:${email}; const ipKey rate:ip:${ip}; // 用Redis的有序集合实现滑动窗口 const pipeline redis.pipeline(); // 移除窗口外的记录 pipeline.zremrangebyscore(emailKey, 0, now - windowSize); pipeline.zremrangebyscore(ipKey, 0, now - windowSize); // 统计窗口内的请求数 pipeline.zcard(emailKey); pipeline.zcard(ipKey); const results await pipeline.exec(); const emailCount results[2][1]; const ipCount results[3][1]; if (emailCount maxRequests) { return { allowed: false, reason: 该邮箱请求过于频繁请稍后再试 }; } if (ipCount maxRequests * 5) { return { allowed: false, reason: 当前网络请求过于频繁请稍后再试 }; } // 记录本次请求 await redis.zadd(emailKey, now, ${now}-${Math.random()}); await redis.zadd(ipKey, now, ${now}-${Math.random()}); await redis.expire(emailKey, 120); await redis.expire(ipKey, 120); return { allowed: true }; }IP的限制阈值要比邮箱宽松一些因为同一个办公室或学校的用户可能共享出口IP。我设的是邮箱限制的5倍这个值可以根据实际情况调整。5.3 校验环节的尝试次数限制发送端限流了校验端也不能放松。如果不限制验证码的尝试次数攻击者可以在5分钟的有效期内暴力尝试所有6位数字组合。100万种组合如果每次尝试只要10毫秒理论上不到3小时就能穷举完。虽然实际中会有网络延迟但风险依然存在。我的做法是在Redis的Hash里记录attempts字段每次校验失败就加1超过5次就直接删除验证码强制用户重新获取。async function verifyCode(email, inputCode) { const key email:code:${email}; const data await redis.hgetall(key); if (!data || !data.code) { return { success: false, message: 验证码已过期请重新获取 }; } if (parseInt(data.attempts) 5) { await redis.del(key); return { success: false, message: 尝试次数过多请重新获取验证码 }; } if (data.code ! inputCode) { await redis.hincrby(key, attempts, 1); return { success: false, message: 验证码错误 }; } // 校验成功删除验证码防止重复使用 await redis.del(key); return { success: true, message: 验证成功 }; }注意最后一步校验成功后立刻删除验证码。这保证了验证码是一次性的即使被截获也无法重复使用。6. 把模块串起来Express路由与完整调用流程6.1 接口设计整个模块对外暴露两个接口POST /api/code/send接收邮箱地址生成并发送验证码POST /api/code/verify接收邮箱地址和验证码校验是否正确请求体都用JSON格式返回统一的{ code, message, data }结构。code用0表示成功非0表示各种错误。6.2 发送接口的完整逻辑app.post(/api/code/send, async (req, res) { const { email } req.body; const ip req.ip; // 1. 校验邮箱格式 if (!/^[^\s][^\s]\.[^\s]$/.test(email)) { return res.json({ code: 400, message: 邮箱格式不正确 }); } // 2. 频率限制检查 const rateCheck await checkRateLimit(email, ip); if (!rateCheck.allowed) { return res.json({ code: 429, message: rateCheck.reason }); } // 3. 生成验证码 const code generateCode(6); // 4. 存入Redis5分钟过期 const key email:code:${email}; await redis.hset(key, { code, attempts: 0, createdAt: Date.now() }); await redis.expire(key, 300); // 5. 发送邮件 try { await transporter.sendMail({ from: 验证码服务 ${process.env.QQ_EMAIL}, to: email, subject: 您的验证码, text: 您的验证码是${code}5分钟内有效。, html: ... }); return res.json({ code: 0, message: 验证码已发送请查收邮件 }); } catch (err) { // 发送失败删除已存的验证码 await redis.del(key); console.error(邮件发送失败:, err.message); return res.json({ code: 500, message: 邮件发送失败请稍后重试 }); } });这里有个细节发送失败时要删除已经存入Redis的验证码。否则用户没收到邮件但验证码已经占用了频率限制的名额用户要等一分钟才能重试体验很差。6.3 前端调用的注意事项前端调用这个接口时有几个容易忽略的点按钮要加防抖。用户可能连点多次虽然后端有频率限制但前端防抖能减少无效请求。倒计时提示。发送成功后显示60秒倒计时让用户知道什么时候可以重新发送。错误提示要具体。不要统一显示操作失败要把后端返回的message展示出来比如该邮箱请求过于频繁比发送失败有用得多。验证码输入框限制长度。设置maxlength6并且只允许输入数字减少用户输错的可能。7. 上线前必须检查的几个安全细节7.1 环境变量与密钥管理授权码、Redis密码这些敏感信息绝对不能出现在代码里。用dotenv加载.env文件.env加入.gitignore。部署到服务器时通过环境变量注入而不是把.env文件传上去。如果你用Docker可以用--env-file参数或者Docker Compose的environment字段。如果用云服务一般都有密钥管理服务比明文环境变量更安全。7.2 邮箱地址的规范化用户输入的邮箱地址可能有大小写差异比如UserQQ.com和userqq.com。如果不做规范化攻击者可以用大小写变体绕过频率限制。所以在存储和比较之前统一转成小写const normalizedEmail email.trim().toLowerCase();7.3 日志记录与监控每次发送和校验都要记日志包括时间、邮箱、IP、结果。但注意不要记录验证码本身日志泄露也是常见的安全事故。记录发送成功就够了不需要把验证码写进去。监控方面重点关注两个指标发送失败率和频率限制触发次数。失败率突然升高可能是SMTP配置出了问题频率限制触发次数异常升高可能是有人在攻击。7.4 验证码的有效期设置5分钟是个比较合理的值。太短用户来不及输入太长增加被暴力破解的风险。如果你的业务对安全性要求特别高可以缩短到3分钟如果是内部系统可以放宽到10分钟。另外验证码过期后要确保Redis里的数据被清理。用EXPIRE设置过期时间是最省事的做法Redis会自动清理。如果你用的是内存存储记得加定时清理逻辑否则内存会越用越多。8. 我踩过的几个印象深刻的坑第一个坑是授权码里的空格。从QQ邮箱复制授权码的时候有时候会带上首尾空格肉眼看不出来。结果SMTP连接一直报535错误我换了端口、换了加密方式、甚至怀疑是服务器IP被拉黑了最后用console.log(JSON.stringify(authCode))打印出来才发现多了个空格。所以现在我的代码里一定会加.trim()。第二个坑是连接池没设上限。早期版本我没配maxConnections默认是无限。结果有一次做压测瞬间建了几十个SMTP连接直接被QQ邮箱限流后面所有请求都失败了。加上maxConnections: 3之后就没再出过问题。第三个坑是验证码没删干净。有一次校验成功后忘记redis.del(key)导致同一个验证码在5分钟内可以重复使用。虽然概率很低但确实是个安全漏洞。后来我在代码里加了个约定任何校验成功的分支第一件事就是删除验证码。第四个坑是邮件进了垃圾箱。排查了很久最后发现是标题里带了免费两个字。改成您的验证码之后就正常进收件箱了。垃圾邮件过滤器的规则很复杂但核心原则是让你的邮件看起来像一封正常的业务通知而不是营销邮件。9. 后续可以扩展的方向这个模块目前只支持QQ邮箱发送但Nodemailer本身支持任何SMTP服务。如果你要支持多个邮箱服务商可以做一个配置映射根据发件邮箱的域名选择对应的SMTP配置。另一个方向是模板化邮件内容。现在验证码邮件的HTML是硬编码的如果以后要加欢迎邮件、通知邮件可以把模板抽出来用模板引擎渲染。这样改文案就不用动代码了。还有一个实用的扩展是发送记录查询。把每次发送的记录存到数据库提供一个查询接口方便排查用户说没收到邮件这类问题。记录里存邮箱、时间、发送状态就够了不要存验证码。最后如果你的项目用户量很大可以考虑把邮件发送做成异步队列。接口收到请求后先返回发送中实际发送交给后台worker处理。这样接口响应更快也能更好地控制发送速率。不过对于大多数中小项目来说同步发送完全够用没必要过度设计。

相关新闻

混酸投料计算器:硝化工艺中高精度密度-温度-浓度耦合计算工具

混酸投料计算器:硝化工艺中高精度密度-温度-浓度耦合计算工具

简介:混酸投料计算器是一款面向化学实验人员、化工工艺工程师及高校教学实践者的专业级配比计算工具,专为解决混酸配制中密度换算、体积-质量转换、含水量校验等关键问题而设计,适用于硝化反应、金属蚀刻、催化剂制备等需精确控制酸组分的实际…

2026/10/16 13:09:08 阅读更多 →
HDFS元数据管理深度解析:Fsimage与Edits机制、Checkpoint流程及运维调优实战

HDFS元数据管理深度解析:Fsimage与Edits机制、Checkpoint流程及运维调优实战

1. 从一个真实运维场景说起:NameNode启动为什么这么慢如果你管过Hadoop集群,大概率遇到过这样的场景:某天早上到工位,发现NameNode起不来了,日志停在“Loading fsimage”那一行,十分钟、二十分钟、半小时过…

2026/10/16 13:09:08 阅读更多 →
中小学AI教室怎么做?从硬件配置到课程设计的完整实践指南

中小学AI教室怎么做?从硬件配置到课程设计的完整实践指南

1. 先想明白:AI教室到底要解决什么问题1.1 很多学校把AI教室理解错了这几年中小学人工智能教育热得发烫,我陆续参与了好几个学校的AI教室项目,从需求调研到落地验收都走了一遍,最大的感触是:大部分学校一开始就把方向搞…

2026/10/16 13:09:08 阅读更多 →

最新新闻

Mosaico全景解读:面向Physical AI的机器人数据平台,5大核心能力让你告别.bag文件

Mosaico全景解读:面向Physical AI的机器人数据平台,5大核心能力让你告别.bag文件

【免费下载链接】mosaico Mosaico - The data platform for Physical AI 项目地址: https://gitcode.com/gh_mirrors/mosai/mosaico 点击查看 免费下载 Mosaico 是一款面向 Physical AI 与机器人场景的开源数据平台,能把 ROS .bag、.mcap 这类单体传感器…

2026/10/16 13:52:36 阅读更多 →
云溪天工开料优化软件实操指南:提升板材利用率与余料管理

云溪天工开料优化软件实操指南:提升板材利用率与余料管理

简介:面向板式家具加工与定制生产场景,这套云溪天工开料优化软件免锁版专为衣柜、橱柜、鞋柜、酒架等板材排版而设计,支持雕刻机、电子锯、数控钻、侧孔机等多种切割设备。软件核心优势集中在超强算法、锯缝处理、原片修边、成品公差、余料回…

2026/10/16 13:52:36 阅读更多 →
C++ Win32游戏开发实战:从零实现捕鱼达人核心机制

C++ Win32游戏开发实战:从零实现捕鱼达人核心机制

简介:这是一份基于Windows平台的C课程设计项目,主题为捕鱼达人小游戏,适合正在学习Windows编程或需要完成类似课程设计的高校学生参考。项目展示了如何利用Windows API创建窗口、处理消息循环与鼠标输入,并结合GDI绘图绘制背景、鱼…

2026/10/16 13:52:36 阅读更多 →
阿里云专有云CSB V3.7.1运维实战:进程端口日志四层定位法

阿里云专有云CSB V3.7.1运维实战:进程端口日志四层定位法

简介:本资源是阿里云专有云企业版V3.7.1中云服务总线(CSB)的官方运维指南PDF文档,面向专有云环境下的系统运维工程师、中间件管理员及企业级云平台维护人员,聚焦CSB服务的部署、配置、监控与故障排查等核心运维场景。文…

2026/10/16 13:52:36 阅读更多 →
MATLAB遗传算法ga函数参数调优实战指南

MATLAB遗传算法ga函数参数调优实战指南

简介:本资源是面向MATLAB初学者与优化算法实践者的遗传算法工具箱实战包,聚焦非线性、多目标及复杂约束下的工程优化问题求解,特别适配MATLAB 2017a环境。压缩包含65个文件(214KB),主体为60个.m函数文件&am…

2026/10/16 13:52:36 阅读更多 →
C#.NET整合微信支付宝银联支付:回调验签与统一网关实践

C#.NET整合微信支付宝银联支付:回调验签与统一网关实践

简介:面向C# .NET开发人员的多支付渠道整合方案,聚焦微信、支付宝与银联支付在统一业务后台中的接入与协同。内容覆盖微信JSAPI、Native、H5、APP,支付宝网页支付、APP支付、扫码支付,以及银联网上支付、快捷支付等典型场景&#…

2026/10/16 13:51:34 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →