이전 포스트에서 웹 스크래핑을 공부하면서 기초를 다지기 위한 내용들을 정리했습니다. HTTP 요청을 위한 두 가지 방식, get
방식과 post
방식에 대해 알아보고, urllib.urlopen()
을 사용해 웹페이지에 접근해 원하는 정보를 얻는 방법도 살펴보았습니다. 오늘은 urllib.urlopen()
보다 더 많이 사용되는 request 라이브러리에 대해 공부하고 정리해 보았습니다. 본문의 내용들은 realpython.com을 참고하여 정리했습니다.
urlopen
과 requests
웹 스크래핑이나 API 상호작용을 위한 파이썬 스크립트를 작성할 때, urllib
라이브러리의 urlopen
함수와 외부 requests
라이브러리 사이에서 선택해야 할 수 있습니다. 이 두 가지 방법은 기능적으로 유사해 보일 수 있지만, 사용 편의성과 코드의 가독성 면에서 차이가 있습니다.
urlopen
의 기본적인 접근 방식
urlopen
은 파이썬의 표준 라이브러리인 urllib
에 포함된 함수로, 기본적인 HTTP 요청을 수행할 수 있는 도구를 제공합니다. 이 함수를 사용하여 GET 또는 POST 요청을 실행하고 결과를 HTTPResponse
객체로 받을 수 있습니다. 하지만, urlopen
은 사용시 몇가지 불편함이 있습니다.
.close()
메서드를 호출해야 합니다.requests
: 사용자 친화적인 HTTP 라이브러리
반면, requests
라이브러리는 "HTTP for Humans"라는 슬로건 아래, 최소한의 설정과 코드로 HTTP 요청을 쉽게 수행할 수 있게 설계되었습니다. requests
는 다음과 같은 이점을 제공합니다
response.text
를 사용할 때, requests
는 적절한 문자 인코딩을 알아서 선택합니다..raise_for_status()
메서드를 통해 쉽게 에러를 확인할 수 있습니다.이러한 차이점은 특히 웹 스크래핑이나 API와의 상호 작용을 자주 수행하는 개발자에게 큰 이점을 제공해 많은 사람들이 urlopen보다는 requests 라이브러리를 사용해 HTTP 요청을 수행합니다.
알겠습니다. 2번 항목인 Response
객체와 인코딩/디코딩에 대해 다음과 같이 작성할 수 있습니다:
Response
객체와 인코딩/디코딩requests
라이브러리를 사용하여 웹 요청을 수행하면, 서버로부터 반환되는 정보를 담고 있는 Response
객체를 받게 됩니다. 이 객체는 요청에 대한 상태 코드, 헤더, 콘텐츠 등을 포함하고 있습니다.
status_code
: 서버로부터의 HTTP 응답 상태 코드를 나타냅니다 (예: 200, 404 등).headers
: 응답 헤더를 사전 형태로 제공합니다.text
: 응답 본문을 문자열로 제공하며, requests
는 응답 헤더를 기반으로 적절한 인코딩을 자동으로 선택합니다.content
: 응답 본문을 바이트 형태로 제공합니다, 주로 바이너리 데이터 처리에 사용됩니다.requests
는 사용자 입장에서 인코딩을 간편하게 처리합니다. 서버에서 Content-Type
헤더와 함께 인코딩 타입을 보내면, requests
는 이를 감지하고 자동으로 적절한 인코딩 방식을 Response
객체에 적용합니다. 이렇게 하면 사용자는 별도로 인코딩 방식을 지정하거나 변환할 필요 없이, response.text
속성을 통해 바로 문자열 데이터에 접근할 수 있습니다.
만약 자동 인코딩이 잘못되었다고 판단되는 경우, response.encoding
속성을 사용하여 수동으로 인코딩을 지정할 수 있습니다. 서버가 Content-Type
헤더를 제공하지 않거나 잘못된 인코딩을 제공하는 경우 사용할 수 있습니다.
response.encoding = 'utf-8' # 수동으로 인코딩 설정
print(response.text) # 인코딩이 적용된 텍스트로 응답 본문 출력
이러한 기능들은 requests
라이브러리를 사용할 때 데이터 처리를 더 쉽게 해줍니다.
기본적인 사용법은 requests.get(url)
과 같이 매우 간단하지만, 실제 웹 서비스와 상호작용할 때는 주로 쿼리 문자열을 함께 전송해야 할 때가 많습니다. 여기서는 GitHub의 API를 사용하여 특정 조건을 만족하는 저장소를 검색하는 예제를 통해 requests.get
의 활용 방법을 살펴보겠습니다.
import requests
# GitHub API로 요청할 URL
url = 'https://api.github.com/search/repositories'
# 검색 조건을 파라미터로 설정
param = {'q': 'requests+language:python'}
# param = [('q', 'requests+language:python'})] # 튜플 형태로도 가능
# GET 요청을 수행하고 응답을 받음
response = requests.get(url, params=param)
# 응답 내용을 JSON으로 파싱
json_response = response.json()
print('length: ', len(json_response))
repository = json_response['items'][0]
# JSON 응답에서 각 키에 대한 정보 출력
print('json_keys: ', json_response.keys())
print('json - total_count: ', json_response['total_count']) # 총 저장소 수
print('json - incomplete_results: ', json_response['incomplete_results']) # 결과의 완전성 여부
print('json - items: ', json_response['items'][0]) # 첫 번째 저장소 정보
이 코드는 requests
를 사용하여 GitHub의 저장소 검색 API에 GET 요청을 보냅니다. 요청의 파라미터로는 'requests' 라이브러리와 파이썬 언어를 조건으로 하는 검색 쿼리를 사용합니다. 쿼리 문자열은 params=
인자를 통해 전달하며 딕셔너리 형태, 혹은 (키, 값)을 튜플 형태로 묶어서 전달할 수도 있습니다.
응답 내용을 response.json()
메서드를 통해 파이썬 객체로 변환할 수 있습니다. 이 객체는 검색된 저장소에 대한 다양한 정보를 포함하고 있습니다. json_response.keys()
를 통해 어떤 정보들을 포함하고 있는지 키값을 확인합니다. 확인한 키를 바탕으로 아래서 하나씩 값들을 출력하고 있습니다.
HTTP POST 요청은 웹 서버에 데이터를 전송할 때 사용됩니다. requests
라이브러리는 이 과정을 매우 단순화합니다. POST 요청의 두 가지 일반적인 사용 사례인 폼 데이터와 JSON 데이터 전송을 아래 예제를 통해 설명합니다.
웹 양식을 통해 데이터를 전송하는 것과 유사하게, requests.post
함수를 사용하여 application/x-www-form-urlencoded
포맷의 데이터를 서버로 전송할 수 있습니다.
import requests
# POST 요청을 위한 URL
url = 'https://httpbin.org/post'
# 폼 데이터
data = {'key': 'value'}
# 폼 데이터와 함께 POST 요청을 수행
response = requests.post(url, data=data)
이 코드는 서버에 key=value
형식의 폼 데이터를 전송합니다. httpbin.org
는 이를 받아 form
필드에 저장하고 응답으로 반환합니다.
현대의 웹 API는 종종 JSON 형식의 데이터를 받습니다. requests
는 json
인자를 통해 자동으로 데이터를 JSON 형식으로 인코딩하고, 적절한 Content-Type
헤더를 설정합니다.
# JSON 데이터와 함께 POST 요청을 수행
response = requests.post(url, json=data)
이 경우 httpbin.org
는 받은 JSON 데이터를 data
필드에 문자열 형태로 반환합니다. 동시에, json
필드에는 파싱된 JSON 객체가 담겨서 오게 됩니다.
POST 요청에 대한 서버의 응답을 확인해 보겠습니다.
# 서버로부터 반환된 JSON 데이터 파싱
json_response = response.json()
# 상태 코드와 응답에 포함된 JSON 키 확인
print('status code :', response.status_code)
print('json keys :', json_response.keys())
# 서버로부터 반환된 JSON 내용 출력
print('json - data :', json_response['data']) # JSON으로 전송된 원시 데이터
print('json - json :', json_response['json']) # 서버에서 파싱된 JSON 객체
print('json["Content-Type"] :', json_response['headers']['Content-Type']) # 응답 헤더의 Content-Type
위 코드는 응답의 상태 코드를 출력하고, JSON 응답의 주요 부분을 확인합니다. 'data' 키는 서버에 전송된 데이터 문자열을 담고 있으며, 이는 위의 예제 코드에서 사용자가 전달한 원본 JSON 데이터입니다. 'json' 키는 서버에서 파싱된 JSON 데이터를 담고 있으며, 이를 통해 서버가 데이터를 올바르게 받았는지 확인할 수 있습니다.