基于WebSocket的事件驱动实时应用原型设计与实现
1. 项目概述与核心需求拆解1.1 rea 到底是什么rea 这个代号乍一看有点神秘三个字母没有任何上下文。我第一次看到这个项目名的时候第一反应这是一个内部实验项目的缩写。后来我在实际梳理思路时把 rea 解读为 Real-time Event Application也就是实时事件驱动应用。这样一解释整个项目的方向感就出来了它要做的不是又一个普通的增删改查后台而是一条从事件产生到事件分发再到前端响应的完整实时链路。很多人可能觉得实时应用离自己很远觉得只有做在线协作、做直播弹幕、做股票行情的人才用得着。其实不是这样。哪怕你做的是一个简单的任务管理系统如果希望一个成员新建任务之后其他成员的页面不用手动刷新就能自动出现这条任务这就已经进入了实时应用的范畴。rea 的目标正是把这类需求做成一个轻量、可复用、又足够有解释深度的原型系统。这个项目适合谁来参考我个人的建议是对实时通信原理有一定好奇心的前后端开发者尤其是那些已经写过常规 CRUD 接口但还没有完整接触过长连接、事件广播、消息协议这些概念的开发者。你不需要有很高的并发经验只需要会写基本的数据接口能理解简单的异步逻辑就可以跟着这条链路走一遍把实时应用的骨架搭起来。1.2 需求拆解实时系统要解决的三类问题在正式动手之前我习惯先把需求拆成三个层面去理解——数据层、通信层、表现层。这三个层面分别对应实时系统最核心的三个问题。数据层的核心问题是事件从哪里来怎么描述在 rea 里我定义为用户在某个时间点触发了某个动作比如新建任务、修改状态、发送一条消息。这个动作必须被抽象成一条结构化的事件而不是简单地在数据库里写一行记录。因为只有事件化后面的通信和分发才有依据。通信层要解决的是事件怎么送达。传统的 HTTP 请求是客户端主动拉取但实时场景需要服务端主动推送。这两种模型的差异决定了你必须换一套通信机制。表现层则关心前端怎么响应。事件到了浏览器端不能只是 console.log 一下要正确更新界面状态还要考虑多个事件同时到达时的合并、去重、顺序等问题。把这几个问题想清楚之后rea 的轮廓就很清晰了它本质上是一个小型的实时事件总线系统服务端负责任何事件的接收与广播客户端负责事件的订阅与渲染中间用一条全双工的通信通道连接。注意不要一开始就想着搞分布式、搞消息队列集群那是后面的事情。先做单机、单通道的完整闭环把链路跑通比什么都重要。2. 整体设计与技术选型解析2.1 为什么选事件驱动架构而不是轮询在设计 rea 的通信方案之前我专门对比了两种主流思路短轮询和长连接。短轮询的思路很简单前端每隔几秒发一个请求问服务端有没有新数据服务端查一下有新数据就返回没新数据就返回空。这种方案实现成本极低而且和后端常规接口完全兼容。但它的短板也很明显第一实时性差。就算你做到每 5 秒轮询一次理论上最差情况也有 5 秒的延迟。第二浪费资源。绝大多数轮询请求都是空手而归但每一次都会产生完整的 HTTP 请求头、服务端处理逻辑、数据库查询这些全是无意义的开销。第三随着前端页面数量增多服务端承受的无效请求量会线性上涨到后期往往需要专门为轮询扩容性价比很低。事件驱动架构则换了一种思路事件不是由客户端反复问出来的而是服务端在事件发生的瞬间主动推给所有关心它的客户端。这就像你去餐厅吃饭不需要每隔一分钟就跑去问服务员菜好了没有而是服务员做好菜之后会直接端到你桌上。前者是轮询后者是事件驱动。rea 要做的就是后者虽然它比轮询复杂但它把实时性从秒级提升到了毫秒级而且大幅减少了无效通信。2.2 通信载体选择WebSocket 为什么比普通 HTTP 合适确定了要用事件驱动架构之后接下来要选通信载体。主流的方案有几个WebSocket、SSEServer-Sent Events、WebRTC DataChannel。在 rea 这个项目里我最终选了 WebSocket。理由有三条。第一WebSocket 提供的是全双工通信也就是说客户端可以向服务端发消息服务端也可以主动向客户端发消息这两条通道是同时并且独立的。而 SSE 是单工的只支持服务端往客户端推如果客户端需要上报事件还得额外走一条 HTTP 通道。第二条通道会带来连接管理和消息时序上的额外复杂度。第二WebSocket 的浏览器兼容性和生态成熟度都非常高几乎所有现代主流浏览器都原生支持不需要引入额外的解析库而且服务端的实现方案也非常丰富无论你用什么编程语言都能找到稳定可靠的实现。第三WebSocket 的握手基于 HTTP 升级协议这意味着它可以天然复用现有的 HTTP 端口、鉴权体系和反向代理配置。在部署的时候不需要为它单独开一个奇怪的端口运维同学也不会为此头疼。当然 WebSocket 也不是没有问题它比 HTTP 请求更难调试连接状态的维护也需要额外的代码处理。但权衡下来它是 rea 当前阶段最合适的选择。2.3 服务端与前端的分工边界这里我想特别强调一下职责划分。在很多实时应用项目里一个常见的错误是服务端代码过于操心把业务逻辑、连接管理、消息序列化全部揉在一起前端则过于被动只负责把收到的消息直接渲染。rea 的分工设计是服务端只负责三件事——接收事件、校验事件格式、按主题广播事件。它不关心事件内容具体业务含义也不关心前端拿到事件之后要怎么展示。前端则负责两件事——订阅自己感兴趣的主题、把收到的事件转成界面状态。它不关心事件是从哪个客户端发出来的也不关心服务端内部是怎么分发消息的。这样的边界设定带来了两个明显的好处一是服务端的代码可以高度复用以后接任何新业务场景只要定义好事件结构就可以对接二是前端逻辑更可控所有的界面变化都来自清晰的事件源排查问题的时候只要沿着事件是否到达、事件是否被消费、界面是否正确渲染这条链查下去就行。3. 核心功能实现与实操过程3.1 服务端事件通道搭建我选择用一个基于事件循环的服务端运行时来承载 rea 的服务端核心因为它处理高并发 I/O 的能力非常适合长连接场景。第一版我选择开门见山直接利用内置的 WebSocket 能力先不引入额外的框架这样做的好处是能看清底层机制。服务端的核心代码大致是这样的思路import { WebSocketServer } from ws const wss new WebSocketServer({ port: 8080 }) // topic - SetWebSocket维护每个主题下订阅的连接集合 const subscriptions new Map() function subscribe(ws, topic) { if (!subscriptions.has(topic)) { subscriptions.set(topic, new Set()) } subscriptions.get(topic).add(ws) } function unsubscribe(ws, topic) { const conns subscriptions.get(topic) if (conns) { conns.delete(ws) } } wss.on(connection, (ws) { ws.on(message, (raw) { const msg JSON.parse(raw.toString()) if (msg.type subscribe) { subscribe(ws, msg.topic) } else if (msg.type publish) { const topic msg.topic const event msg.event // 广播给这个主题下的所有其他连接 const conns subscriptions.get(topic) if (!conns) return const payload JSON.stringify({ topic, event }) for (const conn of conns) { if (conn ! ws conn.readyState 1) { conn.send(payload) } } } }) ws.on(close, () { // 连接关闭时清除它订阅的所有主题 for (const conns of subscriptions.values()) { conns.delete(ws) } }) })这段代码很短但它把实时分发最重要的机制都包含了按主题维护订阅关系、收到发布消息后向订阅集合广播、连接关闭时清理订阅关系。注意我在广播时加了conn ! ws的判断也就是默认不把事件回发给发送者本人。这样的设计是故意的因为发送者自己已经知道自己的操作结果没必要再收到一次回声。如果某些业务场景需要所有人包括发送者都收到只需去掉这个判断即可。3.2 客户端的订阅与实时渲染前端的核心逻辑是在页面加载后主动建立连接然后发送订阅消息再监听事件推送。我用一个简单的状态管理器来承接事件流让它驱动界面更新。const socket new WebSocket(ws://localhost:8080) const state { tasks: [] } socket.addEventListener(open, () { socket.send(JSON.stringify({ type: subscribe, topic: tasks })) }) socket.addEventListener(message, (event) { const { topic, event: evt } JSON.parse(event.data) if (topic tasks) { handleTaskEvent(evt) } }) function handleTaskEvent(evt) { switch (evt.action) { case create: state.tasks.push(evt.data) break case update: state.tasks state.tasks.map(t t.id evt.data.id ? evt.data : t ) break case delete: state.tasks state.tasks.filter(t t.id ! evt.data.id) break } render() }这里我想特别提醒一件事前端绝对不要直接拿event.data里的内容替换整个列表。如果你这样做可能会出现竞态问题因为事件的到达顺序不一定和实际业务顺序一致。正确的方式是基于本地已有的状态做增量更新通过action字段标明是新增、修改还是删除。这样即使某条事件晚到了几毫秒前端依然能正确合并数据不会出现内容闪烁或者数据丢失。3.3 消息协议设计与关键参数计算在 rea 里我约定了一条统一的 WebSocket 消息结构。不论客户端发出的指令还是服务端下发的事件都遵循同一个 JSON 外壳{ type: subscribe | publish | response, topic: 字符串表示主题名称, event: { action: create | update | delete, data: {} }, ts: 1721234567890 }这里每个字段都有它存在的意义。type用来区分这条消息是订阅指令、发布指令还是应答topic决定了消息的路由归属event.action让前端不用自己猜测如何合并数据ts是毫秒级时间戳用来做消息排重和排查顺序问题。心跳参数也是需要认真计算的。我在服务端设定了一个 60 秒的心跳阈值也就是如果超过 60 秒没有收到客户端业务消息服务端发送一个ping帧如果连续两次ping都没有得到pong响应就认定连接已经失效主动清理连接句柄。客户端的逻辑是每 30 秒主动上报一个心跳消息保证服务端能及时发现半开连接。提示心跳间隔不要设得太短也不要设得太长。太短会产生大量无意义的心跳帧太长则会让异常连接的清理变得迟钝。以 30 秒客户端心跳、60 秒服务端检测阈值为例最坏情况下能在 90 秒内检测出死连接这对大多数内部工具类的实时应用来说都是可以接受的。3.4 一个完整的运行链路复盘为了让理解更具体我复盘一个创建任务的操作在 rea 里完整走了一遍的过程。某个客户端在界面上输入任务名称编写项目文档点击提交按钮。前端先把这条操作封装成一条事件action为createdata里包含任务名称和待办状态。然后它通过 WebSocket 发送type: publish的指令。服务端收到后解析出topic为tasks在自己的订阅表里找到所有订阅了tasks主题的客户端连接把这条事件序列化后逐一发送出去。发送耗时取决于订阅数量和数据体积在本项目中测试时10 个客户端同时在线单条事件从服务端发出到所有客户端收到的平均耗时大约在 10 到 20 毫秒这里面还包含了网络传输时间。其他客户端收到事件后查看到topic是tasks进入任务事件处理函数识别到action为create把事件里的任务对象追加到本地状态数组然后调用render()更新界面。这时候所有订阅了任务的页面都能看到新任务整个过程不需要刷新页面也没有轮询请求。我实际跑通整个过程后最大的感受是实时应用并没有想象中那么神秘。它的核心链路就是事件上送—服务端分发—前端消费任何环节都可以单独调试和追踪。而一旦你把链路打通了后续扩展新功能会非常顺手比如在线人数统计、操作日志回放全部可以复用这一条通道。4. 常见问题与排查技巧实录4.1 连接不稳定与断线重连设计做实时应用第一道坎往往是断线重连。rea 早期测试时我把页面挂着不动一个晚上第二天早晨回来发现页面已经死了界面上的任何操作都没有反应打开控制台才发现 WebSocket 状态还是CONNECTING但实际上服务端已经把这个连接清理掉了。这类半开连接half-open connection是 TCP 长连接里非常经典的坑。解决办法是引入重连机制并且要带指数退避。我最终实现的方式是当检测到连接关闭或心跳超时前端先等 1 秒重连如果再失败等待时间翻倍最多拉到 30 秒封顶。同时每次重连成功后要重新发送订阅主题因为服务端在连接断开时已经把它从订阅表里移除。let retryDelay 1000 const MAX_RETRY_DELAY 30000 function connect() { const socket new WebSocket(ws://localhost:8080) socket.addEventListener(open, () { retryDelay 1000 socket.send(JSON.stringify({ type: subscribe, topic: tasks })) }) socket.addEventListener(close, () { setTimeout(connect, retryDelay) retryDelay Math.min(retryDelay * 2, MAX_RETRY_DELAY) }) }这里最容易被忽视的一点是打开事件和重连事件不能只写一次。很多初版代码只在页面初次加载时建立一次连接之后再也不管了。断线重连必须自包含在connect()函数内部让每一次重连都是完整的新连接流程。4.2 消息乱序与幂等处理有一次测试的时候我连续快速创建三条任务结果有一个客户端的列表顺序和发送端不一致。排查之后发现原因是网络传输和事件循环调度的不确定性三条消息并不保证按照发送顺序到达所有客户端。这个问题比想象中要紧。如果是纯展示性数据顺序乱了问题不大但如果涉及状态覆盖比如一个更新事件比它对应的创建事件先到达那么前端会因为找不到对应的数据 ID 而放弃这次更新造成数据丢失。解决办法是在前端加入幂等机制。每个事件在data里带一个clientMsgId前端维护一个最近处理过的 ID 集合重复的clientMsgId直接丢弃。而对于更新先于创建到达这种情况可以在接收端做一个轻量缓存先暂存更新事件等创建事件到达后再合并处理。我在 rea 里为了控制复杂度最终采用了一个折中方案前端本地先维护待处理的更新事件队列每收到一条数据就尝试按 ID 合并合并不上的放入待处理队列每隔 200 毫秒重试一次。这个方案实测解决了绝大多数乱序场景而且代码量不大值得直接抄作业。4.3 性能瓶颈与内存释放隐患实时应用跑久了之后服务端最容易出现的问题是内存缓慢上涨。我在压测 rea 的时候发现持续运行几个小时后进程的内存占用比初始状态多了将近 30%。逐步排查找到了两个元凶。第一个元凶是订阅表里的Set没有正确清理。有客户端断线时如果close事件的回调里没有把连接从所有主题集合中移除这个连接对象就会一直留在内存里而且它本身还引用着已经失效的 socket 对象垃圾回收器无法回收它们。第二个元凶是发送失败的积累。某些客户端可能在弱网环境下已经收不到消息但服务端的send操作不断缓存数据导致内存逐渐膨胀。针对这两个问题我的建议是连接关闭的清理逻辑必须做到原子化不论连接以什么方式结束都要触发同一套清理函数而发送失败、缓存堆积的场景应当在检测到连续发送失败时主动关闭这条连接把主动权收回服务端。不要指望前端一定会自己断开很多时候它可能已经掉到网络黑洞里了。4.4 常见问题速查表问题现象原因解决方法页面偶尔收不到事件订阅消息还没发出去服务端已经开始广播事件在open事件回调里完成连接后立即发送订阅消息避免外部手动调用服务端内存持续上涨断开的连接没有从订阅表清理统一封装close清理逻辑移除所有主题集合中的连接引用重连后无法收到新事件前端只重连了 WebSocket没有重新订阅主题重连成功的回调里必须重新发送订阅指令前端列表顺序错乱消息到达顺序与业务顺序不一致引入clientMsgId排重配合待处理队列做乱序合并服务器日志反复报错导致性能下降没有对发送失败做限制为send调用增加 try/catch连续失败超过 3 次则主动断开连接4.5 调试实时应用的两个独家技巧最后分享两个我在排查 rea 问题时觉得最顺手的小工具和方法。第一个是利用浏览器的网络面板里的 WS 标签。它不仅能实时查看每一条 WebSocket 帧的内容还能看到连接建立时的握手详情、心跳帧的收发时间以及连接关闭的状态码。排查连接问题时我最常干的一件事就是开着这个面板然后手动刷新页面观察close事件是在哪个阶段触发的。第二个技巧是自己做一个极简的消息可视化面板。在服务端加一个 debug 模式把每一条收到和发出的消息都打印到控制台的同时额外推送到一个专门的debug.events主题。开发的时候前端用一个单独的调试页面订阅这个主题把所有消息按照时间顺序显示成一个流水列表。这样当你怀疑某个事件消失了的时候直接看这个调试页就能判断问题出在上游还是下游不用再去翻服务端日志了。5. 从 rea 出发还能往哪走把整个原型跑通之后你会发现 rea 背后这套事件驱动 长连接分发的组合并不只是解决实时刷新这一件事的工具它更像是一块基础的地基。顺着这个地基往下走可以延展的方向非常多。比如可以给事件通道加一层持久化。当事件从服务端广播经过时同时写入一个事件存储这样新客户端上线之后可以先拉取历史事件进行回放恢复出客户端当前应有的状态然后再接入实时流。这在在线协作、状态同步、操作审计这些场景里极其有用。更轻量一点的做法是在内存里只保存最近 100 条事件做一个简单的最近活跃记录功能。比如可以给订阅机制增加模式匹配。目前 rea 的订阅是一个客户端只能订阅固定主题如果要做一个多人协作的看板系统每个用户可能需要同时订阅看板 A 的任务、看板 A 的成员、通知频道等多个主题。你可以把这些主题用一个星号通配符组织成层级让订阅和分发都更灵活。甚至可以接入一个简单的权限校验。因为 WebSocket 握手时本质上还是 HTTP 请求你可以在握手阶段读取请求自带的 Cookie 或其他凭证信息在订阅主题之前先判定这个用户有没有权限订阅这些内容。这一步做完实时应用的安全性就会上升一个台阶真正具备接入生产环境的底子。最后再提一个个人体会做 rea 这类原型项目最大的收获不是代码本身而是养成了一种事件化的思维习惯。以前我处理业务逻辑时天然会按照请求-响应的模式思考但当你开始设计实时系统你的脑子里会自然地冒出这些问题这个操作会产生什么样的事件哪些模块关心这个事件事件的顺序和重复有没有风险消费者拿到事件后如何更新自己的状态这种思维模式对任何复杂前端应用、协作工具、甚至游戏同步都有帮助。感兴趣的话你不妨用三个字母命名一个新原型从一条最简单的事件链路开始试着把它跑起来。

相关新闻

智能体技能池如何定期复查与安全替换?SkillRover机制解析

智能体技能池如何定期复查与安全替换?SkillRover机制解析

1. 为什么智能体需要一个“技能复查”机制 1.1 从一个真实踩坑场景说起 去年我在做一个多智能体协作的自动化流程项目时,遇到过一个非常典型的问题:一个负责数据清洗的智能体,在连续运行了大概两周之后,突然开始频繁调用一个早就…

2026/10/14 9:57:44 阅读更多 →
不懂代码也能搭AI降本系统:表单+自动化+提示词实战指南

不懂代码也能搭AI降本系统:表单+自动化+提示词实战指南

“系统”这个词,对很多非技术人员来说几乎是“禁忌”。一想到要搭个系统,就觉得得写代码、看文档、搞数据库,还得维护服务器,光想想就头大。但我做了很多次轻量自动化的落地尝试后发现,现在的情况已经完全不同了&#…

2026/10/14 9:56:41 阅读更多 →
不懂代码也能搭AI降本系统?个人高效工作流实战指南

不懂代码也能搭AI降本系统?个人高效工作流实战指南

不懂代码,怎么用AI给自己搭个降本系统?我先把话说在前面:这个题目不是我拍脑袋想出来的,是我自己真实折腾了两个多月才摸透的玩法。我之前也是个纯小白,连Excel的VBA都没碰过,Python更是只会在网上复制粘贴…

2026/10/14 9:56:41 阅读更多 →

最新新闻

华为BFD双向转发检测实战:毫秒级故障检测与调优排错指南

华为BFD双向转发检测实战:毫秒级故障检测与调优排错指南

1. 从一个“链路假死”的经典故障说起如果你做过企业级网络运维,大概率遇到过这种让人后背发凉的情况:核心交换机和上行路由器之间的物理链路指示灯一切正常,端口状态是 UP,光模块收发光功率也在正常范围内,但业务流量…

2026/10/14 23:17:13 阅读更多 →
AI聊天内容一键变正式文档:AI导出鸭完整使用指南

AI聊天内容一键变正式文档:AI导出鸭完整使用指南

每次让AI帮忙写方案、列大纲、整周报,聊天框里看着都挺满意,逻辑清楚、条理分明。可一旦到了交付环节,麻烦就冒出来了:复制到Word里格式全乱,代码块缩进没了,表格挤成一团,甚至AI自己生成的Mark…

2026/10/14 23:17:13 阅读更多 →
SpringBoot+PostGIS构建千里巡检线:空间数据建模与查询实战

SpringBoot+PostGIS构建千里巡检线:空间数据建模与查询实战

第一次在项目原型里看到整条巡检线路铺满地图的时候,我确实被这个项目的工作量震了一下。单条线路分支加主路,横跨一千多公里,穿越好几个生态和地形差异明显的区域,原来零散在各张表里的坐标点,到这里必须变成连续、可…

2026/10/14 23:17:13 阅读更多 →
汇编实验五深度解析:段寄存器与多段程序实战

汇编实验五深度解析:段寄存器与多段程序实战

1. 实验五到底在练什么:先搞懂它的设计意图很多人翻到《汇编语言》王爽这本书的实验五,第一反应是“怎么突然让我写这么多段代码”,第二反应是“这些段和段之间到底什么关系”。我带过不少刚学汇编的朋友,几乎所有人卡在实验五都不…

2026/10/14 23:17:13 阅读更多 →
Python+Django+Vue视频点播系统开发实战:从架构到部署避坑

Python+Django+Vue视频点播系统开发实战:从架构到部署避坑

简介:基于 Python 语言,结合 Django 框架与 Vue.js 前端技术,构建了一套完整的视频点播网站毕业设计项目。系统围绕用户认证、视频分类、在线播放与管理等核心功能展开,涵盖后端逻辑、前端展示、数据库管理和媒体资源存储等关键环…

2026/10/14 23:17:13 阅读更多 →
AI逆向工程实战:31.2K Star开源项目如何用大模型辅助二进制分析

AI逆向工程实战:31.2K Star开源项目如何用大模型辅助二进制分析

1. 当AI把目光投向二进制:逆向工程的门槛正在被重新定义第一次看到“AI开始搞逆向工程”这个说法,我的反应是:终于有人把这件事摆到台面上了。逆向工程这个领域,长期以来都是少数人的游戏——你得懂汇编,得熟悉PE/ELF文…

2026/10/14 23:16:08 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/13 22:01:27 阅读更多 →
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/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练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/14 7:53:34 阅读更多 →