[스터디 노트] 웹 스크래핑을 위한 기초 - requests 라이브러리

소환인·2023년 11월 3일
0

스터디노트

목록 보기
18/48

이전 포스트에서 웹 스크래핑을 공부하면서 기초를 다지기 위한 내용들을 정리했습니다. HTTP 요청을 위한 두 가지 방식, get방식과 post방식에 대해 알아보고, urllib.urlopen()을 사용해 웹페이지에 접근해 원하는 정보를 얻는 방법도 살펴보았습니다. 오늘은 urllib.urlopen()보다 더 많이 사용되는 request 라이브러리에 대해 공부하고 정리해 보았습니다. 본문의 내용들은 realpython.com을 참고하여 정리했습니다.

1. urlopenrequests

웹 스크래핑이나 API 상호작용을 위한 파이썬 스크립트를 작성할 때, urllib 라이브러리의 urlopen 함수와 외부 requests 라이브러리 사이에서 선택해야 할 수 있습니다. 이 두 가지 방법은 기능적으로 유사해 보일 수 있지만, 사용 편의성과 코드의 가독성 면에서 차이가 있습니다.

urlopen의 기본적인 접근 방식

urlopen은 파이썬의 표준 라이브러리인 urllib에 포함된 함수로, 기본적인 HTTP 요청을 수행할 수 있는 도구를 제공합니다. 이 함수를 사용하여 GET 또는 POST 요청을 실행하고 결과를 HTTPResponse 객체로 받을 수 있습니다. 하지만, urlopen은 사용시 몇가지 불편함이 있습니다.

  • 데이터 인코딩과 헤더 설정이 수동으로 이루어져야 합니다. 직접 헤더를 확인해서 인코딩 방식을 확인하고 디코딩시 방식을 지정해주어야 합니다.
  • 에러 처리를 위해 추가적인 코드 작성이 필요합니다. urlopen() 사용시 에러를 다루는 방법을 어제 포스트에선 정리하지 않았습니다. 곧 관련 내용을 정리하도록 하겠습니다.
  • 응답 객체를 사용한 후에는 명시적으로 리소스를 해제하기 위해 .close() 메서드를 호출해야 합니다.

requests: 사용자 친화적인 HTTP 라이브러리

반면, requests 라이브러리는 "HTTP for Humans"라는 슬로건 아래, 최소한의 설정과 코드로 HTTP 요청을 쉽게 수행할 수 있게 설계되었습니다. requests는 다음과 같은 이점을 제공합니다

  • 인코딩을 자동으로 처리하여 따로 지정할 필요가 없습니다. response.text를 사용할 때, requests는 적절한 문자 인코딩을 알아서 선택합니다.
  • 헤더 설정이 매우 간단합니다.
  • 예외 처리가 훨씬 명확하고, .raise_for_status() 메서드를 통해 쉽게 에러를 확인할 수 있습니다.
  • 리소스 관리가 더욱 용이합니다. 많은 경우에 명시적인 리소스 해제가 필요 없습니다.

이러한 차이점은 특히 웹 스크래핑이나 API와의 상호 작용을 자주 수행하는 개발자에게 큰 이점을 제공해 많은 사람들이 urlopen보다는 requests 라이브러리를 사용해 HTTP 요청을 수행합니다.

알겠습니다. 2번 항목인 Response 객체와 인코딩/디코딩에 대해 다음과 같이 작성할 수 있습니다:

2. 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 라이브러리를 사용할 때 데이터 처리를 더 쉽게 해줍니다.

3. HTTP GET 요청: 쿼리 문자열 사용하기

기본적인 사용법은 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()를 통해 어떤 정보들을 포함하고 있는지 키값을 확인합니다. 확인한 키를 바탕으로 아래서 하나씩 값들을 출력하고 있습니다.

4. HTTP POST 요청

HTTP POST 요청은 웹 서버에 데이터를 전송할 때 사용됩니다. requests 라이브러리는 이 과정을 매우 단순화합니다. POST 요청의 두 가지 일반적인 사용 사례인 폼 데이터와 JSON 데이터 전송을 아래 예제를 통해 설명합니다.

폼 데이터로 POST 요청하기

웹 양식을 통해 데이터를 전송하는 것과 유사하게, 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 필드에 저장하고 응답으로 반환합니다.

JSON 데이터로 POST 요청하기

현대의 웹 API는 종종 JSON 형식의 데이터를 받습니다. requestsjson 인자를 통해 자동으로 데이터를 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 데이터를 담고 있으며, 이를 통해 서버가 데이터를 올바르게 받았는지 확인할 수 있습니다.

profile
돌고돌아

0개의 댓글