简介:一份围绕石油工程设计大赛单项组钻井工程赛项的培训PPT,面向参赛学生、指导教师及煤层气钻井工程技术人员,系统讲解直井与单翼多分支水平井钻完井工程设计的完整流程。内容以沁端区块实际案例为背景,涵盖井身结构设计、钻具组合、钻井液配比、HSE与经济评价等核心模块,并引用了《煤层气田开发方案编制规范》《井身结构设计方法》等行业标准,具有较强的规范性和参考价值。资源为单个pptx演示文稿,约1.95MB,共1个文件,适合用于赛前集训、方案对照和汇报讲稿准备。目前已有90人学习浏览。通过该PPT可快速掌握套管射孔完井、裸眼完井、穿针工艺联通水平井等设计要点,为参赛方案撰写或实际工程设计提供直观模板。
1. 石油工程设计大赛钻井工程培训资料:PPTX 不只是幻灯片
比赛季最常见的场景不是缺技术,而是缺一份能统一所有人认知的培训资料。同一个井队的 6 名队员手里,可能同时存在 3 个版本的「石油工程设计大赛单项组钻井工程培训资料.pptx」:一个只有封面,一个嵌着公式乱码,还有一个在教室投影上丢了半边版式。问题不在于内容是否权威,而在于这个文件从未被当成工程件来管理。
PPTX 本质上是一个 zip 包,内部是 XML、图片、主题和备注的集合。也就是说,钻井工程培训资料完全可以像代码一样做模板化生成、自动校验和版本比对。这套思路面向两类人:一类是替参赛队做技术支撑的 IT 工程师,另一类是打算用脚本管理教学课件的石油工程师。后者不需要精通 Python,照着命令执行就能显著减少赛前返工。
2. 钻井工程单项组培训大纲先行,再用 python-pptx 生成 PPTX
做培训资料最忌讳一上来就打开 PowerPoint 手动画页。钻井工程单项组的培训内容多且杂,先定「内容模型」,再写生成脚本,后面才能少返工。内容模型指的是把每个知识单元映射到一种页型:表格页、步骤页、图文页、公式页、案例页。页型决定你会用到 python-pptx 里的哪些 API,也直接影响后续修改成本。
2.1 钻井工程培训资料的 8 个模块与页型映射
钻井工程培训资料常见的 8 个模块如下。这里不追求一次覆盖全部赛题范围,而是给脚本一个稳定的信息结构。
| 模块 | 核心知识点 | 推荐页型 |
|---|---|---|
| 井身结构 | 套管层次、井眼尺寸、钻头直径 | 图 + 参数表 |
| 钻头选型 | PDC/牙轮、IADC 编码、进尺与机械钻速 | 参数表 + 案例数字 |
| 钻井液设计 | 密度、粘度、失水、固相含量 | 表格 + 公式 |
| 井控技术 | 溢流发现、关井程序、压井计算 | 步骤列表 + 公式 |
| 固井与完井 | 水泥浆设计、顶替效率、套管附件 | 图 + 检查表 |
| 钻机与设备 | 提升、旋转、循环系统 | 图 + 标注 |
| HSE 与应急 | 风险识别、应急联络、演练记录 | 要点列表 + 备注 |
| 历年赛题 | 赛题条件、设计思路、评分点 | 案例页 + 备注 |
这张表的价值在于:每个模块都能对应到一种可复用的幻灯片页型。「参数表」用add_table生成,「步骤列表」用文本框的段落实现,「公式」渲染成透明 PNG 再插入,「图 + 标注」则拆成图片层和文本框层。大纲确定后,生成脚本只需要遍历一个模块列表,就能批量产出整套课件。
2.2 用 python-pptx 生成统一标题页与目录页
有了大纲,先定全局画布。比赛场地常用 16:9 投影,老式 4:3 模板在宽屏上会左右留黑边,现场观感很差。python-pptx 的Presentation()默认套用内置模板,通常是 4:3 尺寸,所以第一步要改成 13.333 英寸 x 7.5 英寸。修改尺寸不只是改两个数字,模板里的版式可能自带背景和占位符,生成后仍然建议用 PowerPoint 实际打开检查一遍。
from pptx import Presentation from pptx.util import Inches, Pt from pptx.dml.color import RGBColor prs = Presentation() prs.slide_width = Inches(13.333) prs.slide_height = Inches(7.5) # 默认模板里 index 5 通常是“仅标题”版式,实际以 layout.name 为准 layout = None for lyt in prs.slide_layouts: if lyt.name == "Title Only": layout = lyt break if layout is None: layout = prs.slide_layouts[5] slide = prs.slides.add_slide(layout) slide.shapes.title.text = "石油工程设计大赛单项组钻井工程培训资料" box = slide.shapes.add_textbox(Inches(0.8), Inches(2.0), Inches(11.7), Inches(0.8)) tf = box.text_frame tf.text = "版本 V2.3 | 培训对象:钻井单项组 | 更新日期:2025" p = tf.paragraphs[0] p.font.size = Pt(14) p.font.color.rgb = RGBColor(0x40, 0x40, 0x40)lyt.name可能因为模板语言不同写成 "Title Only" 或「仅标题」,用循环查找比写死索引更安全。add_textbox(Inches(0.8), Inches(2.0), Inches(11.7), Inches(0.8))的四个参数分别是左、上、宽、高,单位是英寸;如果模板是公制,建议统一用Inches或Cm,不要混用。text_frame.text赋值的文本会成为第一个段落,之后直接修改paragraphs[0]的字体即可。
目录页同样可以用文本框逐行写。一般会用一个模块名列表循环生成,每行是「模块编号 + 模块名 + 页数」。这里注意一个细节:paragraphs[0]已经存在,第一项直接改写,后续项用add_paragraph(),否则文件里会多一个空行。
modules = ["井身结构", "钻头选型", "钻井液设计", "井控技术"] toc_box = slide.shapes.add_textbox(Inches(0.8), Inches(1.2), Inches(11.7), Inches(5.0)) tf = toc_box.text_frame for i, name in enumerate(modules): p = tf.paragraphs[0] if i == 0 else tf.add_paragraph() p.text = f"{i+1}. {name}" p.font.size = Pt(20)2.3 参数化写入钻头选型与钻井液性能表
表格是钻井工程资料里信息密度最高的页型。钻头选型、钻井液性能、固井水泥浆配方,几乎全是「井段、类型、数值、备注」的结构。用截图贴表虽然快,但比赛前设计参数一改就要重新截图,图片里的旧数字容易漏改。所以,凡是会被评委追问的参数,都用表格对象写入,而不是图片。
rows_data = [ ["井段(m)", "钻头类型", "钻井液密度(g/cm³)", "备注"], ["0-300", "牙轮钻头", "1.08-1.12", "一开"], ["300-1200", "PDC钻头", "1.12-1.18", "二开"], ["1200-2600", "PDC钻头", "1.18-1.25", "三开"], ] table_shape = slide.shapes.add_table( len(rows_data), 4, Inches(0.8), Inches(1.5), Inches(11.7), Inches(2.8) ) table = table_shape.table for r, row in enumerate(rows_data): for c, value in enumerate(row): cell = table.cell(r, c) cell.text = str(value) for paragraph in cell.text_frame.paragraphs: paragraph.font.size = Pt(12)add_table返回的是GraphicFrame,真正操作的是.table属性。行列数由rows_data直接决定,逻辑上不会越界。table.cell(r, c)返回单元格对象,给.text赋值时会自动生成或替换第一个段落;后面的循环是为了统一字号。没有显式设置列宽时,python-pptx 会平均分配总宽,如果某一列内容较长,可以单独设置table.columns[c].width = Inches(x);行高不需要精确控制,PowerPoint 打开时会按内容自动撑开。
参数化之后,每一口井的培训资料只是替换rows_data这个二维列表。井段、钻头型号、钻井液密度可以从 Excel 或 JSON 读取,脚本负责生成。教练说「二开要用牙轮钻头和 PDC 对比」,直接改数据重跑脚本,整套课件的对应表格页就全部更新。这就是把培训资料当成工程件管理的第一个落地步骤。
3. 公式、井身结构图与井控流程在 PPTX 里的正确落法
钻井工程培训资料绕不开公式,比如当量循环密度、压井计算公式。PowerPoint 里手动插入公式使用的是 OMML(Office Math Markup Language),界面操作没问题,但用 python-pptx 直接构造 OMML 很繁琐,容易写坏 XML。更稳的做法是把公式渲染成透明背景 PNG 再插入,代价是缩放时可能轻微发虚,所以渲染 dpi 要设到 300 以上。
3.1 用 matplotlib 渲染 ECD 公式并插入 PPTX
公式图的生成可以用 matplotlib 的 mathtext,它支持大部分 LaTeX 数学子集。下面这段代码把当量循环密度公式渲染成一张透明 PNG:
import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt formula = r"$ECD = \rho_m + \frac{P_{ann}}{0.052 \cdot TVD}$" fig = plt.figure(figsize=(5, 1.0)) fig.text(0.5, 0.5, formula, ha="center", va="center", fontsize=20) fig.savefig("ecd_formula.png", dpi=300, transparent=True, bbox_inches="tight") plt.close(fig) slide.shapes.add_picture( "ecd_formula.png", Inches(0.8), Inches(1.2), width=Inches(4.5) )matplotlib.use("Agg")是为了在无显示环境的服务器上也能出图,跑批量脚本时不会弹窗。fig.text的ha和va控制文本在画布内居中,fontsize=20是图片内部字号,插入 PPTX 后的视觉大小由width=Inches(4.5)决定。dpi=300保证缩放不虚,transparent=True让公式图融合进浅色背景。需要注意 mathtext 不支持复杂 LaTeX 环境,如果是多行推导式,建议用完整 LaTeX 工具链渲染。公式图插入后,最好在下方再加一个文本框说明每个符号含义,便于评委快速理解。
3.2 井身结构示意图:SVG 转 PNG 再插入
井身结构图是最容易被做成「截图贴上去」的元素,但它恰恰最需要保持比例准确。表层套管、技术套管、油层套管之间的位置关系,直接影响队员对井眼尺寸的记忆。常见的三种插法各有取舍:
| 插入方式 | 优点 | 缺点 |
|---|---|---|
| 直接插入 SVG | 矢量缩放无损、文件小 | 旧版 Office/LibreOffice 兼容性差,[Content_Types].xml需正确声明 |
| 用 Inkscape 转 PNG | 兼容性最好,可控制透明通道 | 改图需重新转换,占用空间稍大 |
| 用 python-pptx 原生绘制矩形 | 数据可参数化,后期改尺寸方便 | 复杂井身结构代码量很大 |
比赛前临时改图是常态,我一般用 Inkscape 命令行把 SVG 转成 300dpi 的 PNG,再插入幻灯片。
inkscape casing.svg \ --export-filename=casing.png \ --export-dpi=300 \ --export-background-opacity=0--export-filename是 Inkscape 1.x 的参数,旧版本叫--export-png,如果脚本在多台机器跑,先执行inkscape --version确认版本。--export-dpi=300控制位图采样密度,--export-background-opacity=0保留透明背景,这样插入任何模板都不会出现白底块。转换完成后再用add_picture插入,插入时最好显式指定width,否则 SVG 画布尺寸和 PowerPoint 默认显示尺寸可能不一致,把页面撑出边界。
3.3 井控关井程序的「步骤连续页」而不是动画
井控流程是培训资料里的关键内容,常见的教学页会做成动画:点击一次出现一步。但 python-pptx 没有公开的动画 API,手工往 slide XML 里塞动画标签很容易写坏文件。更可控的做法是「步骤连续页」:为每个步骤生成独立一页,当前步骤高亮,其余步骤灰色弱化。这样既能模拟逐步讲解,又方便截图、打印和手机翻页。
from pptx import Presentation from pptx.dml.color import RGBColor # prs 和 layout 沿用前面生成的变量 steps = ["发现溢流", "停泵停钻", "上提钻具至合适位置", "关闭防喷器", "记录立压和套压"] for idx, current in enumerate(steps, start=1): slide = prs.slides.add_slide(layout) slide.shapes.title.text = f"关井程序 第{idx}步" box = slide.shapes.add_textbox(Inches(0.8), Inches(1.4), Inches(8.0), Inches(3.0)) tf = box.text_frame for j, step in enumerate(steps, start=1): p = tf.paragraphs[0] if j == 1 else tf.add_paragraph() run = p.add_run() run.text = f"{j}. {step}" run.font.size = Pt(20) if j == idx: run.font.bold = True run.font.color.rgb = RGBColor(0xC0, 0x00, 0x00) else: run.font.color.rgb = RGBColor(0x99, 0x99, 0x99)外层enumerate(steps, start=1)控制生成多少页,内层enumerate控制每一页列出全部步骤。tf.paragraphs[0]是文本框架自带的首段,所以第一个步骤直接复用,其余通过add_paragraph()新增。每个段落里用add_run()创建 run,再分别设置粗体和颜色。当前步骤红色高亮,其他步骤灰色,队员翻页时能同时看到完整流程和当前重点。这种页型比动画更稳定,也更容易在比赛前做自动化校对。
4. PPTX 培训资料的自动校验与版本比对:比赛前必做
培训资料在提交前最怕三件事:页数不对、画幅比例不对、某个图片链接失效。PPTX 是 zip 包,用系统自带的unzip解包,可以直接绕开 PowerPoint 看内部结构。不要只信 PowerPoint 的页数显示,它以ppt/presentation.xml里的<p:sldIdLst>为准,而包里可能残留未被引用的slideN.xml,这类文件不会显示但会让包变大。
4.1 解包 PPTX,确认幻灯片数量与画幅
unzip -q 石油工程设计大赛单项组钻井工程培训资料.pptx -d pptx_check grep -o 'slide[0-9]*\.xml' pptx_check/ppt/_rels/presentation.xml.rels | sort -V grep -o 'sldSz cx="[0-9]*" cy="[0-9]*"' pptx_check/ppt/presentation.xml第一条命令把 pptx 解压到pptx_check目录,之后所有检查都在这个目录里做。第二条命令从presentation.xml.rels中提取实际被引用的幻灯片文件,sort -V让 slide2 排在 slide10 前面,避免字符串排序造成 slide10 紧跟 slide1。第三条命令查看画幅参数,cx和cy单位是 EMU,1 英寸等于 914400 EMU;常见 16:9 是cx="12192000" cy="6858000",4:3 则是9144000 x 6858000。如果这里出现别的值,比赛投影上很可能会被拉伸或留黑边。
提示:如果解包后没有
ppt/presentation.xml,说明这个文件不是标准 OOXML 产物,多半是 WPS 或其他工具生成的老格式,先另存为标准 .pptx 再处理。
4.2 用 python-pptx 检查标题重复和空白页
培训资料通常由多人分头编写,拼接后经常出现标题重复、只有标题没有正文、或者旧参数残留在正文里。与其肉眼翻页,不如写个脚本提取每页标题和正文字符数。
from pptx import Presentation from collections import Counter prs = Presentation("培训资料.pptx") records = [] for idx, slide in enumerate(prs.slides, start=1): title = "" if slide.shapes.title is not None: title = slide.shapes.title.text.strip() body_len = 0 for shape in slide.shapes: if shape.has_text_frame: text = shape.text_frame.text.strip() if shape is not slide.shapes.title: body_len += len(text) records.append((idx, title, body_len)) if not title: print(f"[WARN] 第{idx}页缺少标题") if body_len == 0: print(f"[WARN] 第{idx}页只有标题没有正文") titles = [r[1] for r in records if r[1]] for title, count in Counter(titles).items(): if count > 1: print(f"[WARN] 标题重复出现了{count}次:{title}")slide.shapes.title返回的是占位符类型为 title 的形状;如果页面用的是普通文本框而不是标题占位符,这里取不到标题,这是预期行为。正文长度统计排除了标题占位符,shape.has_text_frame同时过滤掉图片和图表,避免调用文本接口报错。Counter(titles)会统计空字符串,所以先用if r[1]过滤。这个脚本不修改原文件,只输出一份排错清单,适合提交前批量检查。
4.3 检查媒体文件、字体与自动修复
打开 PPTX 提示「已修复的部分」,大多数和媒体文件或主题文件损坏有关。用 zipfile 做一次空文件检查,比 PowerPoint 的修复弹窗更早暴露问题。
import zipfile with zipfile.ZipFile("培训资料.pptx") as z: for name in z.namelist(): if name.startswith("ppt/media/"): info = z.getinfo(name) if info.file_size == 0: print(f"[ERR] 空媒体文件: {name}") if info.file_size / 1024 / 1024 > 50: print(f"[WARN] 媒体文件过大: {name} {info.file_size/1024/1024:.1f}MB")namelist()返回包内全部文件路径,getinfo()拿到file_size和compress_size。空文件通常是原图删除后留下的占位文件,残留在包里会导致打开时自动修复。50MB 是经验阈值,钻井工程资料里如果嵌入了高清井史扫描件,单张图片可能在 10MB 左右;但超过 50MB 的图片放进课件,对比赛分享和现场打开都是负担。
字体方面,python-pptx 不能嵌入字体,PowerPoint 的「嵌入字体」功能会额外生成ppt/fonts/目录。如果评委电脑上没有目标字体,排版就会错乱。脚本里可以检查ppt/fonts/是否存在,或者统一把常用标题指定为微软雅黑、黑体这类 Windows 自带字体。检查项汇总如下:
| 校验项 | 检查方式 | 常见问题 |
|---|---|---|
| 幻灯片数量 | presentation.xml.rels里的 slide 引用数 | 残留未引用 slide 文件 |
| 画幅比例 | presentation.xml的sldSz | 4:3 和 16:9 混用 |
| 媒体文件 | ppt/media/下文件大小与 rels 引用 | 空文件、超大扫描件 |
| 字体 | 检查 run.font.name 与ppt/fonts/ | 字体缺失导致排版乱 |
| 标题重复 | python-pptx 遍历 shapes.title | 多人合并章节后重复 |
5. 把培训资料 PPTX 变成可检索的练习库:批量导出备注与要点页
培训资料往往只在赛前集中讲一遍,散会后队员想查「井控关井程序」在第几页,只能一页页翻。低成本的高价值技巧是:用 python-pptx 把每一页的标题、正文和演讲者备注全部导成一个 Markdown 文件。这个文件可以被grep、编辑器全局搜索、Obsidian 双链,也可以直接作为撰写赛题文档的素材库。
from pptx import Presentation from pathlib import Path def export_pptx_md(src: str, out_md: str) -> None: prs = Presentation(src) lines = [] for idx, slide in enumerate(prs.slides, start=1): title = "" title_shape = slide.shapes.title if title_shape is not None: title = title_shape.text.strip() lines.append(f"## 第 {idx} 页:{title}") body_parts = [] for shape in slide.shapes: if not shape.has_text_frame: continue if shape is title_shape: continue text = shape.text_frame.text.strip() if text: body_parts.append(text) if body_parts: lines.append("\n".join(body_parts)) if slide.has_notes_slide: notes = slide.notes_slide.notes_text_frame.text.strip() if notes: lines.append(f"> 备注:{notes}") lines.append("") Path(out_md).write_text("\n".join(lines), encoding="utf-8") export_pptx_md("石油工程设计大赛单项组钻井工程培训资料.pptx", "钻井培训_检索版.md")slide.has_notes_slide先判断是否存在备注页,避免直接访问notes_slide时抛错;notes_text_frame.text返回备注里的全部文本,换行会原样保留。shape is title_shape用对象身份判断,避免把标题文本重复写进正文区。表格内容不会出现在这里,因为has_table的 shape 没有text_frame,要继续导出表格需要额外读取shape.table的每个 cell。这个脚本已经能覆盖绝大多数培训页的正文和备注。
执行后直接搜索:grep -n "井控" 钻井培训_检索版.md,找到的不只是关键词,还有它所在页的标题和相邻内容。若想把每页转成 JSON 条目,只需把lines按##分割后写成列表。保留 Markdown 里的页标题原样,队员在手机上搜到某一节后,回到 PPTX 里用页码定位就不会因为标题被改写而找不到。
本文还有配套的精品资源,点击获取