HTTP ์์ฒญ
Python์ requests ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์น API์ ํต์ ํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์๋ด
์๋ค.
requests๋?โ
requests๋ Python์์ HTTP ์์ฒญ์ ๋ณด๋ด๊ธฐ ์ํ ๊ฐ์ฅ ์ธ๊ธฐ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค. ๊ฐ๋จํ๊ณ ์ง๊ด์ ์ธ API๋ก ์น ์๋ฒ์ ์ฝ๊ฒ ํต์ ํ ์ ์์ต๋๋ค.
์ฃผ์ ํน์งโ
- ๊ฐ๋จํ๊ณ ์ง๊ด์ ์ธ API
- ์๋ JSON ์ธ์ฝ๋ฉ/๋์ฝ๋ฉ
- ์ธ์ ๊ด๋ฆฌ ๋ฐ ์ฟ ํค ์ฒ๋ฆฌ
- ํ์ผ ์ ๋ก๋ ์ง์
- ํ์์์ ์ค์ ๊ฐ๋ฅ
์ค์นํ๊ธฐโ
pip install requests
๊ธฐ๋ณธ GET ์์ฒญโ
๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ GET ์์ฒญ๋ถํฐ ์์ํด๋ด ์๋ค.
import requests
# ๊ธฐ๋ณธ GET ์์ฒญ
response = requests.get('https://api.github.com')
# ์๋ต ํ์ธ
print(response.status_code) # 200
print(response.text) # ์๋ต ๋ณธ๋ฌธ
print(response.json()) # JSON ํ์์ผ๋ก ํ์ฑ
์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ ์ถ๊ฐโ
# URL์ ์ง์ ์์ฑ
response = requests.get('https://api.github.com/search/repositories?q=python')
# params ๋์
๋๋ฆฌ ์ฌ์ฉ (๊ถ์ฅ)
params = {
'q': 'python',
'sort': 'stars',
'order': 'desc'
}
response = requests.get('https://api.github.com/search/repositories', params=params)
print(response.url) # ์ค์ ์์ฒญ๋ URL ํ์ธ
POST ์์ฒญโ
๋ฐ์ดํฐ๋ฅผ ์๋ฒ๋ก ์ ์กํ ๋ POST ์์ฒญ์ ์ฌ์ฉํฉ๋๋ค.
# Form ๋ฐ์ดํฐ ์ ์ก
data = {
'username': 'john',
'password': 'secret123'
}
response = requests.post('https://httpbin.org/post', data=data)
# JSON ๋ฐ์ดํฐ ์ ์ก
json_data = {
'name': 'John Doe',
'email': 'john@example.com',
'age': 30
}
response = requests.post('https://httpbin.org/post', json=json_data)
print(response.json())
ํ์ผ ์ ๋ก๋โ
# ๋จ์ผ ํ์ผ ์
๋ก๋
files = {'file': open('report.pdf', 'rb')}
response = requests.post('https://httpbin.org/post', files=files)
# ํ์ผ๋ช
์ง์
files = {
'file': ('report.pdf', open('report.pdf', 'rb'), 'application/pdf')
}
response = requests.post('https://httpbin.org/post', files=files)
# ์ฌ๋ฌ ํ์ผ ์
๋ก๋
files = {
'file1': open('image1.jpg', 'rb'),
'file2': open('image2.jpg', 'rb')
}
response = requests.post('https://httpbin.org/post', files=files)
PUT๊ณผ DELETE ์์ฒญโ
๋ฆฌ์์ค๋ฅผ ์ ๋ฐ์ดํธํ๊ฑฐ๋ ์ญ์ ํ ๋ ์ฌ์ฉํฉ๋๋ค.
# PUT ์์ฒญ (์ ์ฒด ์
๋ฐ์ดํธ)
update_data = {
'id': 1,
'title': 'Updated Title',
'completed': True
}
response = requests.put('https://jsonplaceholder.typicode.com/todos/1', json=update_data)
# PATCH ์์ฒญ (๋ถ๋ถ ์
๋ฐ์ดํธ)
partial_data = {'completed': True}
response = requests.patch('https://jsonplaceholder.typicode.com/todos/1', json=partial_data)
# DELETE ์์ฒญ
response = requests.delete('https://jsonplaceholder.typicode.com/todos/1')
print(response.status_code) # 200 ๋๋ 204
ํค๋ ์ค์ โ
์์ฒญ ํค๋๋ฅผ ํตํด ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ ๋ฌํ ์ ์์ต๋๋ค.
# ๊ธฐ๋ณธ ํค๋ ์ค์
headers = {
'User-Agent': 'MyApp/1.0',
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.get('https://api.github.com', headers=headers)
# API ํค ์ธ์ฆ
headers = {
'Authorization': 'Bearer YOUR_API_KEY',
'X-API-Key': 'YOUR_API_KEY'
}
response = requests.get('https://api.example.com/data', headers=headers)
์ธ์ฆโ
๋ค์ํ ์ธ์ฆ ๋ฐฉ๋ฒ์ ์ง์ํฉ๋๋ค.
from requests.auth import HTTPBasicAuth, HTTPDigestAuth
# Basic ์ธ์ฆ
response = requests.get(
'https://api.example.com/protected',
auth=HTTPBasicAuth('username', 'password')
)
# ๊ฐ๋จํ ๋ฐฉ๋ฒ
response = requests.get(
'https://api.example.com/protected',
auth=('username', 'password')
)
# Bearer Token ์ธ์ฆ
headers = {'Authorization': 'Bearer YOUR_ACCESS_TOKEN'}
response = requests.get('https://api.example.com/data', headers=headers)
# OAuth 2.0
from requests_oauthlib import OAuth2Session
oauth = OAuth2Session(client_id, token=token)
response = oauth.get('https://api.example.com/protected')
JSON ์ฒ๋ฆฌโ
JSON ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ฒ ๋ค๋ฃฐ ์ ์์ต๋๋ค.
# JSON ์๋ต ํ์ฑ
response = requests.get('https://api.github.com/users/github')
data = response.json()
print(data['name'])
print(data['public_repos'])
# JSON ์์ฒญ ์ ์ก
payload = {
'name': 'John',
'email': 'john@example.com',
'settings': {
'notifications': True,
'theme': 'dark'
}
}
response = requests.post('https://api.example.com/users', json=payload)
# ์ปค์คํ
JSON ์ธ์ฝ๋
import json
class CustomEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
return super().default(obj)
response = requests.post(
'https://api.example.com/data',
data=json.dumps(payload, cls=CustomEncoder),
headers={'Content-Type': 'application/json'}
)
ํ์์์ ์ค์ โ
๋คํธ์ํฌ ๋ฌธ์ ๋ก ์ธํ ๋ฌดํ ๋๊ธฐ๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
# ์ฐ๊ฒฐ ํ์์์ 5์ด, ์ฝ๊ธฐ ํ์์์ 10์ด
try:
response = requests.get('https://api.example.com', timeout=(5, 10))
except requests.exceptions.Timeout:
print("์์ฒญ ์๊ฐ์ด ์ด๊ณผ๋์์ต๋๋ค.")
# ์ ์ฒด ํ์์์ 10์ด
response = requests.get('https://api.example.com', timeout=10)
# ํ์์์ ์์ (๊ถ์ฅํ์ง ์์)
response = requests.get('https://api.example.com', timeout=None)
์๋ฌ ์ฒ๋ฆฌโ
๋ค์ํ HTTP ์๋ฌ๋ฅผ ์ ์ ํ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค.
import requests
from requests.exceptions import (
ConnectionError,
Timeout,
HTTPError,
RequestException
)
try:
response = requests.get('https://api.example.com/data', timeout=5)
response.raise_for_status() # 4xx, 5xx ์๋ฌ ๋ฐ์
data = response.json()
print(data)
except ConnectionError:
print("์ฐ๊ฒฐ ์คํจ: ๋คํธ์ํฌ๋ฅผ ํ์ธํ์ธ์.")
except Timeout:
print("์๊ฐ ์ด๊ณผ: ์๋ฒ๊ฐ ์๋ตํ์ง ์์ต๋๋ค.")
except HTTPError as e:
print(f"HTTP ์๋ฌ: {e.response.status_code}")
if e.response.status_code == 404:
print("๋ฆฌ์์ค๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.")
elif e.response.status_code == 401:
print("์ธ์ฆ์ด ํ์ํฉ๋๋ค.")
elif e.response.status_code == 500:
print("์๋ฒ ๋ด๋ถ ์ค๋ฅ์
๋๋ค.")
except RequestException as e:
print(f"์์ฒญ ์คํจ: {str(e)}")
์ธ์ ์ฌ์ฉโ
์ฌ๋ฌ ์์ฒญ์ ๋ณด๋ผ ๋ ์ธ์ ์ ์ฌ์ฉํ๋ฉด ํจ์จ์ ์ ๋๋ค.
# ์ธ์
์์ฑ
session = requests.Session()
# ๋ชจ๋ ์์ฒญ์ ์ ์ฉ๋ ํค๋ ์ค์
session.headers.update({
'User-Agent': 'MyApp/1.0',
'Authorization': 'Bearer YOUR_TOKEN'
})
# ์ธ์
์ผ๋ก ์ฌ๋ฌ ์์ฒญ
response1 = session.get('https://api.example.com/users')
response2 = session.get('https://api.example.com/posts')
response3 = session.post('https://api.example.com/comments', json={'text': 'Hello'})
# ์ฟ ํค ์๋ ๊ด๋ฆฌ
login_data = {'username': 'john', 'password': 'secret'}
session.post('https://example.com/login', data=login_data)
# ๋ก๊ทธ์ธ ํ ์ธ์ฆ๋ ์์ฒญ
response = session.get('https://example.com/dashboard')
# ์ธ์
์ข
๋ฃ
session.close()
# Context Manager ์ฌ์ฉ (๊ถ์ฅ)
with requests.Session() as session:
session.headers.update({'Authorization': 'Bearer TOKEN'})
response = session.get('https://api.example.com/data')
์ฌ์๋ ์ค์ โ
๋คํธ์ํฌ ๋ฌธ์ ์ ์๋์ผ๋ก ์ฌ์๋ํ ์ ์์ต๋๋ค.
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
# ์ฌ์๋ ์ ๋ต ์ค์
retry_strategy = Retry(
total=3, # ์ต๋ 3๋ฒ ์ฌ์๋
backoff_factor=1, # 1์ด, 2์ด, 4์ด ๋๊ธฐ
status_forcelist=[429, 500, 502, 503, 504],
method_whitelist=["HEAD", "GET", "OPTIONS", "POST"]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session = requests.Session()
session.mount("https://", adapter)
session.mount("http://", adapter)
# ์๋ ์ฌ์๋ ์ ์ฉ
response = session.get('https://api.example.com/data')