본문으로 건너뛰기

Python으로 만드는 AI 웹 스크래퍼

HTML을 정제하고 Markdown으로 바꿔 LLM이 웹페이지 질문에 답하게 하는 Python 튜토리얼입니다.

이 요약은 AI가 원문을 분석해 생성했습니다. 정확한 내용은 원문 기준으로 확인하세요.

TL;DR

웹페이지 전체 HTML을 LLM에 전달하면 script, navigation, footer, popup과 반복 문구가 입력에 섞여 토큰과 처리 부담이 커집니다. 이 튜토리얼은 Python에서 requests로 HTML을 가져오고 BeautifulSoup으로 잡음을 제거한 뒤 markdownify로 Markdown을 만들며, gpt-5.4-nano가 사용자 질문에 필요한 답변만 생성하도록 연결합니다. prompt에는 페이지에 있는 정보만 사용하고 없는 내용은 만들지 말라는 제약을 넣어 Olostep 홈페이지와 pricing 페이지의 질문 응답을 테스트합니다. 결과는 Markdown으로 화면에 표시하거나 파일로 저장할 수 있지만, 서버 운영과 API 호출, 페이지 변경 대응 비용까지 고려하면 기존 scraping API와 직접 구축 방식을 비교해야 합니다.

섹션별 상세

01
일반적인 웹 스크래퍼는 페이지의 원시 HTML이나 전체 텍스트를 반환하지만, LLM 애플리케이션에 그대로 넣으면 navigation, script, footer, 반복 콘텐츠가 입력을 차지합니다. 이 튜토리얼은 Python과 Jupyter Notebook으로 웹페이지를 가져온 뒤 불필요한 구조를 제거하고 Markdown으로 바꾸는 흐름을 구성합니다. 필요한 본문만 LLM에 전달하면 출력이 읽기 쉬워지고 사용자의 질문에 맞는 답변을 다른 workflow로 넘기기 쉬워집니다.
02
구현 환경은 requests, BeautifulSoup, markdownify, OpenAI, ftfy, python-dotenv로 구성됩니다. requests가 페이지를 가져오고 BeautifulSoup이 HTML을 파싱하며 markdownify가 본문을 Markdown으로 바꾸는 식으로 각 패키지가 단계별 역할을 맡습니다. .env 파일의 OPENAI_API_KEY를 load_dotenv()로 읽고 OpenAI client를 생성하므로 API 키를 notebook 코드에 직접 넣지 않으며, API 계정의 billing과 사용할 수 있는 모델도 확인해야 합니다.
python
def clean_html(html):
    html = fix_text(html)
    soup = BeautifulSoup(html, "html.parser")
    # Remove obvious noisy tags
    for tag in soup([
        "script", "style", "noscript", "svg", "img", "iframe", "nav", "header", "footer", "aside", "form", "button"
    ]):
        tag.decompose()
    noise_words = [
        "cursor", "modal", "popup", "floating", "signup", "login", "cookie", "banner", "navbar", "menu", "footer", "header", "subscribe", "newsletter", "loading", "wait", "success", "auth", "w-nav", "w-form"
    ]
    # First collect noisy tags
    tags_to_remove = []
    for tag in soup.find_all(True):
        if tag.attrs is None:
            continue
        class_value = tag.get("class", [])
        id_value = tag.get("id", "")
        if isinstance(class_value, list):
            class_text = " ".join(class_value).lower()
        else:
            class_text = str(class_value).lower()
        id_text = str(id_value).lower()
        if any(word in class_text or word in id_text for word in noise_words):
            tags_to_remove.append(tag)
    # Then remove them safely
    for tag in tags_to_remove:
        tag.decompose()
    body = soup.body if soup.body else soup
    return str(body)

문자열 인코딩을 보정한 뒤 불필요한 HTML 태그와 class·id 기반 잡음 요소를 제거합니다.

웹페이지에서 추출된 원시 HTML과 페이지 구조를 보여주는 코드 화면입니다.
Screenshot화면에는 page-wrapper, preloader, global-styles, main-wrapper 같은 HTML 요소와 제목 태그가 표시됩니다. 본문에 섞인 레이아웃 요소를 그대로 LLM에 전달하기보다 script, navigation, footer 등 잡음을 제거해야 한다는 정제 단계의 필요성을 시각적으로 뒷받침합니다.
03
fetch_page()는 User-Agent 헤더와 15초 timeout을 포함한 requests.get()으로 URL의 HTML을 가져오고 raise_for_status()로 404나 500 같은 HTTP 오류를 중단시킵니다. clean_html()은 fix_text()로 인코딩 문제를 보정한 다음 script, style, noscript, svg, img, iframe, nav, header, footer, aside, form, button 태그를 분해합니다. 이어 popup, cookie, navbar, newsletter, modal 같은 단어가 class나 id에 포함된 태그를 수집해 제거하므로 페이지 본문에 집중할 수 있는 HTML이 남습니다.
python
def html_to_markdown(html):
    markdown_text = markdownify_html(
        html,
        heading_style="ATX",
        bullets="-"
    )
    markdown_text = fix_text(markdown_text)
    # Remove image markdown
    markdown_text = re.sub(r"!\[.*?\]\(.*?\)", "", markdown_text)
    # Remove extra spaces and blank lines
    markdown_text = re.sub(r"[ \t]+", " ", markdown_text)
    markdown_text = re.sub(r"
{3,}", "

", markdown_text)
    lines = []
    skip_lines = [
        "click to try", "wait...", "you've successfully reserved your spot.", "thank you! your submission has been received!", "oops! something went wrong while submitting the form.", "product", "resources", "company"
    ]
    for line in markdown_text.splitlines():
        line = line.strip()
        if not line: continue
        if line.lower() in skip_lines: continue
        lines.append(line)
    return "
".join(lines)

정제된 HTML을 읽기 쉬운 Markdown으로 바꾸고 이미지 링크, 과도한 공백, 반복된 문구를 제거합니다.

정제된 웹페이지가 제목과 문단, 목록을 갖춘 Markdown 텍스트로 변환된 결과입니다.
ScreenshotMarkdown 결과에는 Olostep의 웹 데이터 API 설명과 /scrapes, /crawls, /searches, /answers 기능이 구조화된 문장과 목록으로 남아 있습니다. 이미지와 반복된 웹사이트 장식 대신 질문 응답에 필요한 사실 중심 콘텐츠를 LLM 입력으로 사용할 수 있는 형태입니다.
04
html_to_markdown()은 정제된 HTML을 ATX heading과 하이픈 목록을 사용하는 Markdown으로 변환합니다. 이미지 Markdown과 과도한 공백 및 빈 줄을 정규식으로 없애고, form 메시지와 navigation label 같은 반복 문구는 skip_lines 목록과 비교해 제외합니다. 결과는 raw HTML보다 짧고 사람이 확인하기 쉬운 텍스트가 되며, 글에서 입력 토큰을 줄이는 전처리 효과가 설명됩니다.
python
def answer_query_from_page(markdown_text, user_query):
    prompt = f"""
You are an AI web scraping assistant. You will receive Markdown extracted from a webpage. Your task is to answer the user's query using only the useful page content.
User query: {user_query}
Webpage Markdown: {markdown_text}
Instructions:
- Return only clean Markdown.
- Use only information from the webpage Markdown.
- Do not invent missing details.
- Ignore navigation links, buttons, CTAs, popups, decorative labels, image captions, and repeated marketing fragments.
- Ignore lines like "Start for free", "Contact Sales", "Your AI Agent", and decorative workflow examples unless they directly answer the query.
- Focus on headings, paragraphs, product descriptions, feature sections, pricing details, documentation text, and factual claims.
- If the page does not contain the answer, say: "The page does not contain this information."
- Keep the answer short, clear, and focused.
"""
    response = client.responses.create(
        model=MODEL_NAME,
        input=prompt
    )
    return response.output_text

사용자 질문과 웹페이지 Markdown을 LLM에 전달하고 페이지에 있는 정보만 사용한 짧은 Markdown 답변을 반환합니다.

05
질문 응답 단계는 전체 페이지 요약 대신 특정 user query에 답하도록 prompt를 구성합니다. prompt에는 웹페이지 Markdown과 질문을 함께 넣고, 제공된 내용만 사용하며 누락된 정보는 추측하지 말고 없으면 지정된 문장을 반환하라는 제약을 둡니다. 마지막 ai_web_scraper()가 수집, 정제, 변환, 응답을 순서대로 실행하고 Olostep 홈페이지의 회사 개요와 pricing 페이지의 가격 질문에 대한 Markdown 결과를 생성합니다.
python
def ai_web_scraper(url, user_query):
    raw_html = fetch_page(url)
    cleaned_html = clean_html(raw_html)
    markdown_text = html_to_markdown(cleaned_html)
    answer = answer_query_from_page(markdown_text, user_query)
    return answer

웹페이지 수집, HTML 정제, Markdown 변환, 질문 응답을 하나의 재사용 가능한 함수로 연결합니다.

Python으로 AI 웹 스크래퍼를 만드는 전체 흐름을 Fetch Webpages, Clean HTML, Convert to Markdown, Ask Anything의 네 단계로 배치한 그래픽입니다.
Diagram이미지는 원시 웹페이지를 수집한 뒤 HTML 잡음을 제거하고 Markdown으로 변환한 다음 LLM에 질문을 보내는 처리 순서를 보여줍니다. 하단 코드에는 fetch_page, clean_html, html_to_markdown, answer_query_from_page를 차례로 호출하는 함수 구조가 나타나 튜토리얼의 핵심 pipeline과 직접 연결됩니다.
06
튜토리얼은 결과를 ai_scraper_result.md 파일에 UTF-8 Markdown으로 저장하는 방법까지 연결합니다. 이 구조는 notebook에서 각 단계를 확인한 뒤 API, chatbot, agent workflow로 옮기기 쉬운 작은 QA 엔진으로 사용할 수 있습니다. 다만 서버 운영, LLM 호출, 페이지 변경 대응, 오류 처리와 유지보수에 비용이 들기 때문에 Olostep, Firecrawl, Exa 같은 기존 scraping 또는 web intelligence API와 직접 구축 방식을 작업 규모와 목적에 따라 비교해야 합니다.
AI 웹 스크래퍼가 회사가 하는 일을 질문받고 생성한 Markdown 답변 화면입니다.
Screenshot화면은 Olostep을 웹 데이터 infrastructure와 web data API로 요약하며 search, crawl, scrape, structure 기능을 한 플랫폼에서 제공한다는 답변을 보여줍니다. 전체 웹페이지를 반환하지 않고 사용자 질문에 해당하는 회사 설명만 출력한다는 QA pipeline의 결과 사례입니다.
Olostep pricing 페이지의 Trial과 Starter 요금제 및 요청 한도를 Markdown 목록으로 정리한 화면입니다.
Screenshot화면에는 Trial $0, 성공 요청 500건, Starter 월 $9, 성공 요청 5,000건, 동시 요청 150건, 1K당 $0.495가 표시됩니다. pricing 페이지에서 가격 관련 질문만 골라 읽기 쉬운 결과로 반환하는 테스트 사례이며, 원문에 있는 구체적인 요금 정보가 출력에 보존됩니다.

용어 해설

웹 스크래핑(Web Scraping)
웹 스크래핑은 웹사이트에서 정보를 자동으로 수집하는 기술입니다. requests로 페이지 HTML을 가져온 뒤 BeautifulSoup으로 구조를 파싱하고 불필요한 요소를 제거해 필요한 콘텐츠만 남깁니다. LLM 애플리케이션에서는 입력 토큰과 잡음을 줄이는 전처리 단계로 중요합니다.
Markdown
Markdown은 제목, 문단, 목록 같은 구조를 간결한 텍스트 문법으로 표현하는 형식입니다. 이 글에서는 정제된 HTML을 Markdown으로 변환해 이미지와 반복된 레이아웃을 제거하고, LLM이 읽기 쉬운 입력으로 만듭니다. 최종 답변 저장과 후속 workflow 연결에도 활용됩니다.
대규모 언어 모델(Large Language Model)
대규모 언어 모델은 텍스트를 입력받아 문맥을 파악하고 자연어 결과를 생성하는 모델입니다. 이 파이프라인에서는 정제된 웹페이지 Markdown과 사용자의 질문을 함께 받아 페이지에 근거한 짧은 답변을 생성합니다. 원문에 없는 정보의 추측을 막도록 입력 범위와 출력 형식을 prompt에서 제한합니다.
HTML 파서(HTML Parser)
HTML 파서는 웹 문서를 태그와 속성으로 분해해 프로그램이 다룰 수 있는 구조로 바꾸는 도구입니다. BeautifulSoup은 이를 이용해 script, style, nav, footer 같은 태그를 찾아 삭제하고 class와 id에 포함된 잡음 단어도 검사합니다. 결과적으로 LLM에 전달할 본문 중심의 HTML이 남습니다.

기술

  • Python
  • Jupyter Notebook
  • requests
  • BeautifulSoup
  • markdownify
  • OpenAI
  • ftfy
  • python-dotenv
  • gpt-5.4-nano
  • Markdown
  • HTML

활용 사례

  • 특정 웹페이지에서 회사 개요를 추출하는 질의응답 도구
  • pricing 페이지에서 가격 정보를 찾아 Markdown으로 정리하는 workflow
  • 정제된 웹 콘텐츠를 chatbot이나 AI agent에 전달하는 파이프라인
  • 웹페이지 답변을 Markdown 파일로 저장해 후속 작업에 활용하는 자동화

언급된 리소스

AI 분석 전체 내용 보기

AI 요약 · 북마크 · 개인 피드 설정 — 무료

출처 · 인용 안내

원문 발행 2026. 08. 14.수집 2026. 08. 14.출처 타입 RSS

인용 시 "요약 출처: AI Trends (aitrends.kr)"를 표기하고, 사실 확인은 원문 보기 기준으로 진행해 주세요. 자세한 기준은 운영 정책을 참고해 주세요.