Airflow实战:如何用DAG理顺复杂数据任务编排

长期做数据开发的人一定都有这种感觉:任务多了以后,整个数据链路就像一团越缠越紧的毛线。今天我要聊的 Airflow,正是我在解决任务编排混乱问题时找到的答案。它不是一个跑批脚本的替代品,而是一套真正让你把任务之间的依赖关系、执行顺序、失败处理都摆到台面上管理的方法论。如果你负责的数据任务开始超过两位数,或者每天半夜还在被业务方追问“报表为什么没出来”,这篇文章值得你花十分钟看完。

一开始我接手某个数据调度平台时,生产环境里跑着上百个 Python 脚本和 Shell 脚本,靠 cron 驱动。表面上看起来每个任务都能按时启动,但只要某个环节的数据源延迟,或者上游脚本意外退出,整条链路就会像多米诺骨牌一样连环迟到。你在凌晨两点被叫起来,打开服务器一个个查日志,从几十个脚本里定位到底是哪一步卡住了,那种体验我相信经历过的人都懂。

Airflow 解决的就是这个问题。它用一个有向无环图(DAG)把任务的依赖、顺序、重试策略全部表达出来,你可以在 Web UI 上直观看到整个数据管线的当前状态。更重要的是,它的调度模型把“什么时候该跑”和“任务该做什么”彻底分开了,这让任务编排的清晰度提升了一个量级。这篇文章我会从为什么容易乱、DAG 的核心机制、实战中的拆分技巧、调度时间陷阱、以及线上排查链路这五个角度,完整地讲一遍我自己从踩坑到理顺的过程。

1. 任务编排为什么会乱成“一锅粥”:先搞清楚问题根源

很多人一上来就急着写 DAG,但如果不先理解编排混乱的根源,就算换工具,过几个月一样会变成新的“屎山”。我见过不少团队从 crontab 迁到 Airflow 之后,DAG 写得比脚本还难维护,根本原因就是没有想清楚“任务”和“编排”之间的界限。

1.1 手写脚本加 cron 的方式在什么时候会失控

用 cron 写定时任务本身没有错,很多轻量场景完全够用。问题出在任务之间的依赖关系只能靠“时间猜测”来隐式保证。比如任务 B 必须在任务 A 完成后才开始,你就在 cron 里把 B 的开始时间设在 A 预计结束时间之后半小时。刚开始可能没问题,但随着数据量增长,A 的运行时长从 20 分钟变成了 1 小时,B 依然在预定的时间启动,读到的就是上一轮甚至不完整的数据。

更麻烦的是失败处理。cron 场景下脚本挂掉之后,你通常只能靠脚本自己写 try-except 然后发邮件。没有统一的重试机制,没有任务级别的状态记录,没有历史运行趋势。你要判断今天仓库里某张表的数据对不对,只能手工去服务器上看今天的日志文件。这种靠人肉盯的方式,在任务数量少的时候还凑合,一旦上了规模,任何一次调整都可能引发连锁反应。

1.2 团队协作中的“隐形知识”是混乱的放大器

编排混乱还有一个很隐蔽的原因:关键的执行顺序、参数配置、失败处理策略,经常只存在于某个老同事的脑子里。我见过一个团队,某张核心宽表的产出流程,依赖一个只在特定目录下存在的配置文件,而这份配置是三年前某个人临时添加的,代码仓库里根本找不到说明。新同事接手以后根本不敢动,哪怕只是改一个超时时间,都怕踩到雷。

Airflow 真正带来的改变,不只是把计划调度可视化,而是强制你把这些“隐形知识”写成了声明式的代码。什么任务在什么条件下执行、失败之后怎么重试、重试几次、每次间隔多久、超时多长时间算失败,这些全部变成 DAG 文件里的显式配置。任何一个人打开 dag 文件,就能完整地理解这条数据链路的全部规则。

1.3 “清晰”到底意味着什么:三个可衡量的标准

我认为一个编排系统算不算“清晰”,应该用三个标准去衡量。第一是“可预测”,任何一个任务,你都能准确说出它今天什么时候跑、依赖哪些任务、在什么条件下会失败;第二是“可排查”,任务出问题后,你在五分钟之内能定位到具体是哪个环节、哪条日志、哪条数据出了问题;第三是“可演进”,新增任务、修改依赖、调整调度频率,不需要小心翼翼地排查所有下游影响,改完 DAG 提交,系统自动帮你处理。

这三个标准,传统 cron 方式很难同时满足。而 Airflow 的 DAG 结构、任务实例状态记录、依赖上下文分析,恰好就是在往这三个方向靠。这也是我为什么坚持认为,Airflow 的核心价值不是“调度”,而是“编排的确定性”。

2. DAG 才是 Airflow 的灵魂:一套机制讲透任务依赖的表达方式

Airflow 里的核心概念就一个:DAG。它把不同任务组织成一张有向无环图,每个节点是一个任务,每条边代表依赖关系。这一点我认为比任何花哨功能都重要,因为“依赖”是所有编排问题的根本,“环”则是死锁的代名词。理解了这一层,后面的所有配置都是锦上添花。

2.1 用代码声明依赖,而不是靠时间线硬凑

先看一个最小可用的 DAG 示例:

from datetime import datetime, timedelta from airflow import DAG from airflow.operators.bash import BashOperator default_args = { "owner": "data_team", "retries": 3, "retry_delay": timedelta(minutes=5), "start_date": datetime(2023, 1, 1), } with DAG( dag_id="etl_order_flow", default_args=default_args, schedule_interval="@daily", catchup=False, ) as dag: extract = BashOperator( task_id="extract_from_source", bash_command="python /data/scripts/extract.py", ) clean = BashOperator( task_id="clean_raw_data", bash_command="python /data/scripts/clean.py", ) load = BashOperator( task_id="load_to_warehouse", bash_command="python /data/scripts/load.py", ) extract >> clean >> load

最后一行extract >> clean >> load是整个编排“清晰”的关键。它表达的意思是:三个任务按顺序执行,clean 永远不可能先于 extract 运行,load 永远不可能在 clean 成功之前触发。这种依赖是系统强制的,不靠任何人肉约定,也不靠时间硬凑。只要有任意一个上游任务失败,下游就自动停止等待,除非你显式配置了触发规则。

很多刚接触的人会问:这不就相当于把多个命令写进一个 Shell 脚本然后加&&连接吗?区别非常大。Shell 脚本里的&&确实能保证顺序,但整个脚本是一个不可分割的单元,你无法观察中间每一步的状态,也更难做到“一步失败只重试这一步”。DAG 的粒度是任务级的,某个失败之后,系统知道失败节点是 clean,你可以在 UI 中只重跑 clean,而不是把整个脚本重新执行一遍。

2.2 任务状态机和依赖触发逻辑:从细节处保证可控

每个任务实例在 Airflow 里有明确的生命周期,包括 queued、running、success、failed、upstream_failed、skipped 等状态。依赖触发逻辑说白了就是:当所有直接上游任务达到 success 状态,且满足触发规则时,当前任务进入 scheduled,随后由调度器分配到 worker 执行。

这里有一个值得注意的细节:默认情况下,只要上游任务失败,下游任务会直接进入 upstream_failed 状态,而不会执行。这意味着失败会沿着依赖链向下传导。但有的场景我们并不希望这种传导发生,比如某个监控任务失败了,并不需要阻断下游报表。这时候就需要手动调整触发策略。

Airflow 中的trigger_rule参数有 all_success、all_done、one_success、one_failed、none_failed、none_skipped 等多个选项,默认是 all_success。我个人的经验法则是:数据加工类任务保持默认的 all_success 就行,越严越好;只有消息通知、日志归档这类非核心任务,才考虑使用 all_done 或 one_success。不要随意放宽触发规则,否则失败会被悄悄吞掉,反而破坏了整套编排的观测性。

2.3 重试、超时和并发:保证链路不因偶发问题中断

清晰编排除了关心任务是否执行,还要关心任务执行过程中如果出现偶发问题,系统如何自愈。Airflow 的 Default Args 里可以配置 retries 和 retry_delay,比如上面例子里的失败重试 3 次、间隔 5 分钟。这里的逻辑是:不是所有失败都值得立刻报警,网络抖动、临时资源不足这些情况,重试几次就能恢复。重试次数耗尽之后才进入 failed 状态,这时候才通知到人。

另一个容易被忽视的点是超时。如果一个任务因为外部数据量暴增而卡住,可能运行两小时还没有结束。如果不设置execution_timeout,调度器永远不会主动杀掉它,后面的依赖任务就一直等待,整个 DAG 的调度节奏就崩溃了。所以我的习惯是:每个任务都设置合理的执行超时,宁可超时误杀,也绝不让一个失控任务拖住整个链路。保守估计一个任务正常执行 30 分钟,超时上限就设置为 60 分钟,给足余量的同时保留止损能力。

并发控制也属于“清晰”的一部分。如果不限制同一 DAG 内可并行运行的任务数量,或者不限制整个 Airflow 集群的 worker 数量,高峰期可能会把所有 worker 跑满,普通任务全在排队。给 DAG 设置max_active_runs=1,可以避免同一个 DAG 的不同调度周期任务互相抢占资源。尤其是那些计算密集型的任务,这一步非常关键。

3. 让 DAG 可读、可维护的实战技巧:从小处着手分出层次

我见过不少人把整个数据链路几十个任务写进同一个 DAG,图上密密麻麻交织成一张蜘蛛网,这比 cron 更可怕。Airflow 给你强依赖表达力,不等于你应该把所有依赖都摊在一张图上。真正清晰的做法是:把复杂的处理流程拆解成若干子流程,再用分层结构把子流程组织起来。

3.1 追求单一职责:一个任务只做一件小事

任务拆分的经验法则是:如果一个任务的任务名需要用逗号连接多个动作,那它就应该被拆开。比如“检查并同步最新库存快照”,可以拆成“检查上游文件就绪”和“同步库存快照到数仓”两个任务。拆完之后,依赖关系更明确,失败定位也更精准,而且单个任务的可重试性大幅提升。

拆分红利在排障时体现得最明显。某天数仓里的用户行为表没更新,你打开 DAG 图一看,停留在“检查上游文件就绪”节点,那问题就在外部数据源,根本不用看后面的任务。如果当初你把检查文件、落临时表、做清洗、合并分区全塞进一个大 PythonOperator,那排查链路就长得多。

3.2 TaskGroup 的使用:让复杂依赖图从视觉上可读

Airflow 从 2.0 开始提供 TaskGroup 机制,可以把多个任务包装成一个逻辑分组。比如一个“每日用户活跃报表”流程,内部可能包含 6 个任务,但对外它只是整条链路里的一个环节。用 TaskGroup 包裹后,Web UI 默认折叠显示为一个大节点,让整体依赖图变得干净清晰。

我自己的习惯是,一层 DAG 里的 TaskGroup 不超过 5 个,每个 TaskGroup 内部的子任务不超过 10 个。超过这个规模,就算有分组,单张图看起来也会吃力。遇到特别庞大的流程,优先考虑拆成多个 DAG,而不是在一个 DAG 里塞满内容。

3.3 参数传递与 XCom:少传大对象,多传引用

任务之间经常需要传递数据,比如某个任务计算出一个结果,下游要基于这个结果做判断。Airflow 提供了 XCom 机制,可以实现跨任务的数据共享。但我必须提醒一句: XCom 适合传小数据量,比如状态标记、文件路径、任务产出对象的 ID,绝对不应该用来传 DataFrame 或大 JSON。

在实践中有两种主流方案处理大参数:要么把中间结果写入外部存储,然后在 XCom 里传存储路径;要么利用变量机制把静态配置放进去,动态数据走存储系统。我倾向于前者,因为路径本身很小,而且下游拿到路径后再独立读取,这个过程的数据血缘也更清晰,方便排查。另外,设置do_xcom_push=False可以避免大返回值被自动存入 XCom,减少数据库压力。

任务命名的规范性也不可忽视。我见过task_1、task_2这种名字,虽然能跑,但每次排查都要点进去看代码。好的任务命名应该让人一眼看出它在链路里的角色,比如wait_for_source_file、merge_partition_daily、send_report_wechat,配合 TaskGroup 名称,连文档都可以少写一半。

4. 调度时间与历史数据:最容易踩坑的两个关键点

Airflow 的调度模型有一个极其重要的反直觉设计:一个 DAG 实例的运行时间,并不是在schedule_interval指定的时刻“触发”的。准确地说,它是在该时刻之后被调度创建的。这个细节如果不理解,你会遇到大量“任务为什么没跑”的困惑。

4.1 schedule_interval 背后的时间语义陷阱

Airflow 判断 DAG 是否需要产生新实例,依据的是execution_date(更准确说应该是data_interval_start和data_interval_end)。比如schedule_interval=@daily,意味着每天 00:00 开启一个新的数据周期,但这个 DAG 实例真正开始执行往往是在 00:00 之后几分钟,比如 00:05。数据周期代表的是“处理哪一段时间的数据”,而实际跑批则有一个自然的延迟。

很多刚迁移过来的同事容易搞混,以为schedule_interval="@daily"就是每天零点整执行。其实零点整开启了一个新周期,调度器检测到新的数据周期后才会排期,再经过调度器和 worker 的分配,真正运行时间通常会有几秒到几分钟的延时。如果你的业务对时间精度要求很高,比如必须整点触发某条线上告警推送,Airflow 并不是最合适的工具,你需要去了解更底层的调度方案,或者另写专门的定时触发系统。

4.2 catchup 和 backfill:处理历史数据时的高危操作

如果 DAG 定义中的start_date早于当前时间,且catchup=True,Airflow 会为缺失的每一个周期都补建 DAG 实例。假设一个 DAG 从 2023 年 1 月 1 日开始,每天跑一次,而你在 2023 年 6 月 1 日才部署它,系统就会把 1 月到 6 月的所有日任务全部排队执行,服务器直接被压垮是常事。

我踩过这个坑之后,现在创建新 DAG 默认都会写上catchup=False,避免产生不可控的历史回填。真正需要回填历史数据时,我会用显式方式指定回填的时间范围和任务范围,比如只回填某个特定周期、只重跑某一个 task_id,而不是把整段历史全部重新跑一遍。

4.3 时区与夏令时:账务与报表场景要多留一分心眼

Airflow 本身支持配置时区,比如设置为Asia/Shanghai,调度时间会按照该时区来理解。但有一类问题比时区更隐蔽:夏令时切换。对于没有夏令时地区运行的报表,这不存在;如果你的业务涉及海外站点,就必须仔细考虑夏令时切换那天,任务调度时间会不会出现一小时偏差,或者导致一天有两个任务实例、或者没有任务实例。

我的建议是,在 DAG 的调度层面不要过度依赖 cron 表达式去做特别精细的时间点,比如每天 01:30 这种非整点时间。夏令时切换的细节不是编程能轻易解决的,最好的办法是统一以 UTC 时间定义调度,展示层再转成本地时间,这样至少可以避免跨站点之间的混乱。真正需要精确当地时间的业务,请务必评估是否值得用更复杂的调度方案去处理。

5. 线上问题排查:一次“任务没跑”的完整链路复盘

Airflow 的 Web UI 已经把状态信息摆得很直观了,但我在实际工作中发现,很多人还是习惯第一时间去看日志,甚至去看系统进程。这其实是走了弯路。我想用一次典型的“任务没跑”场景,完整地讲一遍我的排查链路,从现象定位到根因,这套方法在多次线上问题中都被验证很高效。

5.1 通过视图定位,而不是先翻日志

某个周一早上十点,业务方说周末的日报没有生成。我打开 Airflow Web UI,先看该 DAG 的“最近 7 天运行记录”。视图里清晰地显示:上周六的运行实例状态是 failed,周日和周一应该出现的运行记录根本没有。第一层判断:任务部署配置或调度周期可能出了问题,而不是任务本身出错。

接着我点进周六那个 failed 实例,查看依赖图里是哪个节点标红。发现是wait_for_source_file失败,日志显示它等待的 FTP 文件始终没有出现。我再切到周日的视图,发现周日连实例都没产生,这就不是源码的问题,而是调度上的问题。检查 DAG 的start_date和schedule_interval后发现,周日凌晨部署的时候,start_date 被改成了部署时间之前的一个日期,加上 catchup 为 False,周日当天就没有被纳入调度周期。

5.2 依赖视图与上下游分析:五分钟内定位根因

这次排查从现象到根因,只用了不到十分钟。核心是依赖视图帮了大忙。如果一开始就扎进日志文件,你可能要花上十几分钟翻几个任务的输出,才能拼凑出大概情况。而 DAG 依赖视图明确表达了任务之间的上下游链:wait_for_source_file是所有任务的最上游,它失败必然导致整条链路失败。

这也是我反复强调依赖表达重要性的原因。一个编排系统如果无法提供“谁等谁、谁失败导致谁不能跑”的直观视图,那它做得再复杂也只是一种负担。Airflow 的 Graph 视图、Tree 视图和 Gantt 视图分别解决不同层面的可视问题:Graph 看依赖结构,Tree 看历史趋势,Gantt 看耗时瓶颈。排查问题时,我会按照“先 Tree 看整体表现、再 Graph 看依赖定位、最后 Gantt 看耗时异常”的顺序走,效率高很多。

5.3 资源与并发导致的隐性失败

还有一类失败不体现在代码里,而是隐藏在调度资源层面。某个 DAG 任务运行到一半突然变成 failed,日志里没有明确的 Python 异常,只显示“Task received SIGTERM”之类的信息。这种情况常见于 worker 内存被挤爆、Pod 被驱逐,或者任务执行时间超过了execution_timeout。

排查思路是分两步。第一步看那个时间段整个集群有没有其他高负载任务在跑,如果有,多半是资源争抢;第二步看任务的killed或timeout相关关键字日志,判断是不是execution_timeout设置太短误杀了慢任务。我曾在某次促销数据准备中,就因为一个原本 10 分钟的任务在数据量翻倍后跑了 25 分钟,超过了我设置的 20 分钟超时,导致整条链路中断。那次经验教训是:超时要设置,但不能拍脑袋,要考虑业务数据的高峰波动。

5.4 用告警分级代替无差别通知

整个排查过程还有一个容易踩的坑:告警通知。如果每个任务失败都立刻向全组飞书报警,三天之后所有人都会对报警麻木。我现在的做法是分级:核心链路的关键节点失败,直接告警到响应人;非核心任务的失败,只记录不通知;重试中的失败完全安静。这种方式显著减少了无谓的打扰。

在 Airflow 里可以这样实现:发送通知的逻辑写在 DAG 的回调函数或专门的on_failure_callback里,通过判断任务等级来决定是否调用外部告警接口。更粗暴一点的方案是,直接只给核心 DAG 配置告警,其他 DAG 靠日报式巡检。从实际体验来看,告警越克制,真出问题时被处理的速度反而越快。

尾声:关于编排清晰化,我最后想多说几句

从我这些年的实际体验来说,Airflow 不是银弹,它也解决不了所有调度问题,但它只要被用对方向,确实能让任务编排变得清晰不少。关键不在于把多少任务塞进一张 DAG 图里,而在于你是否遵守了单一职责、显式依赖、明确重试、勿滥用历史回填这些基本原则。工具只是把规则固定下来的框架,真正让链路变清晰的,还是制定并维护这些规则的人。

如果让我给刚上手 Airflow 的团队一个最实用的小建议,那就是先把现有脚本按“上游准备、中游计算、下游产出通知”三段式拆开,再写进 DAG。你会发现,哪怕看似复杂的任务,一旦拆分到位,依赖关系自然就浮出水面了。编排这件事,理顺依赖比熟练使用 API 重要得多,这句话我越做越深有体会。

相关新闻

MySQL 8创建不受限账号与授权全攻略:从GRANT到远程连接踩坑

MySQL 8创建不受限账号与授权全攻略:从GRANT到远程连接踩坑

1. 为什么MySQL 8的授权绕不开“版本差异”这道坎MySQL 8刚发布那阵子,不少从5.7升过来的老玩家在添加用户和授权上集体踩坑。原因很简单:MySQL 8改了几处关键行为,网上大量教程还在用5.7时代的写法,照着抄自然翻车。先明确“不受…

2026/10/20 16:36:29 阅读更多 →
context-mode:用上下文切换解决多环境配置混乱问题

context-mode:用上下文切换解决多环境配置混乱问题

我最近写了一个叫context-mode的小工具,起因其实特别普通:某天我在本地调试一个服务,改完配置后忘了切回测试环境,结果一上午的接口请求全打到了生产数据库上。那一次虽然没有造成真正的事故,但排查过程极其尴尬。从那…

2026/10/20 16:36:29 阅读更多 →
不靠多模态模型,六种自动化批量出图方案与避坑指南

不靠多模态模型,六种自动化批量出图方案与避坑指南

一直有朋友问:业务系统里要自动批量出图,但又不想接多模态模型,想要生成规则高度可控的那种方案,到底有没有?答案是肯定的,而且可选路线不少。多模态模型擅长的是创意发散,而自动化出图要的是确…

2026/10/20 16:36:29 阅读更多 →

最新新闻

全球AI模型榜前20名国产占6席:技术路线与选型指南

全球AI模型榜前20名国产占6席:技术路线与选型指南

1. 榜单背后的信号:国产模型进入第一梯队的真实含义第一次看到“全球AI模型榜前20名,国产占了6个”这个说法时,我的第一反应不是兴奋,而是想搞清楚三件事:这是哪个榜单、用什么指标排的、这6个模型分别强在哪。因为在大…

2026/10/20 22:39:53 阅读更多 →
多头自注意力机制详解:从原理到代码实战,用外卖订单讲透Transformer核心

多头自注意力机制详解:从原理到代码实战,用外卖订单讲透Transformer核心

1. 多头自注意力:别再死记公式,我用外卖订单给你讲明白第一次接触“多头自注意力”这个概念的时候,我盯着论文里的公式看了整整一个下午,脑子里全是“这到底是什么玩意儿”。后来做了几年深度学习相关的项目,踩过不少坑…

2026/10/20 22:39:53 阅读更多 →
计算器也能打穿?CTF中PHP eval黑名单绕过实战解析

计算器也能打穿?CTF中PHP eval黑名单绕过实战解析

1. 拿到题目的第一轮信息收集:页面、请求和异常输入探针1.1 先用肉眼和抓包把页面过一遍CTF的Web题里,最容易被低估的就是这种"门面干净"的题目。页面没有跳转、没有登录、没有文件上传点,只有一个孤零零的输入框和一个计算结果区&…

2026/10/20 22:39:53 阅读更多 →
用Python打造PPT生成工具:模板+数据+渲染三层架构实战

用Python打造PPT生成工具:模板+数据+渲染三层架构实战

1. 为什么我要自己动手做一个 PPT 生成工具 做技术分享、项目汇报、课程作业,甚至给客户做方案,PPT 几乎是绕不开的一环。我粗略算过,过去一年里我至少做了四十多份 PPT,平均每份从整理大纲到排版定稿要花三到五个小时。最让人抓狂…

2026/10/20 22:39:52 阅读更多 →
Python+TensorFlow+PyQt5人脸表情识别与情绪分类系统实战

Python+TensorFlow+PyQt5人脸表情识别与情绪分类系统实战

人脸表情识别这个方向,外行看起来就是“认个脸、判断一下表情”,真正动手做的人才知道,从摄像头画面到“开心、难过、惊讶”这些标签之间,至少隔着四座山:数据、模型、推理、界面。我最近把一套基于 Python TensorFlo…

2026/10/20 22:39:52 阅读更多 →
MySQL+Java+Swing学生宿舍管理系统课程设计全解析

MySQL+Java+Swing学生宿舍管理系统课程设计全解析

简介:面向高校数据库与Java课程设计场景,这套基于MySQLJavaSwing开发的学生宿舍管理系统提供了完整的可运行工程与配套文档。资源以学生信息管理、宿舍分配管理、管理员后台等核心模块为主线,包含数据库表设计、界面交互与业务逻辑分层实现&a…

2026/10/20 22:38:46 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →