파이썬 웹 크롤링 초보자를 위한 실전 예제

파이썬 웹 크롤링

웹 크롤링은 인터넷에서 자동으로 데이터를 수집하는 기술로, 뉴스 데이터 수집, 전자상거래 사이트의 상품 가격 비교, 소셜 미디어 트렌드 분석, 시장 조사, 그리고 학술 연구 등 다양한 목적으로 활용됩니다.
이 글에서는 파이썬(Python)을 활용한 웹 크롤링의 기초와 초보자를 위한 실전 예제를 소개합니다.



1. 웹 크롤링이란?

웹 크롤링(Web Crawling)은 컴퓨터 프로그램(크롤러)이 웹사이트를 방문하고 페이지 데이터를 읽어오는 과정을 말합니다. 이 과정을 통해 특정 정보(예: 뉴스 제목, 상품 가격 등)를 자동으로 수집할 수 있습니다.


2. 준비물

웹 크롤링을 시작하기 위해 필요한 파이썬 라이브러리:

Requests

  • HTTP 요청을 쉽게 처리할 수 있도록 설계된 간단하고 직관적인 라이브러리입니다.
  • JSON 데이터 처리, 세션 유지, 헤더 설정 등 다양한 기능을 지원합니다.
  • 설치: pip install requests

BeautifulSoup

  • HTML 데이터를 파싱하고 원하는 요소를 추출합니다.
  • 설치: pip install beautifulsoup4

3. 실전 예제: 네이버 뉴스의 헤드라인 가져오기

다음은 네이버 뉴스 페이지에서 주요 뉴스 제목을 크롤링하는 예제입니다.

코드

import requests
from bs4 import BeautifulSoup

# 1. URL 설정
url = "https://news.naver.com/"

# 2. HTTP GET 요청
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
}
response = requests.get(url, headers=headers)
response.raise_for_status()  # 요청 실패 시 예외 발생

# 3. HTML 파싱
soup = BeautifulSoup(response.text, "html.parser")

# 4. 뉴스 헤드라인 추출
headlines = soup.select(".hdline_article_tit > a")  # '.hdline_article_tit > a'는 CSS 선택자로, 특정 HTML 구조에서 원하는 요소를 지정해줍니다.

print("네이버 뉴스 헤드라인:")
base_url = "https://news.naver.com"
for idx, headline in enumerate(headlines, start=1):
    title = headline.text.strip()  # 텍스트 내용
    link = base_url + headline["href"]  # 절대 경로 링크 생성
    print(f"{idx}. {title} - 링크: {link}")

결과 예시

네이버 뉴스 헤드라인:
1. 정부, 방역수칙 재조정 검토 중 - 링크: https://news.naver.com/main/read.naver?mode=LSD&mid=sec&sid1=101&oid=001&aid=0001234567
2. 연말 쇼핑 시즌, 할인 행사 시작 - 링크: https://news.naver.com/main/read.naver?mode=LSD&mid=sec&sid1=101&oid=001&aid=0007654321

코드 설명

  1. URL 설정
  • 데이터를 가져올 웹사이트 주소를 설정합니다.
  1. HTTP 요청 보내기
  • requests.get()으로 HTML 데이터를 요청하고 성공 여부를 확인합니다.
  1. HTML 파싱
  • BeautifulSoup을 사용해 HTML을 파싱합니다.
  1. 데이터 추출
  • soup.select()로 CSS 선택자를 활용해 원하는 HTML 요소를 찾습니다. 여기서는 뉴스 제목과 링크를 가져옵니다.

4. 초보자를 위한 팁

1) User-Agent 설정

  • 일부 웹사이트는 기본 요청을 차단할 수 있습니다. 헤더에 User-Agent를 추가하면 크롤링 성공률이 높아집니다.
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
}
response = requests.get(url, headers=headers)

2) robots.txt 확인

  • 크롤링 전에 웹사이트의 robots.txt를 확인해 허용된 페이지만 크롤링하세요.
  • 예: https://news.naver.com/robots.txt
  • 허용 예시: Allow: /news/
  • 비허용 예시: Disallow: /private/
  • Disallow로 표시된 경로는 크롤링하지 않는 것이 좋습니다. 이를 무시할 경우 법적 문제가 발생할 수 있습니다.

5. 주의사항

1) 법적 준수

  • 웹 크롤링은 데이터를 가져오는 행위로, 일부 사이트에서는 이를 금지할 수 있습니다. 웹사이트의 이용 약관과 크롤링 허용 여부를 반드시 확인하세요.

2) 과도한 요청 금지

  • 짧은 시간에 다수의 요청을 보내면 서버에 부담을 줄 수 있습니다. time.sleep()을 사용해 요청 간격을 두세요.
import time
# 요청 사이에 2초 대기
time.sleep(2)

6. 확장 가능성

1) Selenium

  • 동적으로 렌더링되는 페이지(예: JavaScript)를 크롤링할 때 유용합니다.

2) Scrapy

  • 대규모 데이터 크롤링에 적합한 고성능 크롤링 프레임워크입니다.

7. 마무리

이제 파이썬으로 웹 크롤링을 시작해보세요! 크롤링한 데이터를 활용해 자신만의 프로젝트를 만들어보는 건 어떨까요?


8. Q&A

Q1: 크롤링 중 일부 사이트에서 데이터를 가져오지 못합니다. 이유가 뭔가요?

  • 사이트가 크롤링을 방지하기 위해 robots.txt 설정이나 JavaScript를 활용했을 수 있습니다. 이런 경우 Selenium을 사용하거나 요청 헤더를 조정해보세요.

Q2: 크롤링한 데이터를 파일로 저장하려면 어떻게 하나요?

  • 데이터를 CSV 파일로 저장하는 예제입니다:
import csv

with open('headlines.csv', 'w', newline='', encoding='utf-8') as file:
    writer = csv.writer(file)
    writer.writerow(['번호', '제목', '링크'])
    for idx, headline in enumerate(headlines, start=1):
        title = headline.text.strip()
        link = base_url + headline["href"]
        writer.writerow([idx, title, link])
  • 데이터를 JSON 파일로 저장하는 예제입니다:
import json

headlines_data = []
for idx, headline in enumerate(headlines, start=1):
    title = headline.text.strip()
    link = base_url + headline["href"]
    headlines_data.append({"번호": idx, "제목": title, "링크": link})

with open('headlines.json', 'w', encoding='utf-8') as file:
    json.dump(headlines_data, file, ensure_ascii=False, indent=4)

Q3: 크롤링 속도를 조절해야 할 때 어떤 방법을 사용하나요?

  • time.sleep()을 활용해 요청 간격을 조정하거나, 라이브러리에서 제공하는 요청 제한 옵션을 설정하세요.

Q4: 비동기 요청은 어떻게 처리하나요?

  • aiohttp 라이브러리를 사용하면 비동기 HTTP 요청을 구현할 수 있습니다. 대규모 크롤링에 유용합니다.
import aiohttp
import asyncio

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, "https://news.naver.com")
        print(html)

asyncio.run(main())

Similar Posts