파이썬의 requests 라이브러리는 HTTP 요청을 간편하게 수행할 수 있도록 설계된 강력한 도구입니다. 웹 페이지 콘텐츠를 가져오거나 RESTful API와 상호 작용하는 등 다양한 네트워크 작업을 수행할 때 필수적으로 활용됩니다. 이 라이브러리는 직관적인 API를 제공하여 복잡한 HTTP 통신을 쉽게 구현할 수 있게 돕습니다.
1. 라이브러리 설치 및 기본 사용법
1.1. 설치
requests 라이브러리를 사용하려면 pip를 통해 설치해야 합니다. 웹 스크래핑을 위해 HTML 파싱이 필요하다면 BeautifulSoup나 lxml과 같은 라이브러리도 함께 설치하는 것이 좋습니다.
pip install requests beautifulsoup4 lxml
1.2. 응답 객체 이해하기
requests 라이브러리로 HTTP 요청을 보내면 Response 객체가 반환됩니다. 이 객체에는 서버로부터 받은 응답에 대한 다양한 정보가 담겨 있습니다. 주요 속성들은 다음과 같습니다:
response.text: 응답 본문을 유니코드 문자열로 반환합니다.response.encoding: 응답의 인코딩 방식을 접근하거나 설정합니다.response.url: 요청을 보낸 최종 URL을 반환합니다. (리다이렉션이 발생한 경우 최종 URL)response.content: 응답 본문을 바이트(bytes) 형태로 반환합니다. 이미지나 비디오 등 바이너리 데이터 처리 시 유용합니다.response.status_code: HTTP 상태 코드(예: 200, 404)를 반환합니다.response.headers: 응답 헤더를 딕셔너리 형태로 반환합니다.
다음은 간단한 요청을 통해 응답 객체의 속성들을 확인하는 예시입니다:
import requests
# 요청을 보낼 대상 URL
target_url = 'https://www.naver.com'
# GET 요청 보내기
http_response = requests.get(target_url)
# 응답 객체의 다양한 속성 출력
print(f"응답 객체 타입: {type(http_response)}")
print(f"응답 상태 코드: {http_response.status_code}")
print(f"요청 URL: {http_response.url}")
print(f"응답 인코딩: {http_response.encoding}")
print(f"응답 헤더: {http_response.headers}")
print(f"응답 텍스트 (일부): {http_response.text[:200]}...") # 긴 내용을 모두 출력하지 않기 위해 일부만 출력
print(f"응답 바이너리 데이터 길이: {len(http_response.content)} 바이트")
1.3. 리다이렉션 처리
requests는 기본적으로 HTTP 리다이렉션(예: 301, 302)을 자동으로 따릅니다. 하지만 리다이렉션을 추적하지 않고 원본 응답을 받고 싶다면 allow_redirects=False 매개변수를 사용할 수 있습니다. 이 경우, 응답 헤더의 Location 필드에서 리다이렉션 대상 URL을 확인할 수 있습니다.
import requests
# 리다이렉션이 발생하는 URL
redirect_test_url = 'https://httpbin.org/redirect/1'
# 리다이렉션을 따르지 않도록 설정
initial_response = requests.get(redirect_test_url, allow_redirects=False)
print(f"원본 응답 상태 코드: {initial_response.status_code}")
if 'Location' in initial_response.headers:
print(f"리다이렉션 대상 URL: {initial_response.headers['Location']}")
else:
print("리다이렉션 헤더가 없습니다.")
1.4. 요청 타임아웃 설정
네트워크 지연이나 서버 응답 없음으로 인해 요청이 무한정 기다리는 것을 방지하려면 timeout 매개변수를 사용하여 타임아웃 시간을 설정할 수 있습니다. 지정된 시간 내에 응답이 없으면 requests.exceptions.Timeout 예외가 발생합니다.
import requests
# 응답이 지연될 수 있는 URL (예: 5초 지연)
slow_response_url = 'https://httpbin.org/delay/5'
try:
# 3초 타임아웃 설정
timeout_response = requests.get(slow_response_url, timeout=3)
print(f"요청 성공! 상태 코드: {timeout_response.status_code}")
except requests.exceptions.Timeout:
print("요청이 지정된 시간 내에 완료되지 않아 타임아웃되었습니다.")
except requests.exceptions.RequestException as e:
print(f"요청 중 오류 발생: {e}")
# 연결 타임아웃과 읽기 타임아웃을 개별적으로 설정할 수도 있습니다.
# requests.get('https://example.com', timeout=(5, 10)) # 연결 5초, 데이터 읽기 10초
2. GET 요청 보내기
웹에서 데이터를 조회할 때 주로 사용되는 GET 요청은 requests.get() 메서드를 통해 수행됩니다. 쿼리 문자열 매개변수는 params 인수를 사용하여 전달할 수 있으며, User-Agent와 같은 HTTP 헤더는 headers 인수로 설정합니다. requests는 params로 전달된 데이터를 자동으로 URL 인코딩합니다.
import requests
# GitHub API의 리포지토리 검색 엔드포인트
github_search_url = 'https://api.github.com/search/repositories'
# 검색 쿼리 매개변수
search_parameters = {
'q': 'python web-scraping',
'sort': 'stars',
'order': 'desc'
}
# 사용자 에이전트 헤더 설정 (선택 사항, 일부 웹사이트에서 필요)
custom_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
# GET 요청 보내기
api_response = requests.get(
url=github_search_url,
params=search_parameters,
headers=custom_headers
)
# 응답 확인
if api_response.status_code == 200:
print("GET 요청 성공:")
# JSON 형식의 응답을 파이썬 딕셔너리로 변환
data = api_response.json()
print(f"총 검색 결과: {data['total_count']}개")
if data['items']:
print(f"첫 번째 결과: {data['items'][0]['full_name']}")
else:
print(f"GET 요청 실패: 상태 코드 {api_response.status_code}")
3. POST 요청 보내기
데이터를 서버에 제출하거나 리소스를 생성할 때 POST 요청을 사용합니다. requests.post() 메서드를 사용하며, 요청 본문에 포함될 데이터는 data 인수를 통해 전달합니다. data 인수는 딕셔너리 형태로 전달될 수 있으며, 폼 데이터(application/x-www-form-urlencoded)로 전송됩니다. JSON 데이터를 전송하려면 json 인수를 사용합니다.
import requests
import json
# 테스트용 REST API 엔드포인트 (가상 게시글 생성)
post_api_endpoint = 'https://jsonplaceholder.typicode.com/posts'
# 서버로 전송할 데이터 (JSON 형식으로 전송할 예정)
post_payload = {
'title': 'requests 라이브러리로 전송한 글',
'body': '이것은 파이썬 requests를 사용한 POST 요청 예시입니다.',
'userId': 1
}
# 사용자 에이전트 헤더 설정
post_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Content-Type': 'application/json' # JSON 데이터를 보내므로 Content-Type을 명시
}
# POST 요청 보내기 (json 인수를 사용하여 자동 직렬화)
post_response = requests.post(
url=post_api_endpoint,
json=post_payload, # 딕셔너리를 JSON으로 자동 변환하여 전송
headers=post_headers
)
# 응답 확인
if post_response.status_code == 201: # 201 Created는 POST 요청 성공을 의미
print("POST 요청 성공:")
created_resource = post_response.json()
print(f"생성된 리소스: {json.dumps(created_resource, indent=2, ensure_ascii=False)}")
else:
print(f"POST 요청 실패: 상태 코드 {post_response.status_code}")
print(f"응답 본문: {post_response.text}")
4. 프록시 서버 사용
익명성을 확보하거나 지역 제한을 우회해야 할 때 프록시 서버를 사용할 수 있습니다. requests는 proxies 매개변수를 통해 프록시 설정을 지원합니다. 이 매개변수는 프로토콜(http, https)을 키로 하고 프록시 주소를 값으로 하는 딕셔너리 형태를 가집니다.
import requests
# 요청을 보낼 URL (예: 자신의 IP 주소를 확인하는 사이트)
ip_check_url = 'https://httpbin.org/ip'
# 사용할 프록시 설정 (예시, 실제 작동하는 프록시 주소로 변경 필요)
# 'http' 또는 'https' 프로토콜에 따라 다른 프록시를 지정할 수 있습니다.
proxy_configurations = {
'http': 'http://123.45.67.89:8080', # 예시 HTTP 프록시 주소
'https': 'http://123.45.67.89:8080' # 예시 HTTPS 프록시 주소
}
# 사용자 에이전트 헤더
request_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
try:
# 프록시를 사용하여 GET 요청 보내기
proxy_response = requests.get(
url=ip_check_url,
headers=request_headers,
proxies=proxy_configurations,
timeout=10 # 프록시 연결 지연에 대비한 타임아웃 설정
)
if proxy_response.status_code == 200:
print("프록시를 통한 요청 성공:")
print(f"응답 본문: {proxy_response.json()}")
else:
print(f"프록시 요청 실패: 상태 코드 {proxy_response.status_code}")
except requests.exceptions.ProxyError as e:
print(f"프록시 연결 오류: {e}")
except requests.exceptions.RequestException as e:
print(f"요청 중 일반 오류 발생: {e}")
참고: 위의 프록시 주소는 예시이며, 실제 작동하는 프록시 서버의 주소로 변경해야 합니다. 무료 프록시는 불안정할 수 있으므로, 안정적인 작업을 위해서는 유료 프록시 서비스를 고려하는 것이 좋습니다.
5. 세션(Session) 및 쿠키 관리
특정 웹사이트는 로그인 상태 유지 또는 사용자 세션 관리를 위해 쿠키를 사용합니다. requests.Session() 객체를 사용하면 여러 요청 사이에 쿠키를 자동으로 유지하고 재사용할 수 있어, 브라우저의 동작을 효과적으로 시뮬레이션할 수 있습니다.
requests.Session(): 세션 객체를 생성하며, 이 객체를 통해 보낸 모든 요청은 동일한 쿠키와 세션 정보를 공유합니다.session.cookies: 세션에 저장된 쿠키들을RequestsCookieJar객체 형태로 접근할 수 있습니다.
import requests
# 세션 객체 생성
my_session = requests.Session()
# 1. 세션에 쿠키 설정 요청 (httpbin.org는 쿠키를 설정하고 확인하는 데 유용)
# 'mycookie'라는 이름으로 'myvalue' 값을 가진 쿠키를 설정합니다.
set_cookie_url = 'https://httpbin.org/cookies/set?mycookie=myvalue'
print(f"쿠키 설정 요청: {set_cookie_url}")
set_response = my_session.get(set_cookie_url)
print(f"쿠키 설정 요청 상태 코드: {set_response.status_code}")
# 현재 세션에 저장된 쿠키 확인
print(f"세션에 저장된 쿠키: {my_session.cookies.get('mycookie')}")
# 2. 설정된 쿠키가 자동으로 전송되는지 확인
# 이 요청은 이전 요청에서 설정된 'mycookie'를 자동으로 포함하여 전송합니다.
check_cookie_url = 'https://httpbin.org/cookies'
print(f"\n쿠키 확인 요청: {check_cookie_url}")
check_response = my_session.get(check_cookie_url)
print(f"쿠키 확인 요청 상태 코드: {check_response.status_code}")
# 응답 본문에서 전송된 쿠키 확인 (httpbin.org는 받은 쿠키를 JSON으로 반환)
if check_response.status_code == 200:
print(f"확인된 쿠키: {check_response.json()}")
else:
print(f"쿠키 확인 실패: {check_response.text}")
# 세션을 통해 POST 요청을 보낼 때도 쿠키는 자동으로 유지됩니다.
post_data = {'item': 'new_item'}
post_url = 'https://httpbin.org/post' # 임시 POST 엔드포인트
print(f"\n세션을 통한 POST 요청 (쿠키 유지): {post_url}")
post_response_with_session = my_session.post(post_url, data=post_data)
print(f"POST 응답 상태 코드: {post_response_with_session.status_code}")
print(f"POST 응답 본문 (일부): {post_response_with_session.text[:100]}...")