Topic 4: requests로 웹페이지 가져오기 🌐
🎯 학습 목표
파이썬으로 웹페이지를 가져오는 첫걸음을 떼어봐요!
- HTTP가 무엇인지 간단히 이해하기
- requests 라이브러리 사용법 익히기
- 웹페이지 내용 가져오기
- 상태 코드 이해하기
- 간단한 에러 처리하기
🌍 HTTP란 무엇일까요?
웹의 대화 방식
HTTP는 웹에서 정보를 주고받는 방법이에요. 마치 편지를 주고받는 것과 비슷해요!
👤 나 (클라이언트): "네이버 홈페이지 보여주세요!"
🖥️ 서버: "네, 여기 있습니다!" (HTML 전송)
HTTP 요청의 종류
우리가 주로 사용할 것들:
- GET: 정보를 달라고 요청 (웹페이지 보기)
- POST: 정보를 보내면서 요청 (로그인, 글쓰기)
🚀 첫 번째 웹페이지 가져오기
기본 사용법
import requests
# 웹페이지 요청하기
response = requests.get("https://httpbin.org/html")
# 결과 확인
print("상태 코드:", response.status_code)
print("페이지 길이:", len(response.text))
단계별 설명
import requests
# 1단계: URL 정하기
url = "https://httpbin.org/html"
print(f"🌐 {url}에 접속합니다...")
# 2단계: GET 요청 보내기
response = requests.get(url)
print("✅ 응답을 받았습니다!")
# 3단계: 응답 확인하기
print(f"📊 상태 코드: {response.status_code}")
print(f"📏 페이지 크기: {len(response.text)} 글자")
# 4단계: 내용 일부 보기
print("\n📄 페이지 내용 미리보기:")
print(response.text[:200]) # 처음 200글자만
📊 응답(Response) 객체 이해하기
requests.get()은 Response 객체를 반환해요. 이 객체에는 많은 정보가 들어있어요!
Response 객체의 주요 속성
import requests
response = requests.get("https://httpbin.org/json")
# 1. 상태 코드
print(f"상태 코드: {response.status_code}")
# 2. 텍스트 내용
print(f"텍스트 길이: {len(response.text)}")
# 3. 바이트 내용
print(f"바이트 크기: {len(response.content)}")
# 4. URL
print(f"최종 URL: {response.url}")
# 5. 헤더 정보
print(f"콘텐츠 타입: {response.headers.get('content-type')}")
# 6. 응답 시간
print(f"응답 시간: {response.elapsed.total_seconds()}초")
text vs content 차이
# response.text - 문자열 (str)
text_content = response.text
print(type(text_content)) # <class 'str'>
# response.content - 바이트 (bytes)
byte_content = response.content
print(type(byte_content)) # <class 'bytes'>
# 언제 무엇을 사용?
# - HTML, JSON 등 텍스트 → response.text
# - 이미지, 파일 등 → response.content
🚦 HTTP 상태 코드 이해하기
상태 코드는 요청의 결과를 알려주는 3자리 숫자예요.
주요 상태 코드
코드 | 의미 | 설명 |
---|---|---|
200 | OK | 성공! 정상적으로 받았어요 |
404 | Not Found | 페이지를 찾을 수 없어요 |
403 | Forbidden | 접근 권한이 없어요 |
500 | Server Error | 서버에 문제가 있어요 |
상태 코드 확인하기
import requests
# 다양한 상태 코드 테스트
urls = [
"https://httpbin.org/status/200", # 정상
"https://httpbin.org/status/404", # 페이지 없음
"https://httpbin.org/status/500", # 서버 오류
]
for url in urls:
response = requests.get(url)
if response.status_code == 200:
print(f"✅ {url} → 성공!")
elif response.status_code == 404:
print(f"❌ {url} → 페이지 없음")
elif response.status_code == 500:
print(f"🔥 {url} → 서버 오류")
else:
print(f"⚠️ {url} → 코드: {response.status_code}")
🎯 실용적인 예제
예제 1: 웹페이지 정보 수집
import requests
def get_page_info(url):
"""웹페이지 기본 정보 가져오기"""
print(f"🔍 {url} 분석 중...")
# 요청 보내기
response = requests.get(url)
# 정보 수집
info = {
"url": url,
"상태": response.status_code,
"크기": f"{len(response.content):,} bytes",
"타입": response.headers.get('content-type', '알 수 없음'),
"서버": response.headers.get('server', '알 수 없음'),
"응답시간": f"{response.elapsed.total_seconds():.2f}초"
}
# 출력
print("\n📊 페이지 정보:")
for key, value in info.items():
print(f" {key}: {value}")
return info
# 테스트
get_page_info("https://www.python.org")
예제 2: 여러 페이지 확인하기
import requests
import time
def check_websites(urls):
"""여러 웹사이트 상태 확인"""
results = []
for url in urls:
print(f"확인 중: {url}")
try:
# 시작 시간 기록
start_time = time.time()
# 요청 (타임아웃 5초)
response = requests.get(url, timeout=5)
# 응답 시간 계산
response_time = time.time() - start_time
# 결과 저장
results.append({
"url": url,
"status": response.status_code,
"time": f"{response_time:.2f}초",
"success": response.status_code == 200
})
if response.status_code == 200:
print(f" ✅ 정상 ({response_time:.2f}초)")
else:
print(f" ⚠️ 코드: {response.status_code}")
except requests.Timeout:
print(f" ⏰ 타임아웃!")
results.append({
"url": url,
"status": "timeout",
"time": "5초 초과",
"success": False
})
except Exception as e:
print(f" ❌ 오류: {e}")
results.append({
"url": url,
"status": "error",
"time": "-",
"success": False
})
# 서버 부담 줄이기
time.sleep(1)
return results
# 테스트할 사이트들
sites = [
"https://www.google.com",
"https://www.github.com",
"https://httpbin.org/delay/10", # 일부러 느린 응답
]
results = check_websites(sites)
# 결과 요약
print("\n📊 전체 결과:")
success_count = sum(1 for r in results if r["success"])
print(f"성공: {success_count}/{len(results)}")
🔤 인코딩 처리하기
한글 웹사이트를 가져올 때 중요해요!
인코딩이란?
컴퓨터가 문자를 저장하는 방식이에요:
- UTF-8: 한글, 영어, 이모티콘 모두 OK! (가장 많이 사용)
- EUC-KR: 오래된 한글 사이트
- ISO-8859-1: 영어 위주
인코딩 확인 및 설정
import requests
# 한글이 포함된 페이지 요청
response = requests.get("https://httpbin.org/encoding/utf8")
# 인코딩 확인
print(f"서버가 알려준 인코딩: {response.encoding}")
print(f"추측된 인코딩: {response.apparent_encoding}")
# 잘못된 인코딩일 때
if response.encoding == 'ISO-8859-1':
# 올바른 인코딩으로 변경
response.encoding = response.apparent_encoding
print(f"변경된 인코딩: {response.encoding}")
# 이제 한글이 제대로 보여요!
print(response.text[:100])
🛡️ 기본 에러 처리
웹 크롤링에서는 여러 오류가 발생할 수 있어요. 미리 대비해봐요!
자주 발생하는 오류들
import requests
def safe_get(url):
"""안전하게 웹페이지 가져오기"""
try:
# 타임아웃 설정 (10초)
response = requests.get(url, timeout=10)
# 상태 코드 확인
if response.status_code == 200:
print("✅ 성공!")
return response.text
else:
print(f"⚠️ 상태 코드: {response.status_code}")
return None
except requests.Timeout:
print("⏰ 시간 초과: 응답이 너무 느려요")
return None
except requests.ConnectionError:
print("🔌 연결 오류: 인터넷 연결을 확인하세요")
return None
except requests.RequestException as e:
print(f"❌ 요청 오류: {e}")
return None
except Exception as e:
print(f"💥 예상치 못한 오류: {e}")
return None
# 테스트
urls = [
"https://httpbin.org/html", # 정상
"https://httpbin.org/delay/20", # 느린 응답
"https://invalid-url-12345.com", # 잘못된 주소
]
for url in urls:
print(f"\n시도: {url}")
result = safe_get(url)
🎨 User-Agent 설정하기
일부 사이트는 브라우저인지 확인해요. User-Agent를 설정하면 브라우저처럼 보이게 할 수 있어요!
User-Agent란?
# User-Agent는 "나는 누구입니다"라고 알려주는 정보예요
# 기본 requests User-Agent
response = requests.get("https://httpbin.org/user-agent")
print("기본:", response.json())
# 브라우저처럼 보이게 하기
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
response = requests.get("https://httpbin.org/user-agent", headers=headers)
print("변경:", response.json())
헤더 설정 예제
import requests
def get_with_headers(url):
"""헤더를 포함한 요청"""
# 브라우저처럼 보이는 헤더
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'text/html,application/xhtml+xml',
'Accept-Language': 'ko-KR,ko;q=0.9,en;q=0.8',
}
response = requests.get(url, headers=headers)
# 서버가 받은 헤더 확인
if url == "https://httpbin.org/headers":
print("서버가 받은 헤더:")
for key, value in response.json()['headers'].items():
print(f" {key}: {value}")
return response
# 테스트
get_with_headers("https://httpbin.org/headers")
💡 퀴즈: requests 이해도 체크
Q1. HTML 내용을 가져올 때 사용하는 속성은?
response.html
response.text
response.content
response.data
💡 정답 확인
정답: 2번 response.text
response.text
: 텍스트 형태의 응답 (HTML, JSON 등)response.content
: 바이트 형태의 응답 (이미지, 파일 등)
Q2. 상태 코드 200은 무엇을 의미하나요?
💡 정답 확인
정답: 요청이 성공적으로 처리되었음을 의미
200 OK는 가장 일반적인 성공 상태 코드예요!
📝 실습: 날씨 정보 가져오기
import requests
from datetime import datetime
def get_weather_page():
"""날씨 정보 페이지 가져오기 (연습용)"""
# httpbin의 HTML 페이지 사용 (실제 날씨 사이트 대신)
url = "https://httpbin.org/html"
print("🌤️ 날씨 정보 가져오는 중...")
# 헤더 설정
headers = {
'User-Agent': 'Weather Bot 1.0'
}
try:
# 요청 보내기
response = requests.get(url, headers=headers, timeout=5)
if response.status_code == 200:
print("✅ 성공적으로 가져왔습니다!")
# 페이지 정보
print(f"\n📊 페이지 정보:")
print(f" 크기: {len(response.text):,} 글자")
print(f" 응답 시간: {response.elapsed.total_seconds():.2f}초")
print(f" 수집 시간: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
# HTML에서 제목 찾기 (간단한 방법)
html = response.text
if '<title>' in html and '</title>' in html:
start = html.find('<title>') + 7
end = html.find('</title>')
title = html[start:end]
print(f" 페이지 제목: {title}")
return response.text
else:
print(f"❌ 오류: 상태 코드 {response.status_code}")
return None
except Exception as e:
print(f"❌ 오류 발생: {e}")
return None
# 실행
html_content = get_weather_page()
if html_content:
print(f"\n📄 HTML 미리보기:")
print(html_content[:300])
✅ requests 마스터 체크리스트
✅ requests 마스터 체크리스트
🚀 다음 단계
requests로 웹페이지를 가져올 수 있게 되었나요? 이제 가져온 HTML에서 원하는 정보를 추출하는 BeautifulSoup을 배워볼게요!
Last updated on