import glob, re, os, sys, fitz sys.stdout.reconfigure(encoding='utf-8') pdf_path = 'resources/knowledge/original/원가계산/건설공사_표준품셈/2026년_건설공사_표준품셈.pdf' doc = fitz.open(pdf_path) target_files = [] target_files.extend(glob.glob('resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/*.md')) target_files.extend(glob.glob('resources/knowledge/original/원가계산/건설공사_표준품셈/05_유지관리부문/*.md')) target_files.append('resources/knowledge/original/원가계산/건설공사_표준품셈/04_기계설비부문/제13장_플랜트설비공사.md') print(f"Target files: {len(target_files)}") # Build PDF index of section headings print("Indexing PDF pages for section headings...") sec_to_pdf_page = {} for p_num in range(len(doc)): text = doc[p_num].get_text() # Find all patterns like X-Y-Z or X-Y matches = re.findall(r'(\d+-\d+(?:-\d+)?)', text) for m in matches: sec_to_pdf_page.setdefault(m, []).append(p_num) print(f"Indexed {len(sec_to_pdf_page)} section numbers in PDF.") # Now parse each markdown file's tables that have a Remarks column discrepancies = [] for fpath in target_files: fname = os.path.basename(fpath) with open(fpath, 'r', encoding='utf-8') as f: lines = f.readlines() current_sec_num = 'UNKNOWN' current_sec_title = 'UNKNOWN' in_table = False headers = [] table_rows = [] start_line = 0 for idx, line in enumerate(lines): line_s = line.strip() sec_m = re.search(r'(\d+-\d+(?:-\d+)?)(\s+[^\n(]+)?', line_s) if sec_m and not line_s.startswith('|'): current_sec_num = sec_m.group(1).strip() current_sec_title = line_s if line_s.startswith('|') and not line_s.startswith('|---'): cols = [c.strip() for c in line_s.split('|')[1:-1]] if not in_table: # check if header has 비고 or 비 고 if any('비고' in c or '비 고' in c for c in cols): headers = cols in_table = True start_line = idx + 1 table_rows = [] continue if in_table: table_rows.append((idx + 1, cols)) else: if in_table and (line_s == '' or not line_s.startswith('|')): # Check this table against PDF! remarks_col_idx = -1 for ci, h in enumerate(headers): if '비고' in h or '비 고' in h: remarks_col_idx = ci break if remarks_col_idx != -1 and len(table_rows) > 0: md_remarks = [r[1][remarks_col_idx] if remarks_col_idx < len(r[1]) else '' for r in table_rows] # Find matching page in PDF cand_pages = sec_to_pdf_page.get(current_sec_num, []) # filter to body pages (> 45) body_pages = [p for p in cand_pages if p > 45] found_pdf_table = False for p in body_pages: page = doc[p] tabs = page.find_tables() for tab in tabs: df = tab.extract() if not df or len(df) < 2: continue pdf_header = [c if c else '' for c in df[0]] # Check if pdf_header has 비고 pdf_rem_idx = -1 for pci, ph in enumerate(pdf_header): if '비고' in ph or '비 고' in ph: pdf_rem_idx = pci break if pdf_rem_idx != -1: found_pdf_table = True # Extract pdf remarks pdf_remarks_raw = [r[pdf_rem_idx] if pdf_rem_idx < len(r) and r[pdf_rem_idx] else '' for r in df[1:]] # Flatten any multi-line in pdf remarks pdf_remarks_split = [] for pr in pdf_remarks_raw: pdf_remarks_split.extend([sub.strip() for sub in pr.split('\n') if sub.strip()]) # Compare count of non-empty remarks or ditto presence md_non_empty = [m for m in md_remarks if m] pdf_non_empty = [p for p in pdf_remarks_split if p] # Check if ditto marks or numbers mismatch has_ditto = any('〃' in m or '"' in m for m in md_remarks) or any('〃' in p for p in pdf_non_empty) # If row count differs significantly or ditto count differs md_ditto_cnt = sum(1 for m in md_remarks if '〃' in m or '"' in m) pdf_ditto_cnt = sum(1 for p in pdf_non_empty if '〃' in p or '"' in p) if has_ditto and md_ditto_cnt != pdf_ditto_cnt: discrepancies.append({ 'file': fname, 'sec': current_sec_num, 'line': start_line, 'type': 'Ditto count mismatch', 'md_dittos': md_ditto_cnt, 'pdf_dittos': pdf_ditto_cnt, 'md_remarks': md_remarks, 'pdf_remarks': pdf_remarks_raw, 'page': p + 1 }) elif len(md_remarks) != len(df) - 1: # Row count mismatch in table with remarks discrepancies.append({ 'file': fname, 'sec': current_sec_num, 'line': start_line, 'type': 'Row count mismatch in remarks table', 'md_rows': len(md_remarks), 'pdf_rows': len(df) - 1, 'md_remarks': md_remarks, 'pdf_remarks': pdf_remarks_raw, 'page': p + 1 }) in_table = False headers = [] table_rows = [] print(f"\nTotal Discrepancies found: {len(discrepancies)}") for d in discrepancies: print(f"\n[{d['file']}] {d['sec']} (L{d['line']}, PDF page {d.get('page')}) -> {d['type']}") if 'md_dittos' in d: print(f" MD dittos: {d['md_dittos']} vs PDF dittos: {d['pdf_dittos']}") if 'md_rows' in d: print(f" MD rows: {d['md_rows']} vs PDF rows: {d['pdf_rows']}") print(f" MD remarks: {d['md_remarks'][:6]}") print(f" PDF remarks: {d['pdf_remarks'][:6]}")