1. 探矿业务里的数据清洗到底难在哪干了七八年地质信息化我越来越觉得探矿这行的数据整理工作本质上是在跟一堆“历史遗留问题”较劲。你手上拿到的资料可能是八十年代手写后扫描的钻孔柱状图可能是九十年代用老版本Word敲出来的地质简报也可能是某个项目组临时用网页后台导出的化验数据表。格式五花八门编码千奇百怪最要命的是——这些资料里藏着真正值钱的东西品位、坐标、岩性描述、构造产状。RAG检索增强生成这套东西刚火起来的时候我第一反应就是这玩意儿要是能把我们那堆老资料盘活找矿效率能翻倍。但真动手做才知道RAG的上限不取决于模型多强而取决于你喂进去的文本有多干净。探矿业务的数据清洗跟互联网上那种爬网页、洗评论完全不是一回事。它有几个非常要命的特征专业术语密度极高“矽卡岩型铜钼矿”“蚀变分带”“激电异常”数值精度要求苛刻坐标错一位、品位差一个数量级结论就完全反了而且文档结构极其混乱表格套表格、公式混正文、扫描件带手写批注。我见过太多团队模型选的是顶配向量库搭得漂漂亮亮结果检索出来的东西驴唇不对马嘴。问题八成出在清洗环节。TXT、Word、PDF、网页这四种载体在探矿业务里各有各的坑下面我按自己踩过的顺序一个一个拆开讲。2. 四种数据源的清洗策略与实操拆解2.1 TXT文件看着最简单编码和结构最坑人TXT在探矿资料里通常出现在两个地方一是老仪器的导出数据比如激电仪、磁力仪的原始读数二是从各种系统里导出的化验台账。很多人觉得TXT最好处理直接读进来就行。我一开始也这么想直到有一次把一批钻孔测斜数据喂进去检索出来的倾角全是乱码。问题出在编码上。探矿行业的TXT文件GBK、GB2312、UTF-8、甚至带BOM的UTF-8都有还有从老DOS系统里导出来的用的是GBK的变体。你如果不做编码探测直接按UTF-8读中文全变问号数字倒是没事——但数字和中文混在一起的时候整个字段就废了。我的做法是先用chardet做编码探测然后统一转成UTF-8。这里有个细节不要相信chardet的置信度低于0.8的结果那种情况多半是文件里中英文混杂比例特殊得手动指定。转完之后还要处理换行符。Windows导出的TXT是\r\nLinux是\n老Mac是\r。统一成\n之后再做分列。分列才是真正的重头戏。探矿TXT的列分隔符有制表符、逗号、分号、竖线还有用连续空格对齐的。连续空格这种最恶心因为岩性描述里本身就有空格。我的经验是先看前20行人工判断分隔模式然后写针对性的正则。比如化验台账通常是“样品编号 品位 长度 岩性”用\s{2,}切分比用单个空格稳得多。注意TXT清洗完一定要做一次“数值回验”。把原始文件里的关键数值比如Cu品位和清洗后的做抽样比对至少抽10%。我吃过亏有一次正则写错了把“0.85”和“0.35”搞混了因为小数点被当成了分隔符。2.2 Word文档公式、表格和隐藏格式的三重暴击Word文档在探矿业务里主要是地质报告、设计书、评审意见。这类文档的清洗难点不在文字而在公式和表格。地质报告里经常出现化学式CuFeS₂、数学公式品位计算公式、还有大量嵌套表格钻孔一览表、储量估算表。先说公式。Word里的公式有两种一种是老版的Equation Editor对象一种是新版的OMML。这两种直接转文本都会丢东西。我的处理方式是先把Word转成docx如果是doc的话然后用python-docx遍历所有段落遇到公式对象就标记出来单独走LaTeX转换流程。OMML转LaTeX有现成的XSLT但Equation Editor对象比较麻烦我一般是用LibreOffice做一次中转转成docx后再处理。表格是另一个大坑。探矿报告里的表格经常是“合并单元格嵌套表格”python-docx读出来的结构是扁平的合并单元格的信息会丢。我的做法是用docx2python这个库它能保留表格的合并信息读出来是一个嵌套列表然后我再根据行列索引重建结构。这里有个技巧地质表格的列头经常跨页第二页的表格没有表头你得手动把第一页的表头补上去。还有一个容易被忽略的点Word的隐藏文字和批注。有些报告里作者会把一些中间计算过程设为隐藏文字或者用批注写“此处数据待核实”。这些内容如果不清洗掉RAG检索的时候会把它们当成正式内容导致错误结论。我的做法是读段落的时候检查run.font.hidden属性批注则用document.comments单独提取存到另一个字段里不混入正文。实操心得Word清洗完建议把纯文本和表格数据分开存储。纯文本走段落切分表格数据走结构化入库。混在一起切分表格的语义会被切碎检索效果很差。2.3 PDF文档扫描件、矢量图和文字层的三角关系PDF是探矿资料里最复杂的载体。原因很简单同一份PDF里可能既有文字层又有扫描图片还有矢量图。文字层可以直接提取扫描图片得走OCR矢量图比如地质图提取出来是路径数据根本没法直接转文本。我处理PDF的第一步永远是判断这个PDF的类型。用pdfplumber读第一页看chars对象的数量。如果一页有几百个字符说明有文字层如果只有几个甚至没有那就是扫描件。混合型的PDF最麻烦得逐页判断。文字层PDF的提取我推荐pdfplumber而不是PyPDF2。原因在于pdfplumber能保留字符的位置信息这对于处理表格至关重要。探矿PDF里的表格经常没有边框线靠字符的x坐标对齐。pdfplumber的extract_table方法可以基于位置做表格识别比纯文本提取准得多。扫描件PDF就得走OCR。我试过Tesseract、PaddleOCR和商业API。探矿资料里的OCR最大的挑战是专业术语和手写体。Tesseract对印刷体还行但遇到“矽卡岩”这种词经常识别成“砂卡岩”。PaddleOCR的中文模型好一些但对手写批注还是力不从心。我的策略是印刷体走PaddleOCR手写批注单独截出来人工校对。虽然费事但探矿数据错不起。矢量图PDF比如MapGIS导出的地质图是最头疼的。这种PDF里的文字其实是路径提取出来是乱码。我的处理方式是用pdf2image把页面转成高分辨率图片再走OCR。分辨率至少300dpi否则细线条上的文字识别不出来。注意PDF清洗完一定要保留页码和坐标信息。探矿资料里经常需要回溯原文如果清洗后的文本没有位置标记找起来会疯掉。我一般会在每个文本块后面加一个[page:x, bbox:y]的标记检索的时候虽然不显示但排查问题时非常有用。2.4 网页数据从地质云到论坛帖子的抓取与净化探矿业务的网页数据来源很杂地质云平台、矿业权公示系统、行业论坛、甚至一些老的地质队网站。这些网页的清洗难点不在抓取而在净化。地质云平台的数据通常有API但很多老平台只有HTML页面。抓取的时候不要用通用的正文提取算法比如Readability因为探矿页面的正文经常夹杂在表格和列表里通用算法会把关键数据当“导航”删掉。我的做法是先分析页面结构找到数据所在的table或div用XPath精准定位然后单独提取。论坛帖子是另一个极端。探矿论坛里的讨论经常有“我去年在XX矿区看到……”这种口语化描述里面藏着宝贵的经验信息。但论坛页面的噪音也大签名档、广告、引用回复。我的清洗流程是先用CSS选择器去掉signature、ad、quote这些类然后按post容器切分每个帖子单独存。引用回复要特别处理因为引用里可能包含被引用的原始内容直接删会丢信息我一般是把引用内容用[quote]标记包起来检索时可以选择是否包含。网页数据还有一个坑动态加载。很多地质数据平台是前后端分离的直接抓HTML只能拿到空壳。这种情况得用Selenium或者Playwright模拟浏览器。但要注意不要抓太频繁探矿数据平台的服务器通常很弱并发高了直接崩。我一般设2秒间隔单线程跑。实操心得网页抓取完建议做一次“去重”。探矿论坛里经常有人把同一份资料反复发或者不同网站转载同一篇报告。用SimHash做近似去重阈值设0.85左右能去掉大部分重复内容又不至于误删。3. 从清洗到入库RAG知识库的构建全流程3.1 文本切分探矿资料不能按字数硬切清洗完的文本下一步是切分。很多人直接用LangChain的RecursiveCharacterTextSplitter按500字或1000字切。这在通用场景下没问题但在探矿业务里会出大问题。举个例子一份钻孔柱状图描述“从XX米到XX米为矽卡岩见黄铜矿化品位0.8%”。如果你从中间切开“品位0.8%”和“矽卡岩”分到了两个块里检索的时候要么找到岩性没品位要么找到品位不知道是什么岩性。探矿文本的语义单元是“地质段落”不是固定字数。我的切分策略是基于结构标记。清洗阶段我会在文本里插入一些标记比如[钻孔开始]、[岩性段]、[化验结果]。切分的时候优先在这些标记处切保证每个块是一个完整的地质描述。如果某个块太长超过1500字再按句子切但保证不跨岩性段。对于表格数据我不切分直接整表入库。检索的时候表格作为一个整体返回让模型自己解析。因为表格的语义在行列关系里切碎了就没了。3.2 元数据注入让检索能按矿区、按矿种过滤探矿RAG和通用RAG最大的区别是用户经常需要按空间和属性过滤。比如“帮我找XX矿区所有铜品位大于0.5%的钻孔”。如果你只做向量检索没有元数据过滤结果会混入其他矿区的数据。我的做法是在清洗阶段就提取元数据包括矿区名称、矿种、钻孔编号、坐标范围、数据来源、年份。这些元数据存到向量库的metadata字段里。检索的时候先用元数据做一次硬过滤再做向量相似度排序。元数据的提取一部分靠正则比如钻孔编号通常是“ZK”开头加数字一部分靠NER模型。我试过用BERT做地质实体识别效果还行但需要标注数据。如果标注数据少可以先规则提取后面慢慢补模型。注意坐标数据一定要做标准化。探矿资料里的坐标有北京54、西安80、CGCS2000还有各种带号。如果不统一检索“XX坐标附近的钻孔”会漏掉很多。我一般统一转成CGCS2000经纬度存成lat和lon两个字段。3.3 向量化与索引选对Embedding模型比选大模型更重要向量化这一步很多人纠结用哪个大模型其实Embedding模型的选择更关键。探矿文本里专业术语多通用Embedding模型比如text-embedding-ada-002对“矽卡岩”“蚀变分带”这些词的区分度不够。我试过几个方案BGE-large-zh、M3E、还有地质领域微调的模型。BGE-large-zh在探矿文本上的表现明显好于通用模型尤其是对中文地质术语的语义捕捉。如果预算允许可以用探矿资料继续微调BGE效果还能再提升一截。索引方面我推荐HNSW而不是IVF。原因在于探矿数据的查询模式用户经常做“相似钻孔”检索需要高召回率。HNSW的召回率比IVF高虽然内存占用大一些但探矿数据量通常不大几万到几十万条完全扛得住。3.4 检索策略混合检索加Rerank别只靠向量纯向量检索在探矿场景下有个致命问题数值检索不准。比如用户问“铜品位0.8%的钻孔”向量检索可能返回0.75%和0.85%的因为语义上“差不多”。但探矿里0.8%和0.75%可能差一个工业品位边界。我的做法是混合检索向量检索召回Top 50同时用BM25做关键词检索召回Top 50然后合并去重再用Rerank模型精排。Rerank模型我用的BGE-reranker-large对地质文本的排序效果不错。对于数值查询我还会加一层结构化过滤。如果查询里检测到数值和比较词大于、小于、等于先解析成结构化查询在元数据或表格数据里过滤再把结果和向量检索结果合并。4. 常见问题与排查技巧实录4.1 清洗阶段的高频问题速查表问题现象可能原因排查方法解决方案中文变问号编码不匹配用chardet检测编码统一转UTF-8置信度低时手动指定表格数据错列分隔符识别错误对比原始文件和清洗结果用\s{2,}或制表符切分避免单空格公式丢失公式对象未处理检查docx里的OMML对象用XSLT转LaTeX或LibreOffice中转OCR识别错误专业术语或手写体抽样比对原始扫描件印刷体用PaddleOCR手写体人工校对网页抓取为空动态加载查看页面源码是否有数据用Playwright模拟浏览器降低并发检索结果不相关切分粒度不当检查切分后的文本块按地质段落切分表格不切分数值检索不准纯向量检索测试数值查询的召回混合检索结构化过滤Rerank4.2 三个我踩过的坑和对应的解法第一个坑PDF里的隐藏文字层。有些PDF是“双层”的上面是扫描图片下面藏着一层OCR文字。这种PDF用pdfplumber读能读到文字但文字和图片对不上。我一开始没注意清洗出来的文本和实际图片内容有偏差。后来我的做法是先检查PDF是否有文字层如果有再检查文字层和图片是否对齐。对齐的方法很简单随机抽几页把文字层渲染出来和图片叠加对比。如果偏差大就放弃文字层直接走OCR。第二个坑Word表格的跨页合并。地质报告里的钻孔一览表经常跨好几页第一页有表头后面几页没有。python-docx读出来后面的表格没有列名数据全乱。我的解法是读第一页表格的时候把表头存下来后面遇到没有表头的表格自动把第一页的表头补上去。这个逻辑写起来不复杂但能省掉大量人工校对。第三个坑网页抓取的反爬。有些地质数据平台有反爬机制频繁请求会封IP。我一开始用多线程结果被封了好几次。后来改成单线程随机延迟1.5到3秒并且每次请求都带不同的User-Agent。如果还是被封就用Playwright模拟真实浏览器行为加上鼠标移动和滚动。虽然慢但稳。4.3 清洗质量的验证方法清洗完的数据怎么知道质量行不行我的做法是做一次“检索回测”。从原始资料里挑20个典型查询比如“XX矿区铜品位大于0.5%的钻孔”“XX断裂带的产状”然后看RAG检索的结果是否准确。如果准确率低于80%就回去检查清洗环节。还有一个笨办法但很有效随机抽100个文本块人工读一遍看有没有乱码、错列、语义断裂。我每次做完清洗都会抽检虽然费时间但能发现很多自动化检测发现不了的问题。实操心得清洗日志一定要详细。每个文件的编码、分隔符、OCR置信度、切分块数都记下来。出问题的时候日志能帮你快速定位是哪个环节出的错。我一般用JSON格式存日志方便后续分析。5. 探矿RAG清洗的几条硬核经验5.1 精度优先别怕慢探矿数据和互联网数据最大的区别是互联网数据错一点没关系探矿数据错一点可能意味着几百万的钻探投入打水漂。所以我在清洗环节的原则是宁可慢也要准。OCR置信度低于0.9的人工校对表格数据不确定的回查原始文件数值有疑问的做交叉验证。5.2 保留原始文件索引清洗后的数据一定要保留到原始文件的索引。比如每个文本块存一个source_file和page_num字段。这样检索出结果后用户能快速回溯到原文。探矿业务里用户对数据来源的信任度要求很高没有出处的结果他们不敢用。5.3 分阶段验证别等全做完再测清洗流程很长TXT、Word、PDF、网页四种源每种都有多个步骤。我的做法是每完成一种源的清洗就做一次小规模检索测试。比如TXT清洗完先拿TXT数据做检索看效果。如果不行及时调整别等四种源全洗完再发现有问题那时候改起来成本太高。5.4 建立术语词典辅助清洗和检索探矿业务里有很多同义词和缩写比如“矽卡岩”和“砂卡岩”、“黄铜矿”和“黄铜”、“ZK”和“钻孔”。我建了一个术语词典清洗的时候用来做标准化检索的时候用来做查询扩展。这个词典是慢慢积累的一开始可能只有几十个词后面越用越多。5.5 别忘了图片和图表虽然标题里说的是TXT、Word、PDF和网页但探矿资料里还有大量图片地质图、剖面图、柱状图。这些图片里的信息纯文本清洗是拿不到的。我的做法是对图片做OCR提取图上的文字标注然后和对应的正文关联起来。比如一张地质图上有“XX断裂”OCR提取出来后存到该页的元数据里。检索的时候如果用户搜“XX断裂”即使正文没提也能通过图片标注找到。这个工作量大但价值也大。探矿资料里图往往比文字更直观信息密度更高。我现在的做法是优先处理文字图片OCR作为二期工程慢慢补。5.6 持续迭代别想一次到位RAG清洗不是一锤子买卖。随着资料不断新增清洗规则也得不断调整。我一般每季度做一次全面回测看看哪些查询效果不好然后针对性地优化清洗规则。比如发现某个矿区的PDF OCR错误率高就单独对这个矿区的资料做人工校对。这套流程跑下来我们现在的探矿RAG知识库检索准确率能到85%以上。虽然离完美还有距离但已经能帮地质人员快速定位资料省掉大量翻档案的时间。如果你也在做类似的事情我的建议是先从一种数据源开始跑通全流程再逐步扩展。别一上来就四种源一起搞那样容易崩。