# -*- coding: utf-8 -*- """벤더 콘텐츠탭 셀렉터 조사: 샘플 페이지에서 탭류 컨테이너를 위치(부모 컨텍스트)와 함께 덤프.""" import openpyxl, requests, sys, re from bs4 import BeautifulSoup from urllib.parse import urljoin, urlparse from concurrent.futures import ThreadPoolExecutor, as_completed from collections import Counter import urllib3 urllib3.disable_warnings() sys.stdout.reconfigure(encoding='utf-8') UA={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'} NAV_ANCESTORS=('header','gnb','lnb','snb','nav','footer','top','aside','menu_wrap','allmenu','sitemap') TABISH=re.compile(r'(tab|basic_tab|slave|grap|deth|nav_cont|intab)', re.I) def is_in_nav(el): p=el for _ in range(8): p=p.parent if p is None: break idc=(p.get('id') or '')+' '+' '.join(p.get('class') or []) idc=idc.lower() if any(k in idc for k in NAV_ANCESTORS): return True return False def main(): xlsx, n = sys.argv[1], int(sys.argv[2]) if len(sys.argv)>2 else 30 wb=openpyxl.load_workbook(xlsx); ws=wb.active urls=[] for r in range(3, ws.max_row+1): c=ws.cell(r,11); L=ws.cell(r,12).value u=c.hyperlink.target if c.hyperlink else (c.value if isinstance(c.value,str) and c.value.startswith('http') else None) if u and L in ('페이지','게시판'): urls.append(u) dom=Counter(urlparse(u).netloc.replace('www.','') for u in urls).most_common(1)[0][0] urls=[u for u in urls if dom in urlparse(u).netloc] seen=set(); samp=[] for u in urls: k=u.split('?')[0] if k in seen: continue seen.add(k); samp.append(u) if len(samp)>=n: break sess=requests.Session(); sess.headers.update(UA) def fetch(u): try: rr=sess.get(u,timeout=20,verify=False); rr.encoding=rr.apparent_encoding or 'utf-8'; return u, rr.text except: return u, None sig=Counter() with ThreadPoolExecutor(max_workers=12) as ex: for fu in as_completed([ex.submit(fetch,u) for u in samp]): u, html=fu.result() if not html: continue soup=BeautifulSoup(html,'html.parser') for el in soup.find_all(['ul','div']): idc=(el.get('id') or '')+' '+' '.join(el.get('class') or []) if not TABISH.search(idc): continue lis=[li for li in el.find_all('li') if li.find('a')] if len(lis)<2: continue anchors=[li.find('a') for li in lis] hrefs=[a.get('href','') for a in anchors] anchor_only=all(h.strip().startswith('#') or not h.strip() for h in hrefs) kind='인페이지#' if anchor_only else '페이지/게시판링크' where='NAV' if is_in_nav(el) else 'CONTENT' tag=el.name cls=re.sub(r'\d+','N','.'.join(el.get('class') or []) or ('#'+ (el.get('id') or ''))) sig[f"{where:7} {tag}.{cls[:24]:24} li={len(lis):>2} {kind}"]+=1 print(f'=== {xlsx.split(chr(92))[-1]} (도메인 {dom}, 샘플 {len(samp)}) ===') for s,c in sig.most_common(25): print(f' x{c:>2} {s}') if __name__=='__main__': main()