5. 웹 크롤링

header

1. 웹 크롤링이란?

웹 크롤링
웹 크롤링

웹 크롤링은 웹사이트에서 자동으로 데이터를 수집하는 기술입니다.

  • 크롤링(Crawling): 웹페이지를 방문하여 데이터를 가져오는 과정
  • 스크래핑(Scraping): 가져온 데이터에서 필요한 정보만 추출하는 과정

파이썬은 HTTP 요청, 응답 파싱, 데이터 저장을 통해 안정적인 웹 크롤링을 구현할 수 있습니다.

웹 크롤링의 기본 흐름

웹 크롤링의 기본 흐름
웹 크롤링의 기본 흐름

2. 웹 크롤링의 법적 제약

웹 크롤링에는 법적 제약이 존재합니다.

정보통신망법 제48조 정보통신망 침해 행위 금지
“누구든지 정당한 접근 권한 없이 또는 허용된 접근 권한을 넘어 정보통신망에 침입해서는 안 된다.”

준수 사항

  • 목적 제한: 개인 학습·연구 목적으로 제한, 상업적 이용 시 저작권 주의
  • 사용 범위: 허용된 범위 내에서만 사용, 악용 금지
  • 서버 보호: 과도한 부하 방지를 위한 적절한 요청 간격 유지

2. HTML 기초

웹 크롤링을 위해서는 HTML 구조를 이해하는 것이 필수입니다.

HTML이란?

HTML(HyperText Markup Language)은 웹페이지의 구조와 내용을 정의하는 마크업 언어입니다.

  • 웹페이지의 골격을 만드는 언어
  • 태그(tag)를 사용하여 요소를 정의
  • 브라우저가 해석하여 화면에 표시

HTML 기본 구조

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <style>
      /* 스타일 정의 */
    </style>
    <title>페이지 제목</title>
  </head>
  <body>
    <!-- 실제 내용이 들어가는 부분 -->
  </body>
</html>

기본 태그

태그 설명 예시
<h1>~<h6> 제목 <h1>메인 제목</h1>
<p> 문단 <p>문단 내용</p>
<div> 블록 컨테이너 <div>구역</div>
<span> 인라인 컨테이너 <span>텍스트</span>
<ul>, <li> 순서 없는 목록 <ul><li>항목1</li></ul>
<ol>, <li> 순서 있는 목록 <ol><li>항목1</li></ol>
<a> 링크 <a href="url">링크</a>
<img> 이미지 <img src="경로" alt="설명">
<input> 입력 필드 <input type="text" name="username">

실습: 웹페이지 구조 만들기

다음 HTML 구조를 만들어보세요:

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="utf-8" />
    <title>My Home Page</title>
    <style>
      #logo { font-weight: bold; font-size: 20px; }
      .wrap { display: flex; height: calc(100vh - 60px); }
      .aside { width: 200px; border-right: 1px solid #ddd; padding: 10px; }
      a { display: block; margin: 8px 0; text-decoration: none; color: #333; }
      a:hover { color: blue; }
      .main { flex: 1; padding: 20px; }
    </style>
  </head>
  <body>
    <div>
      <h1 id="logo">My Home Page</h1>
    </div>
    <hr/>
    <div class="wrap">
      <ul class="aside">
        <li class="Home"><a href="#">Home</a></li>
        <li><a href="#">Library</a><ul>
        <li><a href="#">Gallery</a></li>
        <li><a href="#">Notes</a></li>
        <li><a href="#">About</a></li>
      </ul>
      <div class="main">
        <h2>콘텐츠 영역</h2>
        <p>여기에 내용을 넣습니다.</p>
      </div>
    </div>
  </body>
</html>

JavaScript를 이용한 요소 선택

웹 크롤링에서 중요한 요소 선택 방법들:

// ID로 선택
document.getElementById("logo");

// 클래스로 선택
document.getElementsByClassName("aside");

// 태그명으로 선택
document.getElementsByTagName("a");

// CSS 선택자로 선택
document.querySelector("#logo"); // ID 선택
document.querySelector(".aside"); // 클래스 선택
document.querySelectorAll('a[class="Home"]'); // 속성 선택

// 복합 선택자
document.querySelector("ul.aside li a"); // 중첩된 요소 선택

연습 문제

위의 HTML 구조에서 다음 요소들을 선택해보세요:

  1. 사이드바의 모든 링크
  2. 로고 제목
  3. 사이드바의 모든 리스트 항목
  4. 메인 콘텐츠 영역
  5. 전체 페이지의 모든 링크
정답 보기

        // 1. 사이드바의 모든 링크
        document.querySelectorAll('ul.aside li a')

        // 2. 로고 제목
        document.getElementById('logo')
        // 또는
        document.querySelector('#logo')

        // 3. 사이드바의 모든 리스트 항목
        document.querySelectorAll('ul.aside li')

        // 4. 메인 콘텐츠 영역
        document.querySelector('div.main')

        // 5. 전체 페이지의 모든 링크
        document.querySelectorAll('a')
    

3. requests 라이브러리

requests는 Python에서 HTTP 요청을 쉽게 보낼 수 있게 해주는 라이브러리입니다.

requests 설치

pip install requests

기본 사용법

import requests

# GET 요청
response = requests.get('https://example.com')
print(response.status_code)  # 200
print(response.text)         # HTML 내용

응답 객체 속성

response = requests.get('https://example.com')

print(response.status_code)    # HTTP 상태 코드 (200, 404, 500 등)
print(response.headers)        # 응답 헤더
print(response.text)          # 응답 내용 (문자열)
print(response.content)       # 응답 내용 (바이트)
print(response.json())        # JSON 응답을 딕셔너리로 변환

헤더 설정

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
response = requests.get('https://example.com', headers=headers)

4. BeautifulSoup (bs4) 라이브러리

BeautifulSoup은 HTML과 XML 문서를 파싱하고 탐색하기 위한 Python 라이브러리입니다.

BeautifulSoup 설치

pip install beautifulsoup4

기본 사용법

from bs4 import BeautifulSoup
import requests

# 웹페이지 가져오기
response = requests.get('https://example.com')
html = response.text

# BeautifulSoup 객체 생성
soup = BeautifulSoup(html, 'html.parser')

# 요소 찾기
title = soup.find('title')
print(title.text)  # 페이지 제목

주요 메서드

요소 찾기

# 첫 번째 요소 찾기
soup.find('div')                    # 첫 번째 div 태그
soup.find('div', class_='content')  # class가 'content'인 첫 번째 div
soup.find('div', id='main')         # id가 'main'인 첫 번째 div

# 모든 요소 찾기
soup.find_all('a')                  # 모든 a 태그
soup.find_all('div', class_='item') # class가 'item'인 모든 div

CSS 선택자 사용

# CSS 선택자로 요소 찾기
soup.select('div.content')          # class가 'content'인 div
soup.select('#main')                # id가 'main'인 요소
soup.select('ul li a')              # ul 안의 li 안의 a 태그
soup.select('div > p')              # div의 직접 자식 p 태그

텍스트와 속성 추출

# 텍스트 추출
element = soup.find('h1')
print(element.text)        # 태그 안의 텍스트
print(element.get_text())  # 같은 결과

# 속성 추출
link = soup.find('a')
print(link['href'])        # href 속성 값
print(link.get('href'))    # 같은 결과 (속성이 없으면 None 반환)

실습 예제

import requests
from bs4 import BeautifulSoup

# 웹페이지 가져오기
url = 'https://www.melon.com/chart/'
header = {'User-Agent': 'Chrome'}
response = requests.get(url=url, headers=header)

if (response.status_code == 200):
    soup = BeautifulSoup(response.text, 'html.parser')
    print(soup.select('.title')[1].text)

5. Selenium 라이브러리

Selenium은 웹 브라우저를 자동화하는 도구로, JavaScript가 동적으로 생성하는 콘텐츠도 크롤링할 수 있습니다.

Selenium 설치

pip install selenium

기본 사용법

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager

# Chrome 브라우저 실행
driver = webdriver.Chrome(ChromeDriverManager().install())

# 웹페이지 접속
driver.get('https://example.com')

# 요소 찾기
element = driver.find_element(By.ID, 'username')
element.send_keys('test@example.com')

# 브라우저 종료
driver.quit()

주요 메서드

요소 찾기

# ID로 찾기
driver.find_element(By.ID, 'username')

# 클래스로 찾기
driver.find_element(By.CLASS_NAME, 'content')

# CSS 선택자로 찾기
driver.find_element(By.CSS_SELECTOR, 'div.content')

# XPath로 찾기
driver.find_element(By.XPATH, '//div[@class="content"]')

# 모든 요소 찾기
driver.find_elements(By.TAG_NAME, 'a')

요소 조작

# 텍스트 입력
element.send_keys('Hello World')

# 클릭
element.click()

# 텍스트 가져오기
text = element.text

# 속성 가져오기
href = element.get_attribute('href')

# 체크박스/라디오 버튼 선택
element.click()  # 선택/해제

대기 처리

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 명시적 대기 (최대 10초)
wait = WebDriverWait(driver, 10)
element = wait.until(EC.presence_of_element_located((By.ID, 'dynamic-content')))

# 조건별 대기
wait.until(EC.element_to_be_clickable((By.ID, 'button')))
wait.until(EC.text_to_be_present_in_element((By.ID, 'status'), '완료'))

실습 예제

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 브라우저 실행
driver = webdriver.Chrome()

try:
    # 네이버 접속
    driver.get('https://www.naver.com')

    # 검색창에 텍스트 입력
    search_box = driver.find_element(By.ID, 'query')
    search_box.send_keys('파이썬 크롤링')

    # 검색 버튼 클릭
    search_button = driver.find_element(By.CSS_SELECTOR, '.btn_search')
    search_button.click()

    # 검색 결과 대기
    wait = WebDriverWait(driver, 5)
    results = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, '.lst_view > .bx')))

    # 검색 결과 출력
    for result in results[0:4]:  # 상위 5개만
        title = result.find_element(By.CSS_SELECTOR, '.title_area').text
        print(title)

finally:
    driver.quit()

requests + BeautifulSoup vs Selenium

특징 requests + BeautifulSoup Selenium
속도 빠름 느림
JavaScript 처리 불가 처리 가능
리소스 사용 적음 많음
사용 용도 정적 콘텐츠 동적 콘텐츠
설치 복잡도 간단 복잡 (WebDriver 필요)

언제 Selenium을 사용할까?

  • JavaScript로 동적 생성되는 콘텐츠 크롤링
  • 로그인이 필요한 사이트 크롤링
  • 사용자 상호작용이 필요한 웹사이트
  • SPA(Single Page Application) 크롤링