최근 자동화나 데이터 관련해서 외주를 받아 작업을 하고 있다. 정적 웹 페이지라고 판단된다면 request, bs4을 이용해 처리했고 동적인 페이지라고 생각이 들면 무조건 selenium으로 페이지에 직접 들어가 태그를 탐색해서 데이터를 가져오곤 했다. 하지만 selenium을 이용하여 코드를 작성하면 속도가 느리다는 문제와 크롬드라이버의 의존성이 크다는 문제가 있었다.
설상가상으로 이번에 외주 받은 프로그램에서 사용하는 크롬 버전은 116.0.5845.140이었는데 이때 크롬에서 [$TBD][1472492] CVE-2023-4572 결함으로 인해서 140 버전의 크롬 드라이버를 다운로드하지 못해 난처한 상황이 맞이하곤 했다. (다행히 패치한 141 버전이 외주 마감일 2일 전에 배포되어서 외주를 성공적으로 끝내긴 했다.)
이 일이 있고 난 뒤에는 동적인 페이지에서 데이터를 가져올 때, 굳이 selenium과 chormdriver을 사용해야 하나라는 생각이 들었고, 관련 코드를 깃헙에서 돌아다니면서 보던 도중에 내가 생각했던 부분을 request.session()을 이용하여 처리하는 아름다운 코드를 보게 되었다. 그래서 requests의 기능 중에서 requests.get()만 사용해 본 나를 반성하고 이번에 requests 라이브러리에 대해 공부하고 정리해보고자 한다.
Requests
requests는 HTTP 통신을 위해 만들어진 python 라이브러리이다. 기본 탑재된 표준 라이브러리가 아니라서 pip 패키지 툴로 설치해줘야 하며 header 설정(및 쿠키), body 설정이 가능하다.
pip install requests
Http 통신
일반적으로 requests을 통해 http 통신하는 방법은 아래와 같다.
r = requests.get('https://api.github.com/events')
r = requests.post('https://httpbin.org/post', data={'key': 'value'})
r = requests.put('https://httpbin.org/put', data={'key': 'value'})
r = requests.delete('https://httpbin.org/delete')
r = requests.head('https://httpbin.org/get')
r = requests.options('https://httpbin.org/get')
추가 기능
- URL에 매개변수 전달하기
URL의 쿼리 문자열에 데이터를 전송하는 경우 URL에서 물음표 뒤에 키/값의 형태로 직접 URL을 구성하여 전송한다. requests에서는 이를 params 인수를 이용하여 처리할 수 있다.
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get('https://httpbin.org/get', params=payload)
# https://httpbin.org/get?key2=value2&key1=value1
payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
r = requests.get('https://httpbin.org/get', params=payload)
# https://httpbin.org/get?key1=value1&key2=value2&key2=value3
- 응답내용 확인하기
requests.get()으로 받은 객체는 text을 이용하여 읽을 수 있다. get 요청은 서버의 콘텐츠를 자동으로 디코딩하며 대부분의 유니코드 문자는 원활하게 디코딩해서 넘어온다. get 요청을 하면 Requests는 Http 헤더를 기반으로 응답 인코딩에 대해 정보를 바탕으로 추측하여 텍스트를 인코딩할 때 활용한다. get 요청 시 사용되는 인코딩 속성은 encoding을 이용하여 확인하고 변경할 수 있다.
import requests
r = requests.get('https://api.github.com/events')
r.text
'[{"repository":{"open_issues":0,"url":"https://github.com/...
r.encoding
'utf-8'
r.encoding = 'ISO-8859-1'
- 바이너리 응답
텍스트가 아닌 요청인 경우에는 응답 본문에 바이트로 접근할 수 있다.
r.content
b'[{"repository":{"open_issues":0,"url":"https://github.com/...
- json 응답
json 데이터를 처리하는 경우 내장된 json 디코더를 사용한다. 만약 응답 코드가 204이거나 응답받은 데이터에 json 데이터가 없을 경우에는 r.json()에서는 requests.exceptions.JSONDecodeError을 일으킨다.
import requests
r = requests.get('https://api.github.com/events')
r.json()
[{'repository': {'open_issues': 0, 'url': 'https://github.com/...
- 헤더 설정
요청 시 http header을 추가하려면 dict() 형태로 데이터를 지정하여 넘겨준다. 응답받은 헤더를 확인하려면 headers을 이용하여 확인한다. 응답받은 헤더는 dict() 형태로 되어 있기 때문에, r.headers ['Content-Type']처럼 접근하여 데이터를 가져올 수 있다. headers에 내용을 추가하려고 한다면, headers.updated()을 이용하여 헤더에 값을 추가할 수 있다.
url = 'https://api.github.com/some/endpoint'
headers = {'user-agent': 'my-app/0.0.1'}
r = requests.get(url, headers=headers)
r.headers
## {
## 'content-encoding': 'gzip',
## 'transfer-encoding': 'chunked',
## 'connection': 'close',
## 'server': 'nginx/1.0.4',
## 'x-runtime': '148ms',
## 'etag': '"e1ca502697e5c9317743dc078f67693f"',
## 'content-type': 'application/json'
## }
s.headers.update({'Accept': 'application/json'})
- 응답 상태 코드
status_code을 이용하여 http 상태 코드를 확인할 수 있다.
r = requests.get('https://httpbin.org/get')
r.status_code
# 200
- Post 요청 시 body에 데이터 담아 요청
post요청 시 body에 데이터를 담아 요청 시에는 data인수에 dict() 형태의 데이터를 전달한다.
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.post('https://httpbin.org/post', data=payload)
print(r.text)
# {
# ...
# "form": {
# "key2": "value2",
# "key1": "value1"
# },
# ...
# }
- 쿠키
응답에 일부 쿠키가 포함되어 있다면 cookies을 통해 접근할 수 있다.
url = 'https://httpbin.org/cookies'
cookies = dict(cookies_are='working')
r = requests.get(url, cookies=cookies)
r.text
# '{"cookies": {"cookies_are": "working"}}'
Session
세션(Session)은 HTTP 요청과 응답 사이에 유지되는 상태 정보를 저장할 수 있는 기능이다. 세션은 웹 사이트에 접근할 때 사용자 인증이 필요한 경우, 접근 제한이 걸려 있거나, 상태 정보가 저장되어 있는 경우에 사용된다. 세션은 웹 서버에 접속할 때 생성되고, 접속을 종료할 때 세션 유지를 종료한다.
세션을 사용하면 쿠키와 같은 상태 정보를 저장할 수 있고, 요청(Request)과 응답(Response) 사이에 연결 상태를 유지할 수 있다. 이를 이용하면 사용자 인증이 필요한 웹 사이트에 접근할 수 있거나, 쿠키를 사용해서 접근 제한이 걸려 있거나, 상태 정보가 저장되어 있는 웹 사이트에 지속적인 접근이 가능하다.
import requests
# 세션을 생성합니다.
session = requests.Session()
# 세션을 사용해서 메인 페이지를 요청합니다.
response = session.get("https://www.example.com")
# 응답의 HTML 코드를 출력합니다.
print(response.text)
# 세션을 종료합니다.
session.close()
또한 with 구문을 이용하여 with 구문내에서만 세션을 유지하여 사용할 수도 있다. wtih 구문이 끝나면 세션이 종료된다.
import requests
with requests.Session() as session:
print(session.cookies.get_dict()) # {}
response = session.get('http://google.com')
# {'AEC': 'Ad49MVGzf2rt5u6ObCPLjVzjrRqRMuYhCFG3iH7Ui8-banKZJ3dpZ_4wCA'}
print(session.cookies.get_dict())
참조
https://github.com/psf/requests/tree/c45a4dfe6bfc6017d4ea7e9f051d6cc30972b310
GitHub - psf/requests: A simple, yet elegant, HTTP library.
A simple, yet elegant, HTTP library. Contribute to psf/requests development by creating an account on GitHub.
github.com
Python 세션 유지 (Request 모듈 사용)
1. Session 설명 세션(Session)은 HTTP 요청과 응답 사이에 유지되는 상태 정보를 저장할 수 있는 기능이다. 세션은 웹 사이트에 접근할 때 사용자 인증이 필요한 경우, 접근 제한이 걸려 있거나, 상태
mallard28.tistory.com
https://bobbyhadz.com/blog/how-to-use-cookies-in-python-requests
Python: How to get and set Cookies when using Requests | bobbyhadz
A step-by-step guide on how to set and get cookies when using the requests library in Python.
bobbyhadz.com
'
'Programing Language > Python' 카테고리의 다른 글
pyautogui을 이용하여 자동화 기능 만들기 (1) | 2023.10.28 |
---|---|
추상 클래스와 덕 타이핑 (0) | 2023.09.06 |
openpyxl로 엑셀 데이터 다루기 (0) | 2023.08.20 |
Selenium과 Pyinstaller를 이용하여 만든 실행파일 뒤에 검은창이 나올 경우 해결 방법 (0) | 2023.07.06 |
Pyinstaller을 통해 py 파일을 각 OS에 맞는 실행 파일로 변환 (0) | 2023.07.06 |