# -*- coding: utf-8 -*-
"""부여군 N(저작물 유형) 재판정 — 장식/공통UI 이미지 false '이미지' 제거.
- phase234 detect_media 는 KOGL 마크만 제외 → file_icon.gif·see_btn.gif·btn_page_*.gif 등
  게시판 스킨/공통버튼 아이콘을 '이미지'로 오탐.
- [[feedback_N_image_rule]] 적용: 장식/공통UI·페이징버튼·첨부아이콘 제외, 실제 사진/업로드·지도/PDF임베드만 인정.
- 대상: 현재 N 에 '이미지' 포함된 같은도메인 행만(false 양성 제거 전용 → 이미지 추가 안 함).
- 게시판은 상세글 상위5 추적. body=#txt|#contents|main.
사용: python -X utf8 _buyeo_rejudge_N.py [--write]
"""
import sys, warnings, re
from urllib.parse import urljoin
import requests, openpyxl
from bs4 import BeautifulSoup

warnings.filterwarnings('ignore')
S = requests.Session(); S.headers.update({'User-Agent': 'Mozilla/5.0'})
XLSX = r'D:\01.프로젝트\DB수집\작업파일\광역_사이트맵\충청남도\7.부여군\충청남도_부여군.xlsx'
DOMAIN = 'buyeo.go.kr'

KOGL = re.compile(r'(?:new_)?img_open(?:type|code)\d', re.I)
# 장식/공통UI: 기존 논산 DECO + 부여 게시판 스킨/공통버튼/첨부아이콘 패턴 보강
DECO = re.compile(
    r'/site/common/img/|move\.png|no[-_]?img|blank\.|spacer\.|'
    r'/img/(?:icon|ico|bul|bullet|arrow|btn|bg|tit|h\d)|'
    r'ico_|btn_|bul_|bg_|_bg\.|icon_|'
    r'file_icon|_icon\.|icon\.gif|_btn\.|see_btn|'          # 첨부아이콘·바로보기버튼
    r'/skin/|/images/(?:kr/)?common/|/common/img/|'         # 게시판 스킨·공통 UI 디렉터리
    r'btn_page|page_(?:next|prev|first|last)', re.I)        # 페이징 버튼
MAPPDF = re.compile(r'pdf|viewer\.html|map|kakao|daum|naver.*map|google.*map|/map', re.I)
VIDEO = re.compile(r'youtube\.com|youtu\.be|/embed/|\.mp4|\.webm|vimeo', re.I)
DETAIL = re.compile(r'mode=V|view\.do|/view|seq=|idx=|mng_no=|bbsSeq|nttId|no=', re.I)


def get(url):
    r = S.get(url, verify=False, timeout=20)
    return BeautifulSoup(r.content, 'html.parser')


def body(soup):
    return soup.select_one('#txt') or soup.select_one('#contents') or soup.select_one('main') or soup


def real_imgs(node):
    n = 0
    for im in node.find_all('img'):
        src = im.get('src') or ''
        if not src or KOGL.search(src) or DECO.search(src):
            continue
        n += 1
    return n


def media_flags(node):
    img = real_imgs(node) > 0
    vid = False
    for ifr in node.find_all('iframe'):
        s = ifr.get('src') or ''
        if VIDEO.search(s):
            vid = True
        elif MAPPDF.search(s):
            img = True
    for a in node.find_all('a'):
        if VIDEO.search(a.get('href') or ''):
            vid = True
    if node.find('video'):
        vid = True
    return img, vid


def detail_links(soup, base):
    out = []
    for a in body(soup).find_all('a'):
        h = a.get('href') or ''
        if h.startswith('#'):
            continue
        if DETAIL.search(h):
            out.append(urljoin(base, h))
    seen = set(); res = []
    for u in out:
        if u not in seen:
            seen.add(u); res.append(u)
    return res[:5]


def judge(k, L, M, N):
    if not isinstance(k, str) or DOMAIN not in k:
        return N, 'skip(외부)'
    try:
        soup = get(k)
    except Exception as e:
        return N, f'fetch실패:{str(e)[:25]}'
    bd = body(soup)
    txtlen = len(bd.get_text(strip=True))
    if L == '게시판' and (M in (0, '0', None)):
        return '없음', 'board0'
    has_img, has_vid = media_flags(bd)
    detail = False
    if L == '게시판' and not has_img:
        for du in detail_links(soup, k):
            try:
                di, dv = media_flags(body(get(du)))
                if di: has_img = True
                if dv: has_vid = True
                if di or dv: detail = True
                if has_img and has_vid: break
            except Exception:
                pass
    parts = []
    if txtlen >= 1: parts.append('어문')
    if has_img: parts.append('이미지')
    if has_vid: parts.append('영상')
    return (','.join(parts) if parts else '없음'), ('detail' if detail else '')


def main():
    write = '--write' in sys.argv
    wb = openpyxl.load_workbook(XLSX); ws = wb.active
    changes = []
    for r in range(3, ws.max_row + 1):
        N = ws.cell(r, 14).value
        if not (isinstance(N, str) and '이미지' in N):
            continue
        k = ws.cell(r, 11).value; L = ws.cell(r, 12).value; M = ws.cell(r, 13).value
        new, tag = judge(k, L, M, N)
        if new != N:
            changes.append((r, N, new, tag, ws.cell(r, 7).value or ws.cell(r, 6).value, k))
    print(f'현재 N에 이미지 포함 행 재판정 → 변경 {len(changes)}건')
    for r, old, new, tag, label, k in changes:
        print(f'  행{r} [{old} → {new}] {tag} | {label} | {str(k)[-45:]}')
    if write and changes:
        for r, old, new, tag, label, k in changes:
            ws.cell(r, 14).value = new
        wb.save(XLSX)
        print(f'\n저장: {XLSX} ({len(changes)}건 수정)')
    elif not write:
        print('\n(계획만. --write 로 반영)')


if __name__ == '__main__':
    main()
