<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="http://zheng-qinghe.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="http://zheng-qinghe.github.io/" rel="alternate" type="text/html" /><updated>2026-10-16T07:32:58+00:00</updated><id>http://zheng-qinghe.github.io/feed.xml</id><title type="html">于硕</title><subtitle>Shuo Yu</subtitle><entry><title type="html">对于营养获取的方式的思考</title><link href="http://zheng-qinghe.github.io/%E5%AF%B9%E4%BA%8E%E8%90%A5%E5%85%BB%E8%8E%B7%E5%8F%96%E7%9A%84%E6%96%B9%E5%BC%8F%E7%9A%84%E6%80%9D%E8%80%83/" rel="alternate" type="text/html" title="对于营养获取的方式的思考" /><published>2026-10-16T00:00:00+00:00</published><updated>2026-10-16T00:00:00+00:00</updated><id>http://zheng-qinghe.github.io/%E5%AF%B9%E4%BA%8E%E8%90%A5%E5%85%BB%E8%8E%B7%E5%8F%96%E7%9A%84%E6%96%B9%E5%BC%8F%E7%9A%84%E6%80%9D%E8%80%83</id><content type="html" xml:base="http://zheng-qinghe.github.io/%E5%AF%B9%E4%BA%8E%E8%90%A5%E5%85%BB%E8%8E%B7%E5%8F%96%E7%9A%84%E6%96%B9%E5%BC%8F%E7%9A%84%E6%80%9D%E8%80%83/"><![CDATA[<p>现在人们为了补充营养而消耗的精力和劳动力是相当大的，吃植物或者是动物可能会变成一种很奢侈很昂贵的事情，相信在不久的将来，甚至很有可能会被设置为法律所禁止的事情</p>

<p>人如果真的想要获得营养的话，直接喝对应的营养液就行，人吃饭的时间也会节省，做饭的时间以及种种工序也会节省。不以吃东西为乐趣的人就可以节省这个时间去做他想做的事了，现在人们为了获得营养，既要消耗巨大的人力、物力和时间，还要杀生，剥夺其他生命的生灵。这虽然是自然过渡中的一环，是自然规律中的一部分，但是这不是生灵意志的那个神的愿景 ，造物主给予了人们或者强壮的动物剥夺其他生灵的力量，但是并没有被告知是否有这样的权利</p>]]></content><author><name></name></author><summary type="html"><![CDATA[现在人们为了补充营养而消耗的精力和劳动力是相当大的，吃植物或者是动物可能会变成一种很奢侈很昂贵的事情，相信在不久的将来，甚至很有可能会被设置为法律所禁止的事情]]></summary></entry><entry><title type="html">角色卡可以写进提示词，也可以用 LoRA 写进权重</title><link href="http://zheng-qinghe.github.io/%E8%A7%92%E8%89%B2%E5%8D%A1%E5%8F%AF%E4%BB%A5%E5%86%99%E8%BF%9B%E6%8F%90%E7%A4%BA%E8%AF%8D-%E4%B9%9F%E5%8F%AF%E4%BB%A5%E7%94%A8-LoRA-%E5%86%99%E8%BF%9B%E6%9D%83%E9%87%8D/" rel="alternate" type="text/html" title="角色卡可以写进提示词，也可以用 LoRA 写进权重" /><published>2026-09-28T00:00:00+00:00</published><updated>2026-09-28T00:00:00+00:00</updated><id>http://zheng-qinghe.github.io/%E8%A7%92%E8%89%B2%E5%8D%A1%E5%8F%AF%E4%BB%A5%E5%86%99%E8%BF%9B%E6%8F%90%E7%A4%BA%E8%AF%8D-%E4%B9%9F%E5%8F%AF%E4%BB%A5%E7%94%A8-LoRA-%E5%86%99%E8%BF%9B%E6%9D%83%E9%87%8D</id><content type="html" xml:base="http://zheng-qinghe.github.io/%E8%A7%92%E8%89%B2%E5%8D%A1%E5%8F%AF%E4%BB%A5%E5%86%99%E8%BF%9B%E6%8F%90%E7%A4%BA%E8%AF%8D-%E4%B9%9F%E5%8F%AF%E4%BB%A5%E7%94%A8-LoRA-%E5%86%99%E8%BF%9B%E6%9D%83%E9%87%8D/"><![CDATA[<p>上一篇我写到：判断可以交给模型，但责任不行。这一篇换个更窄、也更技术的问题——<strong>一个角色的”人格”，到底存在哪？</strong></p>

<p>如果你玩过 SillyTavern（或任何角色扮演前端），大概见过”角色卡”：一张 PNG，里面塞一段 JSON，写着名字、外貌、性格、开场白、对话示例。拖进去，模型就”变成”这个角色。</p>

<p>但那张卡其实活在<strong>提示词层</strong>——每一轮对话，它都被塞进上下文。这一篇我想把它往下一层推：不塞进提示词，而是<strong>写进权重</strong>。</p>

<h2 id="提示词层的角色灵活但有三个代价">提示词层的角色：灵活，但有三个代价</h2>

<p>SillyTavern 的角色卡有明确的规范：主流的 V2（<code class="language-plaintext highlighter-rouge">chara_card_v2</code>）把字段收进一个 <code class="language-plaintext highlighter-rouge">data</code> 对象里——<code class="language-plaintext highlighter-rouge">name</code>、<code class="language-plaintext highlighter-rouge">description</code>、<code class="language-plaintext highlighter-rouge">personality</code>、<code class="language-plaintext highlighter-rouge">scenario</code>、<code class="language-plaintext highlighter-rouge">first_mes</code>（开场白）、<code class="language-plaintext highlighter-rouge">mes_example</code>（对话示例），外加 <code class="language-plaintext highlighter-rouge">system_prompt</code>、<code class="language-plaintext highlighter-rouge">alternate_greetings</code>、<code class="language-plaintext highlighter-rouge">creator_notes</code>，以及一个 <code class="language-plaintext highlighter-rouge">character_book</code>（世界书：关键词触发时才注入设定）。V3 在这个基础上又加了素材、多语言备注等。整段 JSON 以 base64 存在 PNG 的 <code class="language-plaintext highlighter-rouge">tEXt</code> 块里，所以一张图就是一张卡。</p>

<p>它的好处很实在：<strong>不用训练、即插即用、随时换</strong>。但它有三个代价。</p>

<ol>
  <li><strong>永久的 token 税。</strong> <code class="language-plaintext highlighter-rouge">description</code> 和 <code class="language-plaintext highlighter-rouge">personality</code> 是”常驻字段”，每一轮都注入；卡片越厚，挤掉的历史越多——这是”聊着聊着它忘事”的头号原因。</li>
  <li><strong>会漂。</strong> 角色住在上下文里，本质是”你每一轮都在提醒它是谁”。对话一长、话题一偏，它就容易出戏。</li>
  <li><strong>它只是换了上下文。</strong> 说到底，模型的权重一个字没变。你换的是”读什么”，不是”它是谁”。</li>
</ol>

<h2 id="模型层把角色写进权重">模型层：把角色写进权重</h2>

<p>换个思路：如果角色不是”被读到的”，而是”长在模型里”的呢？</p>

<p>这就是<strong>微调（fine-tuning）</strong>——具体说，是 <strong>LoRA / QLoRA</strong>（标题里的 LoRA 是统称，QLoRA 是它在量化底座上的版本）。做法是在冻结的底座旁边，训练一小撮低秩矩阵（适配器，通常只有几十到一两百 MB）。训练完，把适配器<strong>融合</strong>（fuse）回底座，你就得到一个”天生就是这个角色”的模型。</p>

<p>对比一下：提示词层每轮付 token 税，模型层是训练一次性付清、推理时<strong>零额外开销</strong>——因为适配器已经并进权重了。</p>

<h2 id="我为什么选-qlora">我为什么选 QLoRA</h2>

<p>先说硬件，因为这决定了一切。我用的是一台 <strong>MacBook Air（M3 / 24 GB 统一内存 / 512 GB SSD）</strong>。</p>

<p>按公开的内存档位：24 GB 统一内存大约能 cover <strong>LoRA 的 7–8B</strong>、或 <strong>QLoRA 的 8–14B</strong>。我盯上的底座是 12B，所以 LoRA 偏紧、<strong>QLoRA 正合适</strong>（QLoRA = 底座压到 4-bit，只训 16-bit 的 LoRA 适配器，内存占用大幅下降）。</p>

<p>框架用 Apple 自家的 <strong>MLX</strong>，对应命令行工具 <strong><code class="language-plaintext highlighter-rouge">mlx-lm</code></strong>——它原生支持 LoRA / DoRA / QLoRA，一条命令就能开训：</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip <span class="nb">install</span> <span class="s2">"mlx-lm[train]"</span>

python <span class="nt">-m</span> mlx_lm.lora <span class="se">\</span>
  <span class="nt">--model</span> mlx-community/gemma-4-12B-it-4bit <span class="se">\</span>
  <span class="nt">--train</span> <span class="nt">--data</span> ./data <span class="nt">--iters</span> 1000 <span class="se">\</span>
  <span class="nt">--batch-size</span> 2 <span class="nt">--grad-checkpoint</span>
</code></pre></div></div>

<p>底座是 <strong>Gemma 4 12B</strong>。这里有个容易被忽略的边界：Ollama 官网上已经有它的 MLX 构建 <code class="language-plaintext highlighter-rouge">gemma4:12b-mlx</code>，拉下来跑推理很顺（256K 上下文）；但<strong>要微调，得用同源的 MLX / HuggingFace 权重</strong>——Ollama 那个封装是给推理用的，不能直接拿去训。所以我的分工是：<strong>Ollama 管跑，<code class="language-plaintext highlighter-rouge">mlx-lm</code> 管训</strong>。训练完 <code class="language-plaintext highlighter-rouge">mlx_lm.fuse</code> 把适配器合并回底座，得到一个可独立运行的模型。</p>

<h2 id="数据让角色从剧本里学">数据：让角色从”剧本”里学</h2>

<p>我做的是<strong>剧本杀角色</strong>。这类角色的核心不是”知道很多事实”，而是<strong>稳定的说话方式</strong>——口癖、语气、在不同处境下的反应。所以训练数据要的不是百科，而是<strong>对话</strong>。</p>

<p><strong>语料来源这件事我只说一句：先想清楚版权归谁。</strong> 能用得踏实的，无非三类——<strong>自己原创的角色对话</strong>（自己写的剧本、自己设计的角色，最干净，也最贴角色）；<strong>公有领域的经典文本</strong>；<strong>许可写明白、照着许可用的开放语料</strong>。反过来，直接拿仍在版权期内的小说、影视对白去训，风险不该靠”我只是本地跑跑”来兜底。所以这一步，我用的是自己能说清来源的对话。</p>

<p>用法上，统一转成 <code class="language-plaintext highlighter-rouge">mlx-lm</code> 的 <strong>JSONL chat 格式</strong>：<code class="language-plaintext highlighter-rouge">system</code> 放这个角色的卡面（人设、处境），<code class="language-plaintext highlighter-rouge">user</code>/<code class="language-plaintext highlighter-rouge">assistant</code> 放对话——模型学的就是”在这个人设下，下一句该怎么说”。</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="nl">"messages"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
  </span><span class="p">{</span><span class="nl">"role"</span><span class="p">:</span><span class="w"> </span><span class="s2">"system"</span><span class="p">,</span><span class="w"> </span><span class="nl">"content"</span><span class="p">:</span><span class="w"> </span><span class="s2">"你是剧本《××》里的××，说话带几分江湖气，从不直说心事……"</span><span class="p">},</span><span class="w">
  </span><span class="p">{</span><span class="nl">"role"</span><span class="p">:</span><span class="w"> </span><span class="s2">"user"</span><span class="p">,</span><span class="w"> </span><span class="nl">"content"</span><span class="p">:</span><span class="w"> </span><span class="s2">"你昨晚到底去没去过那间屋子？"</span><span class="p">},</span><span class="w">
  </span><span class="p">{</span><span class="nl">"role"</span><span class="p">:</span><span class="w"> </span><span class="s2">"assistant"</span><span class="p">,</span><span class="w"> </span><span class="nl">"content"</span><span class="p">:</span><span class="w"> </span><span class="s2">"……我说没去过，你信么？"</span><span class="p">}</span><span class="w">
</span><span class="p">]}</span><span class="w">
</span></code></pre></div></div>

<h2 id="硬件这条线全公开">硬件这条线（全公开）</h2>

<ul>
  <li><strong>MacBook Air（Mac15,12）· Apple M3（8 核：4 性能 + 4 能效）· 24 GB 统一内存 · 512 GB 内置 SSD + 外接 1 TB SSD</strong></li>
</ul>

<p>两个我踩到、但常被忽略的坑：</p>

<ol>
  <li><strong>Air 没有风扇。</strong> 持续训练会热，热了就降频——同样的迭代数，笔记本会比带风扇的机器慢。所以别拿”跑通一次”就当性能基线。</li>
  <li>
    <p><strong>磁盘不像内存那么紧，但外接扩容有得有失。</strong> 本地微调官方建议留 <strong>20–50 GB</strong> 空闲（底座 + 数据集 + 检查点 + 合并后的权重）；我这台是 512 GB，日常够用，<strong>谈不上瓶颈</strong>。真要放大规模，最高性价比的办法是外接 SSD——但别只看容量：</p>

    <ul>
      <li><strong>利</strong>：便宜（苹果的内置存储加价很凶，外接 1 TB 划算得多）、不占系统盘、模型和数据能拔下来换机复用。</li>
      <li><strong>弊与风险</strong>：带宽与延迟不如内置 NVMe，USB 3.x 更比 Thunderbolt / USB4 慢一截，训练时的数据加载与 checkpoint 读写容易被拖成瓶颈；长时间大量读写会发热降速，偶发掉盘还会<strong>中断长训练</strong>；便携性也差；若格成 exFAT，还会踩不支持符号链接 / 权限、性能差的坑。</li>
      <li><strong>可行性</strong>：可行，但分工要清楚——<strong>大而冷</strong>的东西（权重、数据集、检查点）放外接，<strong>小而热</strong>的（代码、工作目录）留内置；盘格成 APFS、优先 Thunderbolt / USB4、注意散热，敏感数据记得加密。我自己的做法就是这样：模型和数据放外接 1 TB SSD，系统盘只留系统与日常。</li>
    </ul>
  </li>
</ol>

<h2 id="结果与边界">结果与边界</h2>

<p><em>（下面这些量级，是按公开基准推算、结合这台机器特性得出的；实测若有出入，以实测为准。）</em></p>

<p><strong>跑得动，也跑得完。</strong> 12B 的 QLoRA 在这台 24 GB 的机器上，峰值内存大致在 <strong>8–11 GB</strong> 的量级（公开实测里 14B 的 QLoRA 约 9 GB，12B 只会更低），留足了系统余量，不会把机器压死。速度上：公开基准里，7B 的 QLoRA 在 M2 Max 32 GB 上训 5,000 条大约 90 分钟；12B 参数量约 1.7 倍，再叠上 Air 没有风扇、持续跑会降频，我预期<strong>同规模数据要 2–4 小时</strong>。数据集按千级对话、2 个 epoch、<code class="language-plaintext highlighter-rouge">batch-size 2</code> 算，<code class="language-plaintext highlighter-rouge">iters</code> 落在 <strong>1,000–2,000</strong> 这个量级。</p>

<p><strong>模型层 vs 提示词层，差在哪：</strong></p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>提示词层（角色卡）</th>
      <th>模型层（LoRA）</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>长对话稳定性</td>
      <td>几十轮后容易出戏</td>
      <td>明显更稳，口癖是”长”在权重里的</td>
    </tr>
    <tr>
      <td>推理成本</td>
      <td>每轮付 token 税，卡面常驻上下文</td>
      <td>fuse 后零额外开销，上下文留给对话本身</td>
    </tr>
    <tr>
      <td>灵活性</td>
      <td>随换随用，一张卡就是一个角色</td>
      <td>一个适配器≈一个角色，换角色要重训</td>
    </tr>
    <tr>
      <td>前置成本</td>
      <td>零</td>
      <td>要数据、要训练、要时间</td>
    </tr>
  </tbody>
</table>

<p><strong>代价要说清。</strong> 微调有两把刀：<strong>灾难性遗忘</strong>和<strong>过拟合</strong>。数据太少，模型会退化成”复读机”——只会重复训练集里的句式；学得太狠，又会损伤底座原本的能力。所以数据质量比数量重要，<code class="language-plaintext highlighter-rouge">rank</code>、<code class="language-plaintext highlighter-rouge">alpha</code>、学习率都要往保守里调，<code class="language-plaintext highlighter-rouge">grad-checkpoint</code> 该开就开。</p>

<p>最后回到上一篇那条线。把角色写进权重，说到底还是<strong>本地、私有</strong>的一步——数据不出这台机器，模型在自己手里。但”角色可以被固化”不等于”判断可以被托管”：<strong>人格可以写进权重，责任不行。</strong> 它演得再像，那个”像不像、能不能用、要不要发”，仍然得有人来担。</p>]]></content><author><name></name></author><summary type="html"><![CDATA[上一篇我写到：判断可以交给模型，但责任不行。这一篇换个更窄、也更技术的问题——一个角色的”人格”，到底存在哪？]]></summary></entry><entry><title type="html">对开源的思考</title><link href="http://zheng-qinghe.github.io/%E5%AF%B9%E5%BC%80%E6%BA%90%E7%9A%84%E6%80%9D%E8%80%83/" rel="alternate" type="text/html" title="对开源的思考" /><published>2026-09-12T00:00:00+00:00</published><updated>2026-09-12T00:00:00+00:00</updated><id>http://zheng-qinghe.github.io/%E5%AF%B9%E5%BC%80%E6%BA%90%E7%9A%84%E6%80%9D%E8%80%83</id><content type="html" xml:base="http://zheng-qinghe.github.io/%E5%AF%B9%E5%BC%80%E6%BA%90%E7%9A%84%E6%80%9D%E8%80%83/"><![CDATA[<p>我想写个对于开源，我的看法</p>

<p>首先我所呈现的是来自对自然给我的感受和生灵历年的积淀的，是站在巨人的肩膀上做的场景泛化应用或者迭代，就像现在在地球上的自行车设计离不开牛顿定律</p>

<p>如果大家真的需要这个东西并且其意识到，就向大家宣传推广并尽可能的把大家都教会，这样的话既能提升自己周边人的这样一个素养，也是一个推力，让自己看到更广泛的世界，发现自己的不足，倒逼自己迭代。我想这样会成为一个良性循环。我喜欢大家互相真诚分享的环境。</p>

<p>此外，很多时候后知后觉我的很多问题其实是有答案的 不论是对于人生路线上的事情还是某个想法的实现来说 从真实的传记或者新闻什么的层面切入了解 增加对应背景成功和失败的了解有的时候是启发性的，至少也能让我减少很多不安。如今也把我解决了的问题尽可能分享给大家，我们不需要重复的创造轮子，就像我们在土壤上为了果腹而种植庄稼一样，只需要用轮子作出能效更高的自行车，或者不论是否发现轮子的不足，做航天器。或哪天没有燃眉之急的时候，去看看土壤为什么会长出庄稼，土壤从何而来，能否创造。   下面是你的时间。</p>]]></content><author><name></name></author><summary type="html"><![CDATA[我想写个对于开源，我的看法]]></summary></entry><entry><title type="html">当 121 条素材遇上批量重命名</title><link href="http://zheng-qinghe.github.io/%E5%BD%93121%E6%9D%A1%E7%B4%A0%E6%9D%90%E9%81%87%E4%B8%8A%E6%89%B9%E9%87%8F%E9%87%8D%E5%91%BD%E5%90%8D/" rel="alternate" type="text/html" title="当 121 条素材遇上批量重命名" /><published>2026-09-05T00:00:00+00:00</published><updated>2026-09-05T00:00:00+00:00</updated><id>http://zheng-qinghe.github.io/%E5%BD%93121%E6%9D%A1%E7%B4%A0%E6%9D%90%E9%81%87%E4%B8%8A%E6%89%B9%E9%87%8F%E9%87%8D%E5%91%BD%E5%90%8D</id><content type="html" xml:base="http://zheng-qinghe.github.io/%E5%BD%93121%E6%9D%A1%E7%B4%A0%E6%9D%90%E9%81%87%E4%B8%8A%E6%89%B9%E9%87%8F%E9%87%8D%E5%91%BD%E5%90%8D/"><![CDATA[<p>这是工具箱系列的第二篇。上一篇写的是 <a href="/当OCR遇上SOP/">当 OCR 遇上 SOP</a>，讲的是怎么把散落的截图和文档变成可检索的东西。这一篇换个方向：问题不是”找不到内容”，而是”找到了也是一堆乱名字”。</p>

<p>主角是 Windows 上一个叫 PowerRename 的小工具。</p>

<h2 id="一天-121-条最先崩的是重命名">一天 121 条，最先崩的是重命名</h2>

<p>25年5月，我在某企业做新媒体运营的时候会涉及一些视频剪辑的工作。</p>

<p>那两个月的节奏是：<strong>同一条底稿，换开头、换字幕、换封面，批量复制出一堆变体去铺矩阵号。</strong></p>

<p>这个量级下，最先崩的不是剪辑速度，是<strong>素材的名字</strong>。</p>

<p>素材进来的样子大概是这样的：</p>

<ul>
  <li>手机导出来的：<code class="language-plaintext highlighter-rouge">VID_20250512_143022.mp4</code></li>
  <li>相机导出来的：<code class="language-plaintext highlighter-rouge">DSC00123.MOV</code></li>
  <li>微信群里存的：<code class="language-plaintext highlighter-rouge">微信图片_20250512143022.jpg</code></li>
  <li>剪映自动存的：<code class="language-plaintext highlighter-rouge">未命名草稿_2025-05-12-14-30-22.mp4</code></li>
  <li>还有更绝的：<code class="language-plaintext highlighter-rouge">新建文件夹 (2)</code>、<code class="language-plaintext highlighter-rouge">最终版3</code>、<code class="language-plaintext highlighter-rouge">最终版3改</code></li>
</ul>

<p>单看一条视频，乱一点也就乱一点，翻一下就找到了。但当你一天要处理一百多条、而且要<strong>反复回去复用旧素材</strong>的时候，名字就是索引。名字乱，等于没有索引。</p>

<h2 id="为什么名字这么要紧">为什么名字这么要紧</h2>

<p>我当时用飞书搭了个知识库，把脚本、素材、上传、置顶文案复盘成一条批量生产流程。流程能不能跑起来，前提是<strong>文件名可预测</strong>：</p>

<ul>
  <li>一条脚本要对应一批素材，靠名字里的脚本编号能对上；</li>
  <li>裂变出来的 121 条，要能按序号排序、按日期归档；</li>
  <li>两周后回头复用某个镜头，得能靠关键词搜到，而不是靠回忆”那天那个……好像在第三个文件夹？”</li>
</ul>

<p>说白了：<strong>名字不是给现在的我看的，是给一周后那个已经忘光的我看的。</strong></p>

<h2 id="powerrename微软塞进-powertoys-里的那把刀">PowerRename：微软塞进 PowerToys 里的那把刀</h2>

<p>PowerRename 是 <strong>PowerToys</strong> 里的一个模块。PowerToys 是微软官方出的一套 Windows 效率工具集，<strong>免费、开源</strong>，装上之后会在文件资源管理器的右键菜单里多出一项 <code class="language-plaintext highlighter-rouge">Rename with PowerRename</code>。</p>

<p>真正让我留下来的，是三件事：</p>

<ol>
  <li><strong>改之前先看结果。</strong> 上面填”查找”、下面填”替换”，中间实时列出<strong>每一行改完会变成什么样</strong>。没点应用之前，硬盘上一个字节都不动。</li>
  <li><strong>支持正则。</strong> 勾上 <code class="language-plaintext highlighter-rouge">Use regular expressions</code>，就能用捕获组，把 <code class="language-plaintext highlighter-rouge">VID_20250512_143022</code> 这种机器名里的日期和时间<strong>拆出来重新拼</strong>。</li>
  <li><strong>能自动编号。</strong> 替换值里写 <code class="language-plaintext highlighter-rouge">${padding=3;start=1}</code>，它就会给选中的文件依次补上 <code class="language-plaintext highlighter-rouge">001</code>、<code class="language-plaintext highlighter-rouge">002</code>、<code class="language-plaintext highlighter-rouge">003</code>——补零是自动的，不会排成 <code class="language-plaintext highlighter-rouge">1, 10, 11, 2</code>。</li>
</ol>

<p>还有一个救命细节：改错了不用慌，资源管理器里 <strong>Ctrl+Z 能撤销</strong>。</p>

<h2 id="我的三步">我的三步</h2>

<p><strong>第一步：先把脏东西洗掉</strong></p>

<p>最浅的一层，纯文本查找替换，连正则都不用开。</p>

<p>比如把一批从微信里存下来的图片统一去掉前缀：</p>

<ul>
  <li>查找：<code class="language-plaintext highlighter-rouge">微信图片_</code></li>
  <li>替换：（留空）</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">微信图片_20250512143022.jpg</code> 就变成了 <code class="language-plaintext highlighter-rouge">20250512143022.jpg</code>。这一步的价值不是省时间，是<strong>让后面所有规则有一个稳定的输入</strong>。</p>

<p><strong>第二步：统一前缀 + 自动编号（用得最多的一步）</strong></p>

<p>选中一批要归到同一个脚本下的素材：</p>

<ul>
  <li>查找：<code class="language-plaintext highlighter-rouge">^VID_.*</code>（勾上正则）</li>
  <li>替换：<code class="language-plaintext highlighter-rouge">20250512_脚本A_口播_${padding=3;start=1}</code></li>
  <li>应用到：<strong>仅文件名</strong>（扩展名不动）</li>
</ul>

<p>于是：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>VID_20250512_143022.mp4  -&gt;  20250512_脚本A_口播_001.mp4
VID_20250512_143155.mp4  -&gt;  20250512_脚本A_口播_002.mp4
VID_20250512_143401.mp4  -&gt;  20250512_脚本A_口播_003.mp4
</code></pre></div></div>

<p>一次点击，几十条素材全部归位，扩展名原样保留。</p>

<p><strong>第三步：名字里本来就有信息，就别盖掉</strong></p>

<p>相机和手机导出的名字里通常已经带日期时间，与其盖掉，不如<strong>拆出来重排</strong>。用捕获组：</p>

<ul>
  <li>查找：<code class="language-plaintext highlighter-rouge">^VID_(\d{8})_(\d{6})$</code>（勾正则，并勾上”匹配所有出现”）</li>
  <li>替换：<code class="language-plaintext highlighter-rouge">$1_$2_口播</code></li>
</ul>

<p><code class="language-plaintext highlighter-rouge">VID_20250512_143022</code> → <code class="language-plaintext highlighter-rouge">20250512_143022_口播</code>。</p>

<p><code class="language-plaintext highlighter-rouge">$1</code>、<code class="language-plaintext highlighter-rouge">$2</code> 就是正则里那两对括号抓到的东西——年日月、时分秒。日期时间没丢，还多了语义。</p>

<h2 id="换了-mac-之后右键就能做不用装任何东西">换了 Mac 之后：右键就能做，不用装任何东西</h2>

<p>后来我的主力机换成了 Mac。26 年再碰到批量重命名的活儿，我第一反应是去找”Mac 上的 PowerRename”，找了一圈才发现：<strong>这件事根本不用装工具</strong>。</p>

<p>在访达里选中一批文件，<strong>右键 →「重新命名…」</strong>（选中 N 个时会显示成「重新命名 N 个项目」），弹出的面板给了三种做法，和上面那三步几乎一一对应：</p>

<table>
  <thead>
    <tr>
      <th>想干什么</th>
      <th>macOS 右键面板里怎么选</th>
      <th>对应 PowerRename</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>去掉 / 替换名字里的某段字</td>
      <td><strong>替换文本</strong>：”查找”填要删的，”替换成”留空就是删</td>
      <td>纯文本查找替换</td>
    </tr>
    <tr>
      <td>统一加前缀或后缀</td>
      <td><strong>添加文本</strong>：选”名称之前 / 之后”</td>
      <td>同</td>
    </tr>
    <tr>
      <td>统一前缀 + 补零编号</td>
      <td><strong>格式 → 名称和计数器</strong>：自定义格式填前缀，”起始数字”填 1</td>
      <td><code class="language-plaintext highlighter-rouge">${padding=3;start=1}</code></td>
    </tr>
    <tr>
      <td>统一前缀 + 不补零编号</td>
      <td><strong>格式 → 名称和索引</strong></td>
      <td><code class="language-plaintext highlighter-rouge">${start=1}</code>（无 padding）</td>
    </tr>
    <tr>
      <td>按修改日期命名</td>
      <td><strong>格式 → 名称和日期</strong></td>
      <td><code class="language-plaintext highlighter-rouge">$YYYY</code> / <code class="language-plaintext highlighter-rouge">$MM</code> / <code class="language-plaintext highlighter-rouge">$DD</code> 日期变量</td>
    </tr>
  </tbody>
</table>

<p>也就是说，我在 Windows 上最依赖的那招”统一前缀 + 补零编号”，在 Mac 上对应的就是「<strong>名称和计数器</strong>」——它会补前导零，生成 <code class="language-plaintext highlighter-rouge">001</code>、<code class="language-plaintext highlighter-rouge">002</code>、<code class="language-plaintext highlighter-rouge">003</code>，排序时不会出现 <code class="language-plaintext highlighter-rouge">1, 10, 11, 2</code> 这种乱序。「名称和索引」则是纯数字 <code class="language-plaintext highlighter-rouge">1, 2, 3</code>，不补零。</p>

<p>改错了同样是 <strong>Command + Z</strong>（或菜单栏”编辑 → 撤销重新命名”），<strong>整批撤销</strong>。</p>

<h3 id="别去找快捷指令里的现成动作我走错过路">别去找”快捷指令”里的现成动作，我走错过路</h3>

<p>我一开始跑偏了，先去 Automator 和”快捷指令”里翻。这里得澄清一句：右键菜单里那个「<strong>快速操作</strong>」（Quick Actions）子菜单，<strong>系统自带的那些</strong>是旋转、标记、创建 PDF、转换图像这类<strong>处理文件内容</strong>的动作，<strong>并不负责重命名</strong>。想批量改名，认准同一级菜单里的「重新命名…」就够了——除非你自己写一个（见下一节）。</p>

<h3 id="边界唯一做不到的是正则">边界：唯一做不到的是正则</h3>

<p>右键这套只能做”整段查找替换”和”套模板编号”——<strong>没有正则</strong>，也就没法像 PowerRename 那样用捕获组，把 <code class="language-plaintext highlighter-rouge">VID_20250512_143022</code> 里的日期和时间<strong>拆出来重新拼</strong>。</p>

<p>我日常九成的重命名需求——洗掉脏前缀、统一前缀加编号——右键那一下就够了。剩下那一成，可以这么补。</p>

<h3 id="想上正则怎么办快速操作--一段脚本">想上正则怎么办：快速操作 + 一段脚本</h3>

<p>办法是有的：用「快捷指令」新建一个<strong>快速操作</strong>（接收访达里的”文件或文件夹”），里面只放一个「<strong>运行 Shell 脚本</strong>」动作，让脚本去做正则。保存之后，访达右键 → 快速操作 → 就能直接调用。</p>

<p>把上面 Windows 那步 <code class="language-plaintext highlighter-rouge">^VID_(\d{8})_(\d{6})$</code> → <code class="language-plaintext highlighter-rouge">$1_$2_口播</code> 搬到 Mac 上，脚本是这么写的：</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for </span>f <span class="k">in</span> <span class="s2">"</span><span class="nv">$@</span><span class="s2">"</span><span class="p">;</span> <span class="k">do
  </span><span class="nb">dir</span><span class="o">=</span><span class="si">$(</span><span class="nb">dirname</span> <span class="s2">"</span><span class="nv">$f</span><span class="s2">"</span><span class="si">)</span><span class="p">;</span> <span class="nv">base</span><span class="o">=</span><span class="si">$(</span><span class="nb">basename</span> <span class="s2">"</span><span class="nv">$f</span><span class="s2">"</span><span class="si">)</span>
  <span class="nv">name</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">base</span><span class="p">%.*</span><span class="k">}</span><span class="s2">"</span><span class="p">;</span> <span class="nv">ext</span><span class="o">=</span><span class="s2">"</span><span class="k">${</span><span class="nv">base</span><span class="p">##*.</span><span class="k">}</span><span class="s2">"</span>
  <span class="nv">new</span><span class="o">=</span><span class="si">$(</span><span class="nb">printf</span> <span class="s1">'%s'</span> <span class="s2">"</span><span class="nv">$name</span><span class="s2">"</span> | perl <span class="nt">-pe</span> <span class="s1">'s/^VID_(\d{8})_(\d{6})$/$1_$2_口播/'</span><span class="si">)</span>
  <span class="o">[</span> <span class="s2">"</span><span class="nv">$new</span><span class="s2">"</span> <span class="o">!=</span> <span class="s2">"</span><span class="nv">$name</span><span class="s2">"</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nb">mv</span> <span class="s2">"</span><span class="nv">$f</span><span class="s2">"</span> <span class="s2">"</span><span class="nv">$dir</span><span class="s2">/</span><span class="nv">$new</span><span class="s2">.</span><span class="nv">$ext</span><span class="s2">"</span>
<span class="k">done</span>
</code></pre></div></div>

<p>嫌长可以用 zsh 自带的 <code class="language-plaintext highlighter-rouge">zmv</code>：</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>autoload <span class="nt">-Uz</span> zmv
zmv <span class="s1">'VID_(*)_(*).mp4'</span> <span class="s1">'${1}_${2}_口播.mp4'</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">zmv</code> 加 <code class="language-plaintext highlighter-rouge">-n</code> 是<strong>空跑预览</strong>——只打印将要改成什么、不动手。所以流程是：先 <code class="language-plaintext highlighter-rouge">zmv -n</code> 看一眼对不对，确认了再去掉 <code class="language-plaintext highlighter-rouge">-n</code> 真跑。</p>

<p><strong>能力是追平了，但有两样东西追不回来：</strong></p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>PowerRename</th>
      <th>快速操作 + 脚本</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>正则 / 捕获组</td>
      <td>✅</td>
      <td>✅</td>
    </tr>
    <tr>
      <td>补零计数</td>
      <td>✅</td>
      <td>✅（右键本身就有）</td>
    </tr>
    <tr>
      <td><strong>实时预览</strong></td>
      <td>✅ 面板里逐行显示</td>
      <td>⚠️ 只能靠 <code class="language-plaintext highlighter-rouge">zmv -n</code> 空跑</td>
    </tr>
    <tr>
      <td><strong>Ctrl/Command+Z 整批撤销</strong></td>
      <td>✅</td>
      <td>❌ 脚本改名后访达撤销不可靠</td>
    </tr>
    <tr>
      <td>上手成本</td>
      <td>装个软件</td>
      <td>写 + 长期维护脚本</td>
    </tr>
    <tr>
      <td>上限</td>
      <td>微软给什么用什么</td>
      <td><strong>任意逻辑</strong>（能读元数据、按内容改名）</td>
    </tr>
  </tbody>
</table>

<p>所以我的选择是：<strong>不为这一成需求去维护一个快速操作</strong>。真偶尔要拆字段重排，临时开终端 <code class="language-plaintext highlighter-rouge">zmv -n</code> 看一眼再执行，比养着一个脚本省心，也避开了”脚本改名撤销不了”这个风险。</p>

<h2 id="边界我不想把它说成万能">边界，我不想把它说成万能</h2>

<ol>
  <li><strong>它只在 Windows 上。</strong> PowerToys 是 Windows 工具，没有 Mac 版。我当时用的是 Windows 电脑；后来主力机换成 Mac，这套就用不了了——Mac 上的替代做法见上一节。</li>
  <li><strong>它只改名字，不动内容。</strong> 不碰文件内容、不改编码、不转格式——这反而是我敢放心用的原因。</li>
  <li><strong>撤销只管最后一步。</strong> Ctrl+Z 能救回来，但别指望撤一长串；大批量操作前，可以自己检查完之后再让agent检查一遍确保无误。</li>
</ol>

<h2 id="为什么它也进了这个工具箱">为什么它也进了这个工具箱</h2>

<p>和上一篇一样：卡住 → 硬扛 → 撞上一个工具 → 突然顺了。</p>

<p>我第一次意识到”重命名”是个真问题，是在连续两天翻不出一条旧镜头之后。它不是什么高深技术，但<strong>恰恰是这种没人会专门去教、小到不好意思开口问的东西，最浪费时间</strong>。</p>

<p>工具会过时，但”我当时被什么卡住、我是怎么判断该用什么工具的”不会过时。这是这个工具箱想记下来的东西。</p>

<hr />

<h2 id="附录">附录</h2>

<ul>
  <li><strong>PowerToys</strong>：微软官方 Windows 效率工具集，免费开源，支持 Windows 10 / 11。仓库 <code class="language-plaintext highlighter-rouge">https://github.com/microsoft/PowerToys</code></li>
  <li><strong>PowerRename</strong>：其中的批量重命名模块。支持查找替换、正则表达式（ECMAScript 语法）、计数器 <code class="language-plaintext highlighter-rouge">${padding=3;start=1}</code>、文本大小写转换、实时预览、Ctrl+Z 撤销；可作用于文件名或仅扩展名，可包含/排除子文件夹。官方文档见微软 PowerToys 文档站。</li>
  <li><strong>macOS 访达批量重命名</strong>：系统自带，无需安装。选中文件 → 右键「重新命名…」→ 替换文本 / 添加文本 / 格式（名称和索引、名称和计数器、名称和日期）。官方说明见 Apple 支持文档《在 Mac 上给文件、文件夹和磁盘重新命名》：<code class="language-plaintext highlighter-rouge">https://support.apple.com/zh-cn/guide/mac-help/mchlp1144/mac</code></li>
</ul>]]></content><author><name></name></author><summary type="html"><![CDATA[这是工具箱系列的第二篇。上一篇写的是 当 OCR 遇上 SOP，讲的是怎么把散落的截图和文档变成可检索的东西。这一篇换个方向：问题不是”找不到内容”，而是”找到了也是一堆乱名字”。]]></summary></entry><entry><title type="html">当 OCR 遇上 SOP</title><link href="http://zheng-qinghe.github.io/%E5%BD%93OCR%E9%81%87%E4%B8%8ASOP/" rel="alternate" type="text/html" title="当 OCR 遇上 SOP" /><published>2026-09-03T00:00:00+00:00</published><updated>2026-09-03T00:00:00+00:00</updated><id>http://zheng-qinghe.github.io/%E5%BD%93OCR%E9%81%87%E4%B8%8ASOP</id><content type="html" xml:base="http://zheng-qinghe.github.io/%E5%BD%93OCR%E9%81%87%E4%B8%8ASOP/"><![CDATA[<p>这是我想写的一个新系列的第一篇。我想把自己在实习和工作里真正用顺手的工具，一个一个记录下来，开源成一个工具箱。第一个想写的是 MarginNote。</p>

<h2 id="一个具体到化学品名词的问题">一个具体到化学品名词的问题</h2>

<p>2024 年 7 月，我在深圳市计量质量检测研究院（SMQ）业务发展部做业务助理实习生。那三个月，我和几位工程师的一项作业内容就是一起完成了 600 多份阿里巴巴、唯品会的检测报告录入。</p>

<p>真正难住我的不是”录入”这个动作，而是”录什么”。</p>

<p>检测报告里有大量化学名词，不同品类、不同判定规则下，同一个物质的写法可能完全不一样——多一个空格、少一个下标、大小写差一位，在 SOP 标准里就是不合格。当时我们拆样和记录要按 RB/T 214-2017 第 4.5 条、CNAS-CL01 第 7.4 条等等来做（那阵子光京东样品的电池拆样我就做了 70 多份），本质上都是在跟”精确”这两个字较劲。</p>

<p>所以我的真实工作流变成了：录一条 → 不确定 → 翻 SOP → 找到原文 → 再录下一条。</p>

<p>问题出在”翻 SOP”这一步。</p>

<h2 id="sop-不只是一份文档">SOP 不只是一份文档</h2>

<p>如果 SOP 只是一份规整的 PDF，事情会简单很多——能选中文字的，直接搜索就完了。</p>

<p>但真实的 SOP 是散的，而且相当大一部分<strong>根本不在正式文档里</strong>。</p>

<p>它有相当比例来自 QQ 群聊和私聊：前辈在群里发一句”这个品类按新口径走”、mentor 私聊发过来一张截图说”这条规则看下”、某个判定细节在几十条聊天记录里被反复补充。这些内容是鲜活的、最新的，也是最容易丢的——它们散落在各个聊天框里，平时根本不会去回看。</p>

<p>于是我面对的是两类东西：</p>

<ul>
  <li><strong>静态的一半</strong>：正式 SOP 文档，PDF，有的能选中文字，有的不能（基本就是几百页图片）</li>
  <li><strong>流动的一半</strong>：聊天记录，散落在各个聊天框里，没有任何结构，更别提搜索</li>
</ul>

<p>这两半加在一起才是我要检索的”SOP”。而它们当时互不相通。</p>

<h2 id="从截图到可检索picsew--marginnote">从截图到可检索：Picsew + MarginNote</h2>

<p>我的办法是把这两半都变成 PDF，然后塞进同一个地方检索。</p>

<p><strong>第一步：聊天记录 → 长截屏 → PDF</strong></p>

<p>用 <strong>Picsew</strong>（Yojio, Ltd.，iOS / iPad / Mac 都有）。它最关键的不是”拼图”，而是<strong>滚动录屏</strong>：在 QQ 对应的聊天框里开着录屏往上滚一遍，Picsew 会把这段屏幕录制直接识别成一张完整的长截屏，连中间手动截都不用。最后一步直接<strong>导出 PDF</strong>。Picsew 同样要花钱，我买的时候是 <strong>15 元</strong>。</p>

<p>顺带吐槽一句：都 2024 年了（2026年貌似还是没有），苹果系统至今没有自带的长截图能力——聊天记录这种一屏装不下的内容，系统原生只能一张张截，想拼成连续的一整张，得靠第三方 App 的滚动录屏来绕。这笔 15 元，算是给苹果的功能缺口付的过路费。</p>

<p>这一步的价值是：一条几十屏的聊天记录，变成了一份连续的、能翻页的文档。</p>

<p><strong>第二步：PDF → 可检索</strong></p>

<p>把导出的 PDF 和正式 SOP 一起，全部丢进 <strong>MarginNote</strong>（iCloud 同步）。</p>

<p>MarginNote 是付费软件，我买的时候是 88 元（iPhone和iPad可用版）。</p>

<p>MarginNote 真正救了我的，是它的 OCR 能力。打开 OCR 之后，它会在后台对整份文档做一次 OCR 识别预处理的动作把全文变成可检索的，这个过程要根据文档长度和设备性能稍稍一等。等它处理好，我直接在上面搜一个化学名词，它就会精准地定位到文档里那段内容，并且<strong>自动把文档滚动到对应的位置</strong>——不用再在”原图”和”识别结果”之间来回切。</p>

<p><strong>第三步：统一检索</strong></p>

<p>到这里，静态的 SOP 和从聊天记录里长出来的操作口径，终于进了同一个搜索框。</p>

<p>我不再需要记”这条规则大概在第几章”，也不需要在几百页图片里用眼睛找，更不用在聊天框里往上翻记录。搜一下，它直接带着我滚到那一段——几秒钟。</p>

<h2 id="关于-98">关于 98%</h2>

<p>我说它准确，不是凭感觉。在 SMQ 那批 SOP 和聊天截图上，我的体感识别准确率在 98% 左右，检索是秒级的。</p>

<p>但这个数字有三个前提，我不想把它说成万能的：</p>

<ol>
  <li><strong>材料本身要清晰。</strong> SOP 是印刷体、排版规整；聊天截图是屏幕文字，清晰度更高。OCR 在这类材料上发挥得最好。换成老旧文献、模糊扫描件，识别率会明显下降，网上也有用户吐槽过这一点。</li>
  <li><strong>聊天截图有额外损耗。</strong> Picsew 拼接的接缝处偶尔会切到字，长图越宽、导出 PDF 时被压缩得越狠，识别就越容易出错。我的做法是拼完先自己扫一遍接缝。</li>
  <li><strong>98% 的剩下 2% 更危险。</strong> 化学名词里，错一个字符就是另一回事。所以我从不敢直接抄识别结果——我的习惯是：OCR 帮我定位，眼睛做最终确认。工具是用来缩小搜索范围的，不是用来替我负责的。</li>
</ol>

<p>这大概也是这段经历留给我的东西：<strong>流程可以加速，判定不能外包。</strong></p>

<h2 id="为什么想做这个工具箱">为什么想做这个工具箱</h2>

<p>从那之后我意识到一件事：每次被一个问题卡住，我都是先冥思苦想、反复试错，直到某一天撞上一个合适的工具，才突然变得顺滑、高效。工具本身不稀奇，稀奇的是”找到它”之前那段弯路。我不想让其他人也走一遍同样的弯路，所以才想把用顺手的工具一个一个记下来，攒成这个开源工具箱。</p>

<p>我的打算是：每个工具配一篇文，写清楚它解决什么问题、在什么场景下有用、边界在哪里。</p>

<p>我不想写”神器推荐”那种文章。工具会过时，但”我当时被什么问题卡住、我是怎么判断该用什么工具的”这个过程不会过时。</p>

<p>这是第一篇。</p>]]></content><author><name></name></author><summary type="html"><![CDATA[这是我想写的一个新系列的第一篇。我想把自己在实习和工作里真正用顺手的工具，一个一个记录下来，开源成一个工具箱。第一个想写的是 MarginNote。]]></summary></entry><entry><title type="html">No Trivial Labor</title><link href="http://zheng-qinghe.github.io/No-Trivial-Labor/" rel="alternate" type="text/html" title="No Trivial Labor" /><published>2026-03-12T00:00:00+00:00</published><updated>2026-03-12T00:00:00+00:00</updated><id>http://zheng-qinghe.github.io/No%20Trivial%20Labor</id><content type="html" xml:base="http://zheng-qinghe.github.io/No-Trivial-Labor/"><![CDATA[<p>一切的开始，都源于我工作中突然冒出的一个念头：“既然工作都是由计算机来完成的，那我做的工作中很多的重复性的作业（比如重复的在某个时间段打开同样的应用执行同样的操作）是不是也能自动化呢？”</p>

<h2 id="挑战与阻碍">挑战与阻碍</h2>
<p>首先我尝试的是通过代码来进行这个作业（这对当时零代码基础的我是很大挑战，但是我对当时的ai写代码能力已经很有信心。）我首先实现了通过点击一个存在桌面上的代码文件来自动让浏览器打开对应的网页，那网页之后的ui点击操作呢？右键网页，点击检查，找到那个ui的相关代码…… 这一步我印象中当时好像没能实现点击目标ui，紧接着我发现认证是一个更让我头疼的问题，在电脑上扫个码能登录进去的网站通过代码总是会被网站的一些认证机制挡住。
困惑，但是我始终未放弃那一个念</p>
<h2 id="遇见power-automate">遇见Power Automate</h2>
<p>已经忘了是在哪里遇到的了，好像是ai平台？某个大神的分享？等有时间我一定要好好回忆一下这个层解放我生产力的时刻来自哪里，总之power automate进入了我的视野！
那时的我也不确定能否真的能够应用，因为对公司当时还是不太敢在公司之外的网络环境登陆，我在自己常用的软件上随便试用了一番便抱着电脑既兴奋又不安的离开了图书馆，等待第二天去到公司。</p>
<h2 id="喜多优少的落地实践">喜多优少的落地实践</h2>
<p>完成了常规工作后我紧忙将工作流程写入了power automate 很幸运 每个工作流的测试都是成功的，兴奋到了极点，谢天谢地终于不用一直点鼠标了。
紧接着问题出现了，时常会出错呀，本来运行的就需要等一会儿（我一直用的都是desktop版本，不知道跟没有付费关系大不大）还时不时的突然运动完之后没反应，需要关上再运行一次，这也让我产生了不少精神熵，但是还好，像是汽车的自动驾驶，我看着ta执行总比自己一直点点点好。
就这样我几乎每天到公司打开电脑的第一件事就是按住win键打开power automate。感谢mentor给我讲任务的时候细致到公司web后台每一个工作流该怎么操作，这让我后面有了能够用这个ui自动化工具来不假思索的控制相应的界面，致敬。</p>
<h2 id="邮件数据的自动化处理">邮件数据的自动化处理</h2>
<p>好的，一个新的任务中的一个步骤又难住了我，我需要汇总并分析一段时间内xx项目的数据，而这个数据是通过邮件时实发送给我的，一条一条的那种，好在有效的数据是作为xls文件附在每一条邮件里面的。何解？我想这并不难，开发部肯定有办法，好吧mentor说这个api的对接已经进入排期了，他们在一步步的弄，而这个数据也不是至关重要，能收集多少收集多少就好了。懂了，先做别的。
下班后我又总感觉有点什么事没解决，于是就找了找相关的教程，outlook可以批量导出邮件的附件、excel的power query可以合并不同xls文件里面的多行内容到一个表格，成了，感谢开发者们，这是我第一次用技术实实在在的解放生产力，而这一切就发生在我眼前。</p>]]></content><author><name></name></author><summary type="html"><![CDATA[一切的开始，都源于我工作中突然冒出的一个念头：“既然工作都是由计算机来完成的，那我做的工作中很多的重复性的作业（比如重复的在某个时间段打开同样的应用执行同样的操作）是不是也能自动化呢？”]]></summary></entry></feed>