# -*- coding: utf-8 -*- """건설근로자공제회 2단(중분류) 메뉴 링크 보강. megamenu div.menu_inner[data-ui-content] > h3.subtit a.titlink(goMenu) = 그 2단의 대표 URL. button[data-ui-tab=동일키] = 2단 라벨. 라벨로 URL없음 행(E) 매칭해 K 채우고 L/M/N/O 산출. """ import os, re, importlib.util, warnings from copy import copy from urllib.parse import urljoin import openpyxl from bs4 import BeautifulSoup from openpyxl.styles import Font, Alignment warnings.filterwarnings('ignore') spec = importlib.util.spec_from_file_location('p1', r'D:\01.프로젝트\DB수집\_스크립트\_공공기관_phase1.py') m1 = importlib.util.module_from_spec(spec); spec.loader.exec_module(m1) spec2 = importlib.util.spec_from_file_location('p234', r'D:\01.프로젝트\DB수집\_스크립트\_공공기관_phase234.py') P = importlib.util.module_from_spec(spec2); spec2.loader.exec_module(P) specn = importlib.util.spec_from_file_location('nv', r'D:\01.프로젝트\DB수집\_스크립트\_공공기관_navfix.py') NV = importlib.util.module_from_spec(specn); specn.loader.exec_module(NV) XLSX = r'D:\01.프로젝트\DB수집\공공기관\건설근로자공제회.xlsx' BASE = 'https://www.cw.or.kr' LOG = open(r'D:\01.프로젝트\DB수집\_스크립트\_cwlink_result.txt', 'w', encoding='utf-8') def clean(s): return re.sub(r'\s+', ' ', (s or '')).strip() def build_map(): html = m1.render(BASE + '/', wait=4500)[1] soup = BeautifulSoup(html, 'html.parser') # 2단 라벨: button[data-ui-tab] tab_label = {} for b in soup.find_all('button'): k = b.get('data-ui-tab') if k and clean(b.get('title') or b.get_text()): tab_label[k] = clean(b.get('title') or b.get_text()) # 2단 대표URL: menu_inner[data-ui-content] > h3.subtit a.titlink label2url = {} for inner in soup.select('div.menu_inner[data-ui-content], [data-ui-content]'): k = inner.get('data-ui-content') a = inner.select_one('h3.subtit a.titlink') or inner.select_one('a.titlink') or inner.select_one('a.menu_link') if not a: continue u = m1.js_href(a) or (a.get('href') or '') if u.startswith('/') or u.startswith('http'): label = tab_label.get(k) or clean(a.get('title') or a.get_text()) if label: label2url[label] = urljoin(BASE + '/', u) return label2url def main(): label2url = build_map() LOG.write(f'megamenu 2단 라벨→URL {len(label2url)}개\n') wb = openpyxl.load_workbook(XLSX) ws = wb.active sess = P.make_session() left = Alignment(horizontal='left', vertical='center', wrap_text=False) filled = 0 for r in range(3, ws.max_row + 1): if ws.cell(r, 2).value is None: break if ws.cell(r, 11).value: continue # 라벨 = E(중분류) 우선, 없으면 D label = clean(ws.cell(r, 5).value) or clean(ws.cell(r, 4).value) u = label2url.get(label) if not u: continue c = ws.cell(r, 11); c.value = u; c.hyperlink = u old = c.font c.font = Font(name=old.name or '맑은 고딕', size=old.size or 11, color='0000FF', underline='single') c.alignment = left # L/M/N/O 산출 soup, final = P.fetch(sess, u) if soup: body = P.get_body(soup, P.BODY_SEL) form, count = P.detect_form(body) ws.cell(r, 12).value = form ws.cell(r, 13).value = count if form == '게시판' else 1 hi, _, _, ht = P.detect_media(body) vid = NV.real_video(body); aud = NV.real_audio(body) types, q = P.detect_kogl(body) parts = (['어문'] if ht else []) + (['이미지'] if hi else []) + (['영상'] if vid else []) + (['오디오'] if aud else []) ws.cell(r, 14).value = ','.join(parts) if parts else '없음' if types and types != {1, 2, 3, 4}: ws.cell(r, 15).value = ','.join(f'{n}유형' for n in sorted(types)) ws.cell(r, 16).value = '게시판' if form == '게시판' else '게시물' ws.cell(r, 17).value = 'Y' if q == 'Y' else 'N' else: ws.cell(r, 15).value = '미부착' if ws.cell(r, 19).value in ('URL 없음', '접근 실패'): ws.cell(r, 19).value = None filled += 1 LOG.write(f' r{r} {label} → {u}\n') wb.save(XLSX) LOG.write(f'=== 링크보강 {filled}행 ===\n') LOG.close() if __name__ == '__main__': main()