공공기관2 작업 중. _temp 몽타주(재생성가능)는 제외. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
95 lines
3.8 KiB
Python
95 lines
3.8 KiB
Python
"""엑셀 D~J vs verify_results path 비교.
|
|
|
|
분류:
|
|
- MATCH: D~J path가 추출된 path와 동일 (정규화 후)
|
|
- D_MATCH: D만 일치, 나머지 다름
|
|
- D_MISMATCH: D부터 다름
|
|
- EMPTY_PATH: path 추출 실패 (수동 확인 필요)
|
|
- HTTP_ERROR: 접속 실패
|
|
- EXTERNAL: 외부링크 (검증 제외)
|
|
"""
|
|
import sys, io, json, re
|
|
from collections import defaultdict, Counter
|
|
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
|
|
|
|
with open(r'D:\01.프로젝트\DB수집\2주차\검토_리포트\verify_results.json', encoding='utf-8') as f:
|
|
res = json.load(f)
|
|
with open(r'D:\01.프로젝트\DB수집\2주차\검토_리포트\excel_data.json', encoding='utf-8') as f:
|
|
excel = json.load(f)
|
|
|
|
def norm(s):
|
|
if not s: return ''
|
|
s = re.sub(r'\s+', ' ', str(s)).strip()
|
|
# 흔한 표기 차이 정리
|
|
s = s.replace('·', '·').replace('∙', '·')
|
|
return s
|
|
|
|
# 사이트별 비교
|
|
report = {}
|
|
for site, rows in excel.items():
|
|
site_stats = Counter()
|
|
site_details = []
|
|
for r in rows:
|
|
row = r['row']
|
|
K = r['K']
|
|
S = r['S']
|
|
excel_path = [norm(v) for v in [r['D'], r['E'], r['F'], r['G'], r['H'], r['I'], r['J']] if v]
|
|
# 외부링크
|
|
if S == '외부링크':
|
|
site_stats['EXTERNAL'] += 1
|
|
continue
|
|
if not K or not isinstance(K, str) or not K.startswith('http'):
|
|
site_stats['NO_URL'] += 1
|
|
continue
|
|
v = res.get(str(row))
|
|
if not v:
|
|
site_stats['NOT_FETCHED'] += 1
|
|
continue
|
|
if v['http'] != 200:
|
|
site_stats[f'HTTP_{v["http"]}'] += 1
|
|
site_details.append({'row': row, 'tag': 'HTTP_ERROR', 'http': v['http'],
|
|
'excel_path': excel_path, 'url': K})
|
|
continue
|
|
actual_path = [norm(x) for x in v['path']]
|
|
if not actual_path:
|
|
site_stats['EMPTY_PATH'] += 1
|
|
site_details.append({'row': row, 'tag': 'EMPTY_PATH',
|
|
'excel_path': excel_path, 'actual_path': [],
|
|
'title': v.get('title', '')[:100], 'h2': v.get('h2', '')[:60],
|
|
'url': K})
|
|
continue
|
|
# 비교 — 토큰 단위 정확 일치
|
|
if excel_path == actual_path:
|
|
site_stats['MATCH'] += 1
|
|
continue
|
|
# 부분 일치 — D(엑셀 첫 항목)이 actual_path의 어디든 일치하는지
|
|
if excel_path and actual_path and excel_path[0] == actual_path[0]:
|
|
# D 일치, 이후는 다름
|
|
site_stats['D_MATCH'] += 1
|
|
site_details.append({'row': row, 'tag': 'D_MATCH',
|
|
'excel_path': excel_path, 'actual_path': actual_path,
|
|
'url': K})
|
|
elif excel_path and actual_path and excel_path[0] in actual_path:
|
|
site_stats['D_IN_ACTUAL'] += 1
|
|
site_details.append({'row': row, 'tag': 'D_IN_ACTUAL',
|
|
'excel_path': excel_path, 'actual_path': actual_path,
|
|
'url': K})
|
|
else:
|
|
site_stats['D_MISMATCH'] += 1
|
|
site_details.append({'row': row, 'tag': 'D_MISMATCH',
|
|
'excel_path': excel_path, 'actual_path': actual_path,
|
|
'url': K})
|
|
report[site] = {'stats': dict(site_stats), 'details': site_details}
|
|
|
|
# 통계 출력
|
|
print('=== 사이트별 비교 통계 ===')
|
|
for site, v in report.items():
|
|
print(f'\n[{site}] 총 {sum(v["stats"].values())}건')
|
|
for tag, n in v['stats'].items():
|
|
print(f' {tag}: {n}')
|
|
|
|
# 저장
|
|
with open(r'D:\01.프로젝트\DB수집\2주차\검토_리포트\compare_all.json', 'w', encoding='utf-8') as f:
|
|
json.dump(report, f, ensure_ascii=False, indent=2)
|
|
print('\n[saved compare_all.json]')
|