首页 文章 精选 留言 我的

精选列表

搜索[WorkBuddy],共4325篇文章
优秀的个人博客,低调大师

#WorkBuddy# #AI办公# 卷影追踪第三天:水位只掉 0.17GB,昨天抓到的活文件定格在 1.21GB——下行收敛了

本文是「C 盘消耗归因」系列的第六篇,也是卷影追踪的第三日。前情:11/07 破案(-1.63GB 的真凶是 System Volume Information 里的卷影差异区),11/08 第二日复扫(水位再掉 0.80GB,与卷影增量 0.71GB 对上,vssadmin 显示 3.29GB 上限封顶)。今天回答上一期留下的悬念:淘汰发生了吗?水位止跌了吗?

优秀的个人博客,低调大师

WorkBuddy 复盘:后台明明发成功 6 篇,本地台账一行都没有——根因是把记账挂在了命令行开关上

日期:2026-10-24。这是一个典型的「事实已发生、账本却不知道」案例,记下来给所有做自动化流水线的人提个醒。 ## 现象 头条自动发布通道跑了十几天后做回读对账,发现一个怪现象:后台(头条号文章管理页)明明有 10-17、10-18、10-20、10-22 共 6 篇文章带真实展现和阅读数据,但本地发布台账里「最近发布」停在 10-20,`已发布/头条已发/` 目录里也没有这 6 篇的归档。更糟的是,下游的断流检测读台账后,把一条实际活着的线误判成了「断流 🔴」,触发了错误的告警处置。 ## 根因:一行 if 排查 `tt_publish.py`,真凶就一行: ``` if "--auto" in sys.argv or PUBLISH_ONLY: record_ledger(title) # 记台账 archive_draft(f) # 稿件移入已发布 ``` 「记台账 + 归档」这两个**后置动作**被整段包在了 `--auto` 这个命令行开关的判断里。意思是:只有走全自动路径发布才会留痕;而手动补发、`--fill` + `--publish-only` 这类分步路径,页面确认发布成功后直接结束——**发布这个客观事实发生了,但记账代码从来没被调用**。 这违反一条很朴素的分工原则:**事实记录不应该依赖「通过哪条路径做成这件事」**。发布成功是一个客观结果,记账/归档是它的影子,影子的触发条件应该是「结果出现」,而不是「走路 A 还是走路 B」。 ## 修法 把记账解耦出开关: ``` if published_ok: # 只看结果,不看路径 try: record_ledger(title) archive_draft(f) except Exception as e: log(f"ledger failed but published: {e}") # 归档失败不影响「已发布」这个事实 ``` 注意两点:一是即使记账代码本身出错,也不能倒过来说「发布失败」——事实与记账分层,记账挂了记记账的错;二是所有包在 `if :` 里的后置动作都值得问一句:**不带这个开关跑的时候,这一步该不该做?** ## 连带的两个坑(同一批排查时挖出来的) **坑 1:后台发布日期被当噪音跳过。** 补账时需要每篇的真实发布时间。后台列表页的结构是「标题 → 日期行(形如 `10-12 09:22`)→ 已发布 → 展现/阅读」,而解析脚本的噪音过滤正则把孤立的短日期行一并过滤掉了。结果就是:数据明明在页面文本里,解析器却拿不到,只能靠猜——而猜日期等于编数据。修法是给日期行加一个「向上 N 行内贴着『已发布』状态」的定位规则,抓不到就返回空串,绝不猜。 **坑 2:「最近发布」用文件行序取值。** 看板的 `load_toutiao()` 每读一行台账就覆盖一次「最近发布」变量,等于取的是**文件最后一行**。历史补账是往中间插行的,行序不等于时间序,于是 10-23 的新记录被 10-22 的旧记录盖住,页面上「最近发布」和「今天已发 ✔」两张卡自相矛盾。修法是抽一个 `pick_latest()`,按日期字段取最大值,而不是按读取顺序。 ## 三条可以带走的结论 1. **事实与记账分层**:成功判定、事实落盘、账本更新是三件事,后两件不许挂在入口开关上。 1. **凡是要猜的日期,宁可留空**:原始文本里找不到就写「读不到」,不要用推定值填账。 1. **单值汇总别依赖文件行序**:补记、追加、乱序写入都会让它指向错行,按字段取最大值才稳。 这次 6 篇的漏账已用后台真值补齐,不是推定值。下游误判的告警也随台账修复自动纠正。

优秀的个人博客,低调大师

#WorkBuddy# 近 700 页乱序扫描件 → 一份可直接交付的资料汇编:8 个坑、3 条铁律与完整代码思路

> 一个看起来"只是把 PDF 拼起来"的任务,实际做下来我踩了 8 个坑——有的非常隐蔽,静默发生、不报错,直到交付前才被发现。本文把整体工作流、技术方案与全部踩坑记录写出来,代码思路完整给出,希望能帮你少走弯路。全文已脱敏,不含任何可识别的企业、客户、人员、项目编号与产品参数信息。 --- ## 目录 - 一、任务背景:一堆"不可检索"的扫描件 - 二、最终成果 - 三、整体工作流:数据与代码分离 - 四、8 个坑,逐个拆 - 五、沉淀出的 3 条硬规则 - 六、几个工程小技巧 - 七、脱敏说明与合规声明 - 八、总结 --- ## 一、任务背景:一堆"不可检索"的扫描件 我手上有一批**机械制造质量资料**,来源五花八门: - 扫描件(有的是照片级扫描、没有文本层;有的带 OCR 层) - 矢量电子文档(PDF / DOCX 导出) - 页面尺寸、方向都不统一:有横版有竖版,还有整页倒置 180° 的 要求是:**按一份已有计划的序号,把这些资料组织成一份"可交付"的汇编 PDF** —— 要有封面、编制说明、目录、连续页码、书签,还要在每节左上角标注"序号 + 页码",并在部分页面上**框选**出关键数据行。 听起来像"拼 PDF",但真正做下来,难点全在**对位**和**可追溯**上。 --- ## 二、最终成果 |项目|结果| | --- | --- | |汇编成品|696 页 / 68 个书签| |内部结构|10 个大节 + 13 个子节| |页面元素|自动连续页码;页眉公司抬头 Logo;逐节序号标注| |数据定位|44 页红框框选;5 页方向校正(含整页倒置)| |资料整理|200+ 个文件按序号归位,零删除| |磁盘占用|从 7.5 GB 精简到 1.2 GB| --- ## 三、整体工作流:数据与代码分离 核心思路只有一句话:**数据与代码分离,配置驱动**。 ![](https://developer.qcloudimg.com/http-save/yehe-8553481/541a27d2cb9ef072f006e7f39c215f6d.png) **关键设计**:红框规则、旋转页、抽取页全部外置为配置文件;生成脚本里**不含任何业务数据**。改配置就能全局重新生成,不必改动一行生成脚本。 数据源长这样(伪代码): ``` 节定义 = [序号, 名称, 层级, 计划号, 控制点, 状态, 要求, 证据列表] 证据项 = 普通页嵌入(起止页) 或 抽取页(源文件 + 页号 + 备注) ``` --- ## 四、8 个坑,逐个拆 ![](https://developer.qcloudimg.com/http-save/yehe-8553481/1a8c60085398aa4d368dd9a5fb2c6bfb.png) ### 坑 1:书签页码整体少 1 页 **现象**:点书签跳到第 168 页,内容其实在第 169 页。 **根因**:0-based 与 1-based 混用。标注和页映射都写了 `front + idx + 1`,唯独书签漏了 `+1`。 **教训**:跨模块的索引换算,**只在一处定义**,其他所有地方引用它。 ### 坑 2:红框框错行 **现象**:某页本该框第 2 行,却框到了第 3 行。 **排查**:把程序检测出来的"表格行边界线"直接画到页面上目视——发现该页检出了 **14 条线**(尾部多了一条表格外线)。 **真实根因**:表格**第 1 行常常是双行标注**,行高比常规行大 30%,而等距筛选的阈值设成了"中位行距 × 0.30",正好卡在临界点上。这一页失败后就回退到固定几何常量,于是整体偏移一行。 **解决**:阈值放宽到 `× 0.45`;同时改成**多组参数依次重试**,只有第一组失败才启用备选——这样已正确的页面零回归。 ``` PARAMS = [(150, 0.22), (205, 0.20), (205, 0.14), (210, 0.10)] for gray, frac in PARAMS: result = detect_once(page, gray, frac) if result: return result ``` ### 坑 3:改文件名 → 配置全部失效(最惨的一个) **现象**:整理文件(重命名)后重新生成,页数完全正确,但**红框从 44 页变成 0 页**。 **根因**:红框配置的 key 是**源文件名**: ``` {"某零件表.pdf#3#6.3": {"groups": [{"rows": [6], "label": "割齿"}]}} ``` 构建时用 `os.path.basename(path)` 拼 key 去查。文件一改名,46 条 key **全部失配**,于是红框静默消失、不报任何错。 **教训(血泪)**: - 以**文件名为键**的配置,重命名文件必须同步改 key; - 引用**常量/变量**的配置(如按路径取页)会自动跟随,不受影响; - 重命名后必须**重新生成并校验**。我这次就是靠"红框页数 = 0"这个断言发现的。 ### 坑 4:编号和内容对调了 **现象**:整理完重新生成,总页数 576 → 575,少了 1 页。 **根因**:改写文件路径时,我按"文件名的字面含义"推断编号,把同组的两项(力学性能 / 金相组织)**弄反了**。实际编号顺序和直觉顺序相反。 **怎么发现的**:**像素比对**——把两个文件逐页渲染成灰度图做相关性计算,7 组比对相似度全是 **1.0000**,确认是同一份文件,于是按正确编号修正,页数恢复 576。 **教训**:整理资料时,"编号 ↔ 内容"的对应关系**必须实测**,不要按命名直觉推断。像素指纹是个便宜又可靠的手段。 ### 坑 5:引用悬空——标注说"截取自某处",但那里根本没有 **现象**:正文抽取页的角标写着"截取自 10.3.4 过程检验记录",但当资料被新版替换后,该页在该节里**已经不存在了**。对审核方来说这是硬伤:按角标去查,查不到。 **解决**:建立**引用闭包校验**——程序遍历所有"截取"类引用,逐个检查: > 来源(文件名 + 页号)是否真实存在于目标节的页段范围内? ``` for section in SECTIONS: for ev in section.evidences: if ev.note.startswith("截取自"): target = parse_target(ev.note) assert (ev.source_basename, ev.page) in provided_pages(target) ``` **成效**:一次性查出 4 类悬空,当场修复 2 类,剩余 3 处明确列出待决。这个校验建议所有做资料汇编的人都用上。 ### 坑 6:同一零件两张表,行号差 1 **现象**:某零件有"首件表"和"批量表"两张记录表,同一个尺寸在两张表里的**行号不一样**。 **根因**:批量表少了一行重复项,导致后续行号整体前移 1。而且三张表的序号编排还各不相同。 **解决**:**逐页渲染 + 裁切序号列放大目视**,逐页确定行号映射。三张表三种规则,绝不能套用。 **教训**:自动检测在这些"版式相近但细节不同"的扫描页上不够稳,**目视放大核对**是最可靠的兜底。 ### 坑 7:双面打印,封面不能落在反面 **需求**:导出打印稿时,每份检测报告的封面必须落在**正面(奇数页)**;某些分节页要**独占一张纸**(背面留白)。 **做法**: ``` for page in pages: if page.is_report_cover and (pos + 1) % 2 == 0: add_blank_page(size=page.size) # 先补一页空白 add(page) pos += 1 ``` **结果**:7 份报告封面全部落在第 7 / 13 / 19 / 25 / 31 / 37 / 43 页(都是正面)。 ### 坑 8:目标文件被占用 **现象**:`os.replace()` 报 `WinError 5 拒绝访问`——PDF 正被预览窗口打开。 **解决**:先写 `.tmp` 再原子替换;替换失败就另存带时间戳的文件,再用 `copyfile` 覆盖内容。 **⚠️ 一个隐藏大坑**:内容覆盖成**功后,已经打开的窗口不会自**动刷新,用户看到的还是旧版。验证时必须用** 修改时间 + 文件哈希 + 首**页文本 三重**确认,不能只看**文件名。 --- ## 五、沉淀出的 3 条硬规则 ### 1. 引用必达(闭包校验) 任何"截取自 X"的标注,来源必须能被程序验证真实存在。 ### 2. 改名即改键 以文件名为键的配置,重命名后必须同步;改完必须重新生成 + 校验。 ### 3. 编号 ↔ 内容必须实测 不按命名直觉推断对应关系。验证手段优先级: ``` 像素指纹比对 > 结构校验(页数/书签/元素计数)> 目视抽查 > 文件名推断 ``` --- ## 六、几个工程小技巧 |场景|做法| | --- | --- | |中英混排数字间距怪|中文字体用 CJK 字体、ASCII 单独用西文字体分段渲染| |标注压住扫描件上的二维码|只在贴合文字处铺小白底,不铺整条白条| |长任务中断|后台任务 + 日志落盘,避免前台超时| |大批量文件搬运|同盘用 os.rename(快),跨盘用 shutil.move| |破坏性操作|先备份、先列清单、逐批校验,只移动不删除| |工具自动重跑|命令被"提权重跑"时会产生重复日志,以最终磁盘状态为准复核| --- ## 七、脱敏说明与合规声明 本文已做完整脱敏,替换规则如下: |原信息类型|脱敏后| | --- | --- | |客户名称、公司名称|「某船舶配套企业」「我方公司」| |产品型号、图号、规格参数|「某型液动执行器」| |项目编号、内部表单编号|删除或写为「内部编号」| |零部件具体名称|「某盘类件」「某轴类件」等通用表述| |人员姓名、机构全称|删除| |具体尺寸、公差、试验数据|删除(只保留方法论)| |具体日期|相对表述| |文件路径|结构示意| **脱敏原则**: 1. **最小必要**——只保留方法论与通用技术,不保留任何可定位到具体项目/客户/人员的信息; 1. **不可反推**——任何单条信息都不足以反推出主体; 1. **一致性**——同类信息统一替换为同一代号,避免交叉比对; 1. **等同公开物**——脱敏后内容等同于一篇通用技术教程。 **合规声明**:内容为原创,无敏感信息、无商业机密、无第三方版权内容。 --- ## 八、总结 这个任务最大的收获不是"拼出了一份 PDF",而是: > **资料类工作的质量,取决于"可追溯"三个字。** 每一页从哪来、每个标注指向哪、每次改动影响了什么——这些必须能被程序验证,而不是靠记忆和目测。 如果你也在做类似的资料整理 / 汇编工作,欢迎在评论区交流。上面这些坑,能少踩一个是一个。

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册