import json import re import hashlib import zipfile import sys from pathlib import Path from xml.etree import ElementTree as ET SOURCE = Path(r'C:\Users\δΊ‘\Desktop\SOP-QC-YL') sys.stdout.reconfigure(encoding='utf-8') OUT = Path('scripts/sop-qc') OUT.mkdir(exist_ok=True) W = '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}' def clean(value): return re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f]', '', value).replace('\r', '\n').strip() def word_text(node): output = [] for run in node.iter(W+'r'): text = ''.join(n.text or '' if n.tag in (W+'t', W+'delText') else '\t' if n.tag == W+'tab' else '\n' if n.tag in (W+'br', W+'cr') else '' for n in run.iter()) alignment = run.find(W+'rPr/'+W+'vertAlign') if alignment is not None and alignment.get(W+'val') == 'superscript' and text.strip(): text = '^('+text+')' output.append(text) return clean(''.join(output)) records = [] for file in sorted(SOURCE.iterdir(), key=lambda p: p.name): if file.name.startswith('~$') or file.suffix.lower() not in ('.doc', '.docx'): continue blocks = [] if file.suffix.lower() == '.docx': with zipfile.ZipFile(file) as z: body = ET.fromstring(z.read('word/document.xml')).find(W+'body') for node in body: if node.tag == W+'p': blocks.append({'p': word_text(node)}) elif node.tag == W+'tbl': blocks.append({'table': [[ '\n'.join(word_text(p) for p in cell.findall(W+'p')).strip() for cell in row.findall(W+'tc')] for row in node.findall(W+'tr')]}) else: body = ET.parse(OUT/'extracted'/(file.name+'.xml')).getroot() for node in body: if node.tag == 'p': blocks.append({'p': clean(node.text or '')}) elif node.tag == 'table': blocks.append({'table': [[clean('\n'.join(p.text or '' for p in cell)) for cell in row] for row in node]}) text = '\n'.join(b.get('p', '\n'.join(' | '.join(row) for row in b.get('table', []))) for b in blocks) records.append({'file': file.name, 'sha256': hashlib.sha256(file.read_bytes()).hexdigest(), 'blocks': blocks, 'text': text}) (OUT/'extracted'/(file.name+'.txt')).write_text(text, encoding='utf-8') (OUT/'documents.json').write_text(json.dumps(records, ensure_ascii=False, indent=2), encoding='utf-8') print(json.dumps({'documents': len(records), 'tables': sum(sum('table' in b for b in d['blocks']) for d in records)}, ensure_ascii=False))