import gradio as gr import requests from bs4 import BeautifulSoup import urllib.parse # iframe 경로가 상대경로일 경우 절대경로로 만들기 위해 사용 # 디버깅(로그)용 함수 def debug_log(message: str): """ 간단한 디버깅(로그) 출력을 위한 함수 """ print(f"[DEBUG] {message}") def scrape_naver_blog(url: str) -> str: """ 주어진 네이버 블로그 URL에서 제목과 본문을 추출하여 반환합니다. """ debug_log("scrape_naver_blog 함수 시작") debug_log(f"요청받은 URL: {url}") # 헤더 세팅(크롤링 차단 방지 일부 도움) headers = { "User-Agent": ( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/96.0.4664.110 Safari/537.36" ) } try: # 1) 네이버 블로그 '메인' 페이지 요청 response = requests.get(url, headers=headers) debug_log("HTTP GET 요청(메인 페이지) 완료") # 응답 상태코드 확인 if response.status_code != 200: debug_log(f"요청 실패, 상태코드: {response.status_code}") return f"오류가 발생했습니다. 상태코드: {response.status_code}" # BeautifulSoup 파싱 (메인 페이지) soup = BeautifulSoup(response.text, "html.parser") debug_log("HTML 파싱(메인 페이지) 완료") # 2) iframe 태그 찾기 iframe = soup.select_one("iframe#mainFrame") if not iframe: # iframe 자체를 찾지 못한 경우 debug_log("iframe#mainFrame 태그를 찾을 수 없습니다.") return "본문 iframe을 찾을 수 없습니다." iframe_src = iframe.get("src") if not iframe_src: debug_log("iframe src가 존재하지 않습니다.") return "본문 iframe의 src를 찾을 수 없습니다." # 3) iframe src가 상대경로인 경우 절대경로로 보정 # (예: //blog.naver.com/~~~ 와 같은 경우를 처리) parsed_iframe_url = urllib.parse.urljoin(url, iframe_src) # iframe 페이지로 재요청 debug_log(f"iframe 페이지 요청 URL: {parsed_iframe_url}") iframe_response = requests.get(parsed_iframe_url, headers=headers) debug_log("HTTP GET 요청(iframe 페이지) 완료") if iframe_response.status_code != 200: debug_log(f"iframe 요청 실패, 상태코드: {iframe_response.status_code}") return f"iframe에서 오류가 발생했습니다. 상태코드: {iframe_response.status_code}" # 4) iframe 페이지 파싱 iframe_soup = BeautifulSoup(iframe_response.text, "html.parser") debug_log("HTML 파싱(iframe 페이지) 완료") # 제목 추출 title_div = iframe_soup.select_one('.se-module.se-module-text.se-title-text') title = title_div.get_text(strip=True) if title_div else "제목을 찾을 수 없습니다." debug_log(f"추출된 제목: {title}") # 본문 추출 content_div = iframe_soup.select_one('.se-main-container') if content_div: # 본문을 \n 기준으로 구분해서 좀 더 깔끔하게 만들기 content = content_div.get_text("\n", strip=True) else: content = "본문을 찾을 수 없습니다." debug_log("본문 추출 완료") # 결과 합치기 result = f"[제목]\n{title}\n\n[본문]\n{content}" debug_log("제목과 본문을 합쳐 반환 준비 완료") return result except Exception as e: debug_log(f"에러 발생: {str(e)}") return f"스크래핑 중 오류가 발생했습니다: {str(e)}" # Gradio 인터페이스 def main_interface(): interface = gr.Interface( fn=scrape_naver_blog, inputs=gr.Textbox( lines=1, label="네이버 블로그 링크", placeholder="예: https://blog.naver.com/ssboost/222983068507" ), outputs=gr.Textbox(label="결과"), title="네이버 블로그 스크래퍼", description="네이버 블로그 링크를 입력하면 제목과 본문을 추출하여 표시합니다." ) return interface if __name__ == "__main__": debug_log("Gradio 앱 실행 시작") demo = main_interface() demo.launch() debug_log("Gradio 앱 실행 종료")