Word成绩登记表解析:从.doc到结构化数据的工程化管道
简介这份成绩登记表文档面向中小学教师、班主任及教务管理人员用于日常记录与管理班级学生的语文学习成绩也可作为数据库设计、信息系统入门学习的参考素材。资源包共1个doc文件约153KB内容以表格形式呈现涵盖学号、姓名、平时成绩、期中效果、期末效果、学期评分、合计与平均分等字段可直接打印或二次编辑使用。文档结构清晰字段划分明确便于按学生逐条登记与统计也能帮助读者理解成绩数据从采集、存储到分析的基本流程为后续成绩统计、教学质量评估提供基础数据支撑。目前已有100人学习下载适合需要快速搭建成绩记录模板或研究简单数据表设计的用户参考使用。1. 成绩登记表(2).doc 背后的真实需求从一份“野生表格”到可复现的数据管道带过毕业设计或者做过教务系统对接的工程师大概率都遇到过这种文件成绩登记表(2).doc。文件名里的(2)是血泪经验——它意味着前面已经有过一版可能是格式被改乱了可能是数据对不上也可能是导师或教务又提了新要求。这个标题看着像一份普通文档但它背后藏着一个非常典型的工程问题如何把一份格式不固定、来源不可控的 Word 成绩表稳定地解析成结构化数据并且能重复跑、能校验、能追溯。它适合谁适合正在做教务数据迁移、毕业设计管理系统、成绩分析看板或者任何需要从 Word 文档里批量提取表格数据的人。核心痛点不是“读 Word”本身而是 Word 表格的合并单元格、空行、跨页断行、手动换行符这些玄学问题会让一个看似简单的解析脚本在真实文件上集体翻车。这篇笔记就按我实际处理这类文件的路径从选型、解析、清洗到校验把每一步的参数和坑讲清楚。2. 解析 .doc 成绩表的选型为什么不能直接上 python-docx2.1 .doc 与 .docx 的格式分水岭很多人拿到成绩登记表(2).doc第一反应是pip install python-docx然后发现报错Package not found或者读出来是空。原因很简单python-docx只认 OOXML 格式也就是.docx。而.doc是微软 97-2003 的二进制复合文档格式底层是 OLE 结构两者完全不是一回事。常见做法是先用 LibreOffice 做一次无头转换把.doc转成.docx再交给python-docx处理。这个转换步骤在 Linux 服务器上也能跑不需要装 Office。命令如下# 无头模式转换--headless 不弹界面--convert-to 指定目标格式 libreoffice --headless --convert-to docx --outdir ./converted 成绩登记表(2).doc逻辑说明--headless让 LibreOffice 以服务方式运行适合放在自动化脚本里--outdir指定输出目录避免污染原目录。参数上唯一需要注意的是如果服务器上同时跑了多个转换任务LibreOffice 的用户配置目录会冲突建议给每个任务指定独立的-env:UserInstallation参数。转换完成后./converted/成绩登记表(2).docx就可以被python-docx正常读取了。这一步的翻车点在于有些.doc文件本身已经损坏LibreOffice 会静默失败输出一个 0 字节的 docx。所以转换后必须检查文件大小小于 1KB 的直接标记为异常。2.2 读取表格的最小可用代码拿到.docx之后读取表格的核心代码其实很短但参数和边界处理才是重点from docx import Document doc Document(./converted/成绩登记表(2).docx) # 遍历所有表格doc.tables 是一个列表 for t_idx, table in enumerate(doc.tables): print(f 表格 {t_idx}行数 {len(table.rows)}列数 {len(table.columns)} ) for r_idx, row in enumerate(table.rows): # cell.text 会保留手动换行符 \n需要后续清洗 cells [cell.text.strip() for cell in row.cells] print(r_idx, cells)逻辑说明doc.tables返回文档中所有表格对象顺序与文档中出现的顺序一致。row.cells在遇到合并单元格时会返回重复的 cell 对象这是后面去重逻辑要处理的核心问题。参数上cell.text拿到的是纯文本但会保留 Word 里的手动换行符\n和多余空格所以.strip()只是第一步后面还要做更细的清洗。提示如果文档里表格是嵌套的doc.tables只返回顶层表格嵌套表格需要遍历 cell 内部的cell.tables。成绩登记表一般不会嵌套但遇到教务系统导出的复杂模板时要留意。3. 成绩表格清洗合并单元格、空行与学号校验的实战处理3.1 合并单元格的去重与填充Word 表格的合并单元格在python-docx里表现为同一行中多个列返回同一个 cell 对象或者同一列中多个行返回同一个 cell 对象。直接按行列索引取值会得到大量重复数据。处理策略是先按 cell 对象的_tc属性底层 XML 元素做唯一性判断再决定是横向合并还是纵向合并。def dedupe_row(row): 对一行内的合并单元格做去重保留第一个出现的值 seen set() result [] for cell in row.cells: tc_id id(cell._tc) # 用底层 XML 元素 id 判断是否同一个 cell if tc_id not in seen: seen.add(tc_id) result.append(cell.text.strip()) else: result.append() # 重复位置填空保持列对齐 return result逻辑说明cell._tc是 python-docx 内部指向 XML 元素的引用同一个合并单元格在不同行列位置返回的_tc是同一个对象所以用id()可以判断重复。参数上重复位置填而不是直接跳过是为了保持后续按列索引取值的稳定性——如果直接跳过列数会变后面按row[3]取学号就会错位。纵向合并的处理类似但需要在列方向上做一次扫描把空白单元格用上方最近的非空值填充。这一步在成绩表里很常见比如“班级”列合并后只有第一行有值下面全是空。3.2 学号与成绩的格式校验清洗完结构之后下一步是字段级校验。成绩登记表里最容易出问题的三个字段是学号、姓名、成绩。学号通常是 8 到 12 位数字但 Word 里经常被存成文本后带上了不可见字符姓名可能有空格成绩可能是“优秀”“良好”这种等级制也可能是数字但带了“分”字。import re def clean_student_id(raw): 提取纯数字学号去掉所有非数字字符 digits re.sub(r\D, , raw) if 8 len(digits) 12: return digits return None # 长度不对标记为异常 def clean_score(raw): 把成绩统一成 float等级制返回 None 并单独记录 raw raw.strip().replace(分, ) try: score float(raw) if 0 score 100: return score except ValueError: pass return None # 等级制或异常值逻辑说明re.sub(r\D, , raw)把所有非数字字符干掉能处理“2021 001234”这种带空格的学号。参数上学号长度限制在 8 到 12 位是常见教务系统的约束如果你们学校是 10 位改成10 len(digits) 10即可。成绩校验里0 score 100是硬边界超出范围的直接标记异常不要静默截断——截断会让原始数据失真后面查都查不回来。注意等级制成绩优秀/良好/中等/及格/不及格不要强行映射成数字除非教务明确给了映射规则。我一般会单独存一列score_type标记是数字还是等级后续分析时再决定怎么处理。3.3 空行与跨页断行的识别Word 表格里经常夹杂空行尤其是从 PDF 转过来或者手动调整过格式的文件。空行的特征是整行所有 cell 的text.strip()都为空。但要注意有些行看起来空实际上某个 cell 里有一个空格或换行符所以判断条件要用strip()之后的结果。跨页断行是另一个坑Word 在分页处会把一行拆成两行显示但底层 XML 里可能还是同一行也可能真的变成了两行。判断方法是看学号列——如果某行学号为空但其他列有值很可能是上一行的续行。处理策略是遇到学号为空且姓名也为空的行直接跳过遇到学号为空但姓名或成绩有值的行向上合并到最近的有效行。def is_empty_row(cells): 判断是否为空行所有单元格 strip 后都为空 return all(c.strip() for c in cells) def merge_continuation(rows): 把续行合并到上一行学号为空但其他列有值时触发 merged [] for row in rows: if merged and not row[0] and any(row[1:]): # 学号列为空但姓名或成绩有值合并到上一行 for i in range(1, len(row)): if row[i]: merged[-1][i] (merged[-1][i] row[i]).strip() else: merged.append(row) return merged逻辑说明merge_continuation的核心判断是not row[0] and any(row[1:])即学号列为空但其他列有内容。合并时用空格拼接避免姓名被截断。参数上如果你的表格学号不在第一列把索引0改成实际列号即可。4. 批量处理与输出从单文件到目录级管道的工程化4.1 目录扫描与文件过滤实际场景里不会只有一个成绩登记表(2).doc而是一个目录下几十个类似文件命名可能是成绩登记表(1).doc、成绩登记表(3).doc、XX班成绩.doc。批量处理的第一步是过滤出真正的 Word 文件排除临时文件~$开头和已经转换过的文件。import os from pathlib import Path def scan_doc_files(root_dir): 扫描目录下所有 .doc 文件排除临时文件和已转换的 doc_files [] for p in Path(root_dir).rglob(*.doc): # 排除 Word 临时文件~$ 开头和已转换的 docx if p.name.startswith(~$): continue doc_files.append(p) return sorted(doc_files)逻辑说明rglob(*.doc)会递归扫描子目录适合按班级分文件夹存放的场景。排除~$开头的文件是因为 Word 打开文档时会生成临时文件这些文件不是真实数据。参数上sorted()保证处理顺序稳定方便复现和对比结果。4.2 转换、解析、清洗的串联管道把前面的步骤串起来形成一个可重复执行的管道。每个文件独立处理单个文件失败不影响其他文件失败信息记录到日志里。import subprocess import json from datetime import datetime def process_one_doc(doc_path, output_dir): 处理单个 .doc 文件转换 - 解析 - 清洗 - 输出 JSON result {file: str(doc_path), status: ok, rows: [], errors: []} # 步骤1转换 converted Path(output_dir) / (doc_path.stem .docx) cmd [libreoffice, --headless, --convert-to, docx, --outdir, str(output_dir), str(doc_path)] subprocess.run(cmd, capture_outputTrue, timeout60) if not converted.exists() or converted.stat().st_size 1024: result[status] convert_failed result[errors].append(转换后文件不存在或过小) return result # 步骤2解析表格 doc Document(str(converted)) if not doc.tables: result[status] no_table result[errors].append(文档中未找到表格) return result table doc.tables[0] # 默认取第一个表格 raw_rows [dedupe_row(row) for row in table.rows] # 步骤3清洗 cleaned [] for row in raw_rows: if is_empty_row(row): continue sid clean_student_id(row[0]) if row else None if sid is None: result[errors].append(f学号异常: {row[:3]}) continue cleaned.append({ student_id: sid, name: row[1].strip() if len(row) 1 else , score: clean_score(row[2]) if len(row) 2 else None, }) result[rows] cleaned return result逻辑说明subprocess.run调用 LibreOffice 转换timeout60防止某个损坏文件卡死整个管道。转换后检查文件大小小于 1KB 视为失败。解析时默认取第一个表格如果文档里有多个表格需要根据表头内容判断哪个是成绩表。清洗阶段学号异常的记录到errors里但不中断保证其他行能正常输出。参数上output_dir建议按日期分目录比如./output/20250101/这样每次跑的结果不会互相覆盖方便回溯。输出格式用 JSON 而不是 CSV是因为 JSON 能保留嵌套结构和错误信息后续导入数据库或做分析都更方便。4.3 输出结果的结构化存储最终输出建议用 JSON Lines 格式每行一个文件的结果方便用jq或 pandas 直接读取def save_results(results, output_path): 把处理结果写成 JSON Lines每行一个文件 with open(output_path, w, encodingutf-8) as f: for r in results: f.write(json.dumps(r, ensure_asciiFalse) \n)逻辑说明ensure_asciiFalse保证中文姓名正常显示不会被转成\uXXXX。JSON Lines 的好处是追加写入方便处理到一半中断了也不会丢失已完成的结果。参数上如果后续要用 pandas 分析直接pd.read_json(output_path, linesTrue)即可。5. 避坑与排查成绩登记表解析中最容易翻车的 5 个点5.1 转换后表格结构错乱现象.doc转成.docx后原本 5 列的表格变成了 8 列或者合并单元格全部散开。原因LibreOffice 对某些老版本 Word 的表格布局兼容性不好尤其是用了“自动调整”和“固定列宽”混排的表格。解决换用--convert-to docx:MS Word 2007 XML指定输出格式或者先用 Word 手动另存为.docx再处理。如果文件量不大手动另存是最稳的。批量场景下可以在转换后加一步列数校验如果列数超过预期标记为异常人工介入。5.2 学号被识别成科学计数法现象学号202100123456在 Word 里显示正常但读出来变成2.02100123456e11。原因Word 表格里学号被存成了数字格式python-docx读取时按浮点数处理。解决在clean_student_id里先判断原始文本是否包含e或E如果是用Decimal还原from decimal import Decimal def restore_scientific(raw): 还原被科学计数法表示的学号 if e in raw.lower(): return str(Decimal(raw).to_integral_value()) return raw参数上Decimal比float精度高能准确还原 12 位以内的学号。超过 15 位的数字Decimal也会丢精度但学号一般不会那么长。5.3 姓名中的生僻字变成方框现象解析出来的姓名里生僻字显示为□或乱码。原因.doc文件用的字体不支持生僻字或者转换过程中编码丢失。解决这种情况在源文件层面就丢了信息解析阶段无法恢复。处理策略是标记出来让业务方对照原始文件人工补录。可以在输出里加一个name_has_unknown字段检测□和?字符。5.4 多个表格时取错了表现象文档里第一个表格是“课程信息”第二个才是“成绩登记”代码默认取了第一个结果全是课程名。原因doc.tables[0]只取第一个表格没有做表头判断。解决遍历所有表格检查第一行是否包含“学号”“姓名”“成绩”等关键词def find_score_table(doc): 找到包含学号/姓名/成绩表头的表格 keywords {学号, 姓名, 成绩} for table in doc.tables: if not table.rows: continue header [cell.text.strip() for cell in table.rows[0].cells] if keywords.issubset(set(header)): return table return None参数上keywords可以根据实际表头调整比如有些表用“分数”而不是“成绩”加进去即可。5.5 并发转换时 LibreOffice 卡死现象批量处理时跑到第 10 个文件左右LibreOffice 进程卡住不退出后续文件全部超时。原因LibreOffice 的用户配置目录被多个进程同时占用导致死锁。解决给每个转换任务指定独立的UserInstallation目录libreoffice --headless -env:UserInstallationfile:///tmp/lo_profile_$$ \ --convert-to docx --outdir ./converted 成绩登记表(2).doc$$是当前进程 PID保证每个任务用不同的配置目录。代价是每次转换会多花一点时间初始化配置但稳定性大幅提升。如果文件量特别大建议用队列串行处理不要并发。6. 进阶技巧用表头映射和校验规则让管道自己发现异常前面讲的都是“能跑通”的层面但真实项目里跑通只是第一步。成绩数据一旦错位后续的绩点计算、排名、报表全是错的而且很难查。我一般会在管道里加两层保险表头映射和校验规则。表头映射的思路是不硬编码列索引而是根据表头文字动态确定每列的含义。这样即使不同班级的表格列顺序不一样也能正确解析。HEADER_MAP { 学号: student_id, 姓名: name, 成绩: score, 分数: score, 班级: class_name, } def build_column_index(header_row): 根据表头文字建立列索引映射 col_idx {} for i, cell in enumerate(header_row): text cell.text.strip() if text in HEADER_MAP: col_idx[HEADER_MAP[text]] i return col_idx逻辑说明HEADER_MAP把常见表头文字映射到统一字段名build_column_index返回{student_id: 0, name: 1, score: 2}这样的字典。后续取值用row[col_idx[student_id]]不再依赖固定列号。参数上如果表头有“平时成绩”“期末成绩”这种细分可以扩展HEADER_MAP把不同列映射到不同字段。校验规则层我一般会加三条硬规则学号在班级内唯一、成绩在 0 到 100 之间、姓名不为空。任何一条不满足就把这行标记为suspect输出到单独的文件里不进入主数据。def validate_rows(rows): 校验数据返回 (valid, suspect) valid, suspect [], [] seen_ids set() for row in rows: errors [] if row[student_id] in seen_ids: errors.append(学号重复) if row[score] is not None and not (0 row[score] 100): errors.append(成绩越界) if not row[name]: errors.append(姓名为空) if errors: row[errors] errors suspect.append(row) else: seen_ids.add(row[student_id]) valid.append(row) return valid, suspect逻辑说明seen_ids在循环中累积已出现的学号重复的进入suspect。成绩越界和姓名为空同样标记。参数上suspect文件建议保留原始行号和错误原因方便人工核对。这套管道跑下来一个 50 文件的目录大概 3 到 5 分钟能处理完其中大部分时间花在 LibreOffice 转换上。如果追求速度可以把转换步骤换成 Windows 上的 COM 接口调用 Word但那样就绑定了 Windows 环境服务器上跑不了。我一般还是用 LibreOffice稳字优先。最后说个我自己的习惯每次处理完一批成绩表我都会把suspect文件打开看一眼哪怕只有几行。因为成绩数据的错误往往不是技术问题而是源文件本身就有问题——比如老师手动改过某个学生的分数但没保存对或者复制粘贴时串了行。这些错误只有人眼能发现管道只能帮你缩小范围。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

个人AI助手缓存系统实战:用语义缓存降低延迟与成本

个人AI助手缓存系统实战:用语义缓存降低延迟与成本

1. 为什么一个AI助手需要先解决"记得快"的问题先交代一下背景:这是"个人AI助手"系列的第7篇实践记录,前面几个阶段已经把这台助手从"能调API的大模型客户端"逐步做到了"有记忆、有工具调用能力的Agent"。阶段1打…

2026/10/13 19:37:19 阅读更多 →
仓库管理系统数据库设计实例:从课程设计到触发器实现

仓库管理系统数据库设计实例:从课程设计到触发器实现

简介:这份PDF面向数据库课程设计的学生与需要完成仓库管理系统建模的开发者,围绕需求分析、系统功能划分、数据流图、数据字典、概念结构设计、逻辑与物理结构设计及可行性分析展开,帮助读者掌握从业务需求到关系模型的完整设计思路。资源包为…

2026/10/13 19:37:19 阅读更多 →
传智健康PRD文档1:从需求到可执行工程资产的落地实践

传智健康PRD文档1:从需求到可执行工程资产的落地实践

简介:传智健康PRD文档1是一份面向健康管理系统产品设计与开发人员的需求说明书,适合产品经理、后端开发及医疗信息化学习者参考,用于理解健康管理平台从需求定义到功能落地的完整思路。压缩包内共1个docx文件,约890KB,…

2026/10/13 19:36:17 阅读更多 →

最新新闻

从零构建Agent技能库:技能层设计、动态装载与回归测试的工程实践

从零构建Agent技能库:技能层设计、动态装载与回归测试的工程实践

直接做Agent应用的人,这两年应该都有同感:单个Agent的对话能力已经不是瓶颈了,真正拉开差距的是Agent能不能稳定地调用外部能力、按流程完成任务。我最近在整理和重构一个内部项目,名字就叫“agent-skills”,本质上是一…

2026/10/13 20:34:36 阅读更多 →
基于MATLAB的脑电功率谱与多尺度熵分析工具箱实战解析

基于MATLAB的脑电功率谱与多尺度熵分析工具箱实战解析

简介:面向脑电信号分析的多尺度熵计算MATLAB代码包,主要服务神经科学、生物医学工程等领域的科研人员与工程师,可用于处理多通道EEG数据,完成从二进制文件读取、预处理、多尺度熵计算到频谱分析、批量统计的完整流程。代码由杨博士…

2026/10/13 20:34:36 阅读更多 →
用litellm搭建统一模型网关,解决多模型接入难题

用litellm搭建统一模型网关,解决多模型接入难题

1. 做了个模型网关,解决了我最头疼的多模型接入问题先交代一下背景。上个月要给一个内部工具接大模型能力,一开始需求很简单:调一个对话接口,把结果返回给前端就行。结果做着做着就失控了。产品那边今天说换某家的新模型试试&…

2026/10/13 20:34:36 阅读更多 →
吃透OpenCV类型宏CV_8UC3:位深通道与内存布局

吃透OpenCV类型宏CV_8UC3:位深通道与内存布局

写这篇文章的起因,是最近又看到不少人在图像处理群里问“为什么Mat创建老报错”“为什么读进来的图片和我心里想的不一样”,最后发现根子都出在同一个地方:没搞懂OpenCV的类型宏,比如CV_8UC3到底代表什么。这玩意儿看着像一串乱码…

2026/10/13 20:34:36 阅读更多 →
YOLOV4后处理解析:从NMS到DIOU-NMS的原理与Python实现

YOLOV4后处理解析:从NMS到DIOU-NMS的原理与Python实现

YOLOV4学习系列写到第三篇,前面咱们拆过CSPDarknet53骨干结构,聊过SPP和PANet的Neck设计,今天终于轮到推理阶段的最后一道工序——非极大值抑制。NMS这个词很多同学早就不陌生了,检测模型调试、比赛刷分、论文复现都绕不开它。但你…

2026/10/13 20:34:36 阅读更多 →
Zbrush次世代角色头部雕刻全流程:从结构认知到皮肤纹理

Zbrush次世代角色头部雕刻全流程:从结构认知到皮肤纹理

做次世代游戏角色,头部雕刻永远是绕不开的坎。常有人说,身体可以靠布料和铠甲遮,脸却始终暴露在玩家眼前,Zbrush头部细节雕刻直接决定了角色能站上哪个档次。这些年我经手过不少项目,也从大量废案里踩出一些实用的新技…

2026/10/13 20:33:28 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →