프로그래밍/Python

Python3 requests에서 r.text와 r.content의 차이

2020. 7. 21. 17:10

거기서 끄투를 왜해ㅋㅋㅋㅋㅋ

1. 개요

Python3에서 불과 3~4년 전만 하더라도 urlib를 사용하여 HTTP 자원에 접근하는 코드가 많았지만, 이제는 거의다 requests 모듈을 사용하는 추세이다. 그만큼 requests 모듈의 편리성과 확장성이 Pythonic하다고 볼 수 있다. requests 모듈에서 HTTP Response에 접근하는 방법은 크게 두가지가 있다. 하나는 r.text이고 하나는 r.content이다.

 

※ 이 글에서 설명하는 내용은 다음과 같은 코드가 실행된 상태라고 가정한다.

import requests

url = 'https://www.example.com/'
r = requests.get(url)

 

2. r.text

 r.text의 경우엔 HTTP Request를 보낸 URL에서 readable한 내용을 가져올 때 사용한다. r.text를 사용하는 경우에 r.encoding 이라는 리소스를 사용할 수가 있는데, 이는 requests 모듈 자체에서 Request를 바탕으로 받은 Response를 자동으로 encoding을 추측하고 해당 인코딩 값으로 디코드시킨 값이 바로 r.text이다. 따라서 r.text의 경우 이미 requests 모듈내에서 한 번 가공된 값이라고 볼 수 있다.

 

3. r.content

 r.content의 경우에도 gzip이나 defalate 알고리즘에 의해 압축된 HTTP Response를 unzip했다는 점에서 가공되었다고 볼 수 있다. 하지만 r.text는 r.encoding으로 디코드되었지만 r.content는 디코드되지 않은 점에서 차이가 있다. 결론적으로 r.content에는 HTTP Response의 body 부분이 bytes 상태로 그대로 저장되어 있다. 따라서 이미지 등의 미디어 파일을 다른 서버로부터 받고 싶을 때는 r.content를 사용해야 한다. r.text의 경우엔 디코드된 상태이기 때문에 절대로 원본 파일일 수가 없다.

3. r.content를 사용해야 하는 경우 ?

 r.text의 경우 문서의 인코딩 방식을 자동적으로 추측하고 그에 맞게 디코딩해준다는 점에서는 굉장히 편리하다. 그렇지만 다음과 같은 경우를 보면 인코딩 에러가 나타난다.

 

# coding: utf-8
import requests
from bs4 import BeautifulSoup

def main():
    url = 'https://docs.python.org/ko/3/library/weakref.html'
    r = requests.get(url)
    soup = BeautifulSoup(r.text, 'html.parser')
    print(r.encoding)
    print(soup.prettify())


if __name__ == '__main__':
    main()

 

 만약 https://docs.python.org 만을 파싱하는 경우라고 한다면 r.encoding = 'utf-8' 을 사용하여 해결할 수 있겠으나, 만약 docs.python.org 외의 다른 웹사이트도 파싱하는 경우라면? r.encoding = 'utf-8' 을 사용하여 r.text를 가져오는 경우는 너무나 비범용적이다. 따라서 이 경우 r.content를 사용하면 한글 데이터를 보존할 수 있게 된다.