# -*- coding: utf-8 -*- """주택금융 정보목록 3보드 분류 카테고리별 건수 수집 → _hf_cat.json.""" import sys, io, json, re sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') from playwright.sync_api import sync_playwright BOARDS = [ ("표준정보목록", "https://www.hf.go.kr/ko/sub06/sub06_04_01.do"), ("고유정보목록", "https://www.hf.go.kr/ko/sub06/sub06_04_02.do"), ("즐겨찾는목록", "https://www.hf.go.kr/ko/sub06/sub06_04_03.do"), ] CATS = [("전체",""),("감사","24"),("윤리","25"),("기획","26"),("재정","27"),("법무","28"), ("노무","29"),("인사","30"),("총무","31"),("회계","32"),("정보화","33"),("홍보","34"),("대외","35")] CNT_JS = """ () => { // 총건수: 'X건' or pager last page * perpage. 우선 텍스트 'X 건'/'총 X' const t=document.body.innerText; let m=t.match(/총\\s*([0-9,]+)\\s*건/) || t.match(/전체\\s*([0-9,]+)\\s*건/) || t.match(/([0-9,]+)\\s*건/); // 게시판 목록 행수(현재페이지) const rows=document.querySelectorAll('table tbody tr, ul.board-list li, .board_list li').length; return JSON.stringify({tot:m?m[1].replace(/,/g,''):null, rowsOnPage:rows}); } """ out = {} with sync_playwright() as p: br = p.chromium.launch(headless=True) pg = br.new_context(ignore_https_errors=True, viewport={'width':1600,'height':1000}).new_page() for bname, burl in BOARDS: out[bname] = {"url": burl, "cats": []} for cname, cv in CATS: u = f"{burl}?mode=list&srCategoryId={cv}" if cv else f"{burl}?mode=list" try: pg.goto(u, wait_until='domcontentloaded', timeout=20000); pg.wait_for_timeout(600) r = json.loads(pg.evaluate(CNT_JS)) except Exception as e: r = {"tot": None, "rowsOnPage": 0, "err": str(e)[:40]} out[bname]["cats"].append({"name": cname, "v": cv, "tot": r.get("tot"), "rows": r.get("rowsOnPage")}) print(f" {bname} {cname}({cv}): tot={r.get('tot')} rows={r.get('rowsOnPage')}") br.close() json.dump(out, open("_hf_cat.json","w",encoding="utf-8"), ensure_ascii=False, indent=1) print("saved _hf_cat.json")