Files
people/.workbuddy/extract_doc.py
T

53 lines
1.8 KiB
Python
Raw Normal View History

2026-09-10 14:26:55 +08:00
import olefile, struct, sys
def extract_doc_text(filepath):
ole = olefile.OleFileIO(filepath)
word = ole.openstream('WordDocument').read()
flags = struct.unpack('<H', word[0x0A:0x0C])[0]
table_name = '1Table' if (flags & 0x0200) else '0Table'
fcClx = struct.unpack('<I', word[0x01A2:0x01A6])[0]
lcbClx = struct.unpack('<I', word[0x01A6:0x01AA])[0]
table = ole.openstream(table_name).read()
clx = table[fcClx:fcClx+lcbClx]
pos = 0
plc_pcd = None
while pos < len(clx):
clxt = clx[pos]
if clxt == 1:
cb = struct.unpack('<H', clx[pos+1:pos+3])[0]
pos += 3 + cb
elif clxt == 2:
lcb = struct.unpack('<I', clx[pos+1:pos+5])[0]
plc_pcd = clx[pos+5:pos+5+lcb]
break
else:
break
if plc_pcd is None:
return "NO_PCDT"
n = (len(plc_pcd) - 4) // 12
cps = [struct.unpack('<I', plc_pcd[i*4:i*4+4])[0] for i in range(n+1)]
out = []
for i in range(n):
cnt = cps[i+1] - cps[i]
pcd = plc_pcd[4 + i*12: 4 + i*12 + 12]
fc = struct.unpack('<I', pcd[0:4])[0]
compressed = (fc & 0x40000000) != 0
fcoff = fc & 0x3FFFFFFF
if compressed:
raw = word[fcoff:fcoff+cnt]
txt = raw.decode('gb18030', errors='replace')
else:
raw = word[fcoff:fcoff+cnt*2]
txt = raw.decode('utf-16-le', errors='replace')
out.append(txt)
return "".join(out)
if __name__ == '__main__':
import io
for p in sys.argv[1:]:
t = extract_doc_text(p)
sys.stdout.buffer.write(("="*60 + "\n").encode('utf-8'))
sys.stdout.buffer.write(("FILE: " + p + "\n").encode('utf-8'))
sys.stdout.buffer.write(t.encode('utf-8'))
sys.stdout.buffer.write(("\n" + "="*60 + "\n").encode('utf-8'))