文档证据格式:PDF、DOCX 与 TXT 的博弈
文档证据,说白了就是电子取证里最常碰到的「硬通货」。我经手的案子,十有八九都离不开 PDF、DOCX 或者纯文本文件。这三种格式看着简单,但坑特别多。你想想看,一个 PDF 可能藏着隐藏图层,一个 DOCX 可能带着你根本不知道的修订记录,一个 TXT 文件可能因为编码问题直接变成乱码——这些细节,往往就是案件的关键。
我个人习惯,拿到文档证据的第一件事,不是急着看内容,而是先搞清楚它的「底细」:格式是什么?用什么工具生成的?有没有被篡改的痕迹?今天我们就来聊聊这三种格式的解析、提取和互转实战。
PDF 解析与提取:不只是「另存为」那么简单
PDF 这玩意儿,设计初衷是为了「跨平台一致显示」,而不是为了「方便提取内容」。所以很多新手觉得 PDF 转 Word 就是点一下「另存为」——嗯,我当年也这么干过,直到有一次在法庭上,对方律师指出我提交的 PDF 提取文本里缺了一段关键数字。
为什么会这样?因为 PDF 里的文字可能不是「文字」,而是图形。比如扫描件、图片型 PDF,你根本选不中文字。这时候就得用 OCR(光学字符识别)。我常用的工具有 Adobe Acrobat 的 OCR 引擎,或者开源的 Tesseract。但 OCR 不是万能的,遇到手写体、模糊扫描件,识别率会直线下降。
PDF 提取的另一个难点是「结构化信息」。比如表格、页眉页脚、水印。普通的文本提取工具会把表格内容打乱,让你分不清哪行是哪列。我建议用 pdfplumber(Python 库)来处理表格,它能保留单元格的相对位置。
import pdfplumber
with pdfplumber.open("evidence.pdf") as pdf:
for page in pdf.pages:
tables = page.extract_tables()
for table in tables:
for row in table:
print(row) # 每一行是一个列表,保留单元格顺序
还有一个容易被忽略的点:PDF 的元数据。创建时间、修改时间、作者、甚至使用的软件版本,都可能成为线索。用 exiftool 或者 Python 的 PyPDF2 都能提取。
DOCX 结构分析:一个 ZIP 包里的秘密
很多人以为 DOCX 就是一个 Word 文件,其实它本质上是一个 ZIP 压缩包。你把它后缀改成 .zip,解压开,就能看到里面的 XML 文件。这些 XML 文件才是真正的文档内容。
我刚开始做取证时,遇到一个案子:对方声称一份合同是「原始文件」,但我总觉得不对劲。后来我解压了 DOCX,查看了 document.xml,发现里面有一段被隐藏的修订记录——对方删除了关键条款,然后又重新保存。但 DOCX 的修订标记(<w:ins> 和 <w:del>)还留在 XML 里。这就是铁证。
DOCX 的核心结构大致如下:
| 路径 | 内容 | 取证价值 |
|---|---|---|
word/document.xml |
正文内容(含样式、修订) | 高。可提取隐藏文本、修订记录 |
word/comments.xml |
批注 | 高。批注作者、时间、内容 |
word/styles.xml |
样式定义 | 中。可辅助判断文档是否被批量修改 |
docProps/core.xml |
元数据(作者、创建时间等) | 中。但容易被篡改 |
word/media/ |
嵌入的图片、视频 | 高。可能包含隐藏的媒体文件 |
提取 DOCX 中的文本,我推荐用 python-docx 库。它能保留段落、表格、列表的结构,比直接解压 XML 方便得多。
from docx import Document
doc = Document("evidence.docx")
for para in doc.paragraphs:
print(para.text) # 逐段输出文本
# 提取表格
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
print(cell.text)
<w:vanish/> 标记。提取时一定要检查这个属性。
纯文本编码问题:UTF-8、GBK 与 ASCII 的混战
纯文本文件看起来最简单,但编码问题能让你怀疑人生。我见过太多新手,拿到一个 TXT 文件,打开一看全是乱码,就以为文件损坏了。其实只是编码不对。
常见的编码有:
- ASCII: 最古老,只能表示英文字母、数字和少量符号。一个字节一个字符。
- UTF-8: 现在的主流,兼容 ASCII,能表示全世界所有字符。变长编码(1-4 字节)。
- GBK: 中文环境下常见,Windows 简体中文系统的默认编码。每个汉字占 2 个字节。
- GB2312: GBK 的前身,字符集较小。
- ISO-8859-1: 西欧编码,也叫 Latin-1。
怎么判断一个 TXT 文件的编码?我一般用 chardet 库,它能自动检测编码。
import chardet
with open("unknown.txt", "rb") as f:
raw = f.read(10000) # 读取前 10000 字节
result = chardet.detect(raw)
print(result) # 输出:{'encoding': 'GBK', 'confidence': 0.99}
但 chardet 不是 100% 准确。尤其是文件内容很短的时候,它可能猜错。我的习惯是:先看文件来源。如果是从 Windows 中文系统导出的,大概率是 GBK;如果是 Linux 或 macOS 上生成的,大概率是 UTF-8。如果还是不确定,就用十六进制编辑器(比如 HxD)打开,看看字节序列。比如,UTF-8 的 BOM 头是 EF BB BF,GBK 没有 BOM。
格式互转实战:从 PDF 到 DOCX,再到 TXT
格式互转是日常操作,但每个转换步骤都有坑。我画了一张流程图,帮你理清思路。
具体到实战,我总结了几条经验:
- PDF → DOCX: 用 Adobe Acrobat 的「导出」功能,或者用
pdf2docx库。但要注意,复杂排版(比如多栏、文本框)可能会错位。转换后一定要逐页核对。 - DOCX → PDF: 这个相对简单,Word 自带的「另存为 PDF」就够用。但要注意,如果 DOCX 里有嵌入字体,PDF 里可能显示异常。我建议在转换前,把字体都设为常见字体(如宋体、Arial)。
- PDF → TXT: 纯文本提取,用
PyPDF2或pdfminer。但表格会丢失结构,变成一堆数字堆在一起。如果表格很重要,我建议先转 DOCX,再手动整理。 - DOCX → TXT: 用 python-docx 提取文本,然后保存为 UTF-8 编码的 TXT。注意:DOCX 里的图片、图表、公式都会丢失。如果证据包含这些,一定要在转换说明里注明。
嗯,文档证据这块,说难不难,说简单也不简单。关键是要有耐心,别放过任何一个细节。你想想看,一个隐藏的修订标记,一个错误的编码,都可能让整个案子翻盘。所以,下次拿到文档证据,别急着看内容——先看看它的「底细」。