# -*- coding: utf-8 -*- import openpyxl, requests, urllib3, re, json, sys, io from bs4 import BeautifulSoup from concurrent.futures import ThreadPoolExecutor urllib3.disable_warnings() sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') H={'User-Agent':'Mozilla/5.0'} B='https://www.jejusi.go.kr' ws=openpyxl.load_workbook('제주특별자치도_제주시.xlsx').active rows=[] for r in range(3, ws.max_row+1): b=ws.cell(r,2).value if not b or b<45: continue K=ws.cell(r,11).value or '' rows.append({'row':r,'B':b,'name':ws.cell(r,6).value or ws.cell(r,5).value,'L':ws.cell(r,12).value,'K':K}) def get(u): return requests.get(u, timeout=20, headers=H, verify=False).text def scan(x): K=x['K'] if 'jejusi.go.kr' not in K or '.do' not in K: return None try: html=get(K).replace('&','&') except Exception: return None s=BeautifulSoup(html,'html.parser') box=s.select_one('div.depth_tabmenu') if not box: return None tabs=[] for a in box.select('li a'): href=a.get('href') or '' tabs.append({'label':a.get_text(strip=True),'href':href,'blank':a.get('target')=='_blank','active':'active' in ' '.join(a.find_parent('li').get('class',[]))}) if len(tabs)<2: return None return {**x,'tabs':tabs} res=[] with ThreadPoolExecutor(max_workers=8) as ex: res=[r for r in ex.map(scan, rows) if r] # group by tab-set signature to dedupe (same tab bar appears on each tab page) print('depth_tabmenu 가진 행:', len(res)) for x in sorted(res, key=lambda z:z['B']): print(f"B{x['B']} {x['name'][:20]:20s} L={x['L']} K={x['K'].split('jejusi.go.kr')[-1].split('?')[0]}") for t in x['tabs']: print(f" - {t['label'][:24]:24s} {'[새창]' if t['blank'] else ''}{'[active]' if t['active'] else ''} {t['href'].split('jejusi.go.kr')[-1][:55] if 'jejusi' in t['href'] else t['href'][:55]}") json.dump(res, open('_tabscan.json','w',encoding='utf-8'), ensure_ascii=False)