Part 3. API๋ ๋ฌด์์ธ๊ฐ
๋ณธ ํฌ์คํ
์ ํจ์คํธ์บ ํผ์ค(FastCampus)์ ๋ฐ์ดํฐ ์์ง๋์ด๋ง ์ฌ์ธ์ ํจํค์ง Online์ ์ฐธ๊ณ ํ์์ต๋๋ค.
1. Spotify App ์์ฑ ๋ฐ ํ ํฐ ๋ฐ๊ธ
Client Credentials Flow
1
2
3
4
5
|
{
"access_token": "NgCXRKc...MzYjw",
"token_type": "bearer",
"expires_in": 3600,
}
|
- client id, client secret์ ์ ๊ณตํ๋ฉด ์ฐ๋ฆฌ๋ 3600์ด, ์ฆ 1์๊ฐ๋์ ์ฌ์ฉํ ์ ์๋ค.
2. Python ๊ธฐ๋ณธ
1
2
3
4
5
6
7
8
9
10
11
|
import sys
def main():
print('fastcampus')
#python์ผ๋ก ์คํํ์ ๋, ํด๋น pyํ์ผ ์ด๋ฆ์ด ์ ๋ฌ๋๋ฉด, main()์ ์คํํ๋ผ
if __name__ == '__main__':
main()
#์ง์ pyํ์ผ์ด ์คํ ์๋๊ณ , import spotify_api์ ๊ฐ์ด ๋ชจ๋์ฒ๋ผ import๋๋ฉด, ~~๋ฅผ printํ๋ผ.
else:
print('this script i being imported')
|
- Windows๋ Windows Powershell์ ํตํด์ ์งํํ๋ฉด ๋๋ค.
- ๊ธฐ๋ณธ์ ์ผ๋ก ์์ฒ๋ผ ์ฝ๋ฉ์ ์์ํ๊ฒ ๋๋ค.
3. Python Requests ํจํค์ง
requests python library > Developer Interface ์ฐธ๊ณ ํ๊ธฐ
powershell์์ pip install requests ์คํํ๊ธฐ
4. API๋ฅผ ํตํ ๋ฐ์ดํฐ ์์ฒญ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
import sys
import requests
import base64
import json
import logging
client_id = '' # client_id ์
๋ ฅ
client_secret = '' # client_secret ์
๋ ฅ
def main():
headers = get_headers(client_id, client_secret)
params = {
'q': 'BTS',
'type': 'artist',
'limit': 5
}
r = requests.get('https://api.spotify.com/v1/search', params=params, headers=headers)
# print(r.status_code) # 200์ด๋ฉด ์ด์ ์๋ ๊ฒ
# print(r.text)
# sys.exit(0)
def get_headers(client_id, client_secret):
# 1์๊ฐ๋ง ์์ผ๋ฉด expire๋๊ธฐ ๋๋ฌธ์ ์ถ๊ฐ๋ก function ํ๋๋ฅผ ๋ง๋ค์ด๋๋ ๊ฒ์ด๋ค.
endpoint = 'https://accounts.spotify.com/api/token'
encoded = base64.b64encode("{}:{}".format(client_id, client_secret).encode('utf-8')).decode('ascii')
headers = {
'Authorization': 'Basic {}'.format(encoded)
}
payload = {
'grant_type': 'client_credentials'
}
r = requests.post(endpoint, data=payload, headers=headers)
# ์ค๊ฐ์ ์ ๋๋์ง ํ์ธํด๋ณด๋ ์ฝ๋
# print(r.status_code)
# print(r.text)
# print(type(r.text)) #string์ผ๋ก ์ถ๋ ฅ๋๋ฏ๋ก ์๋์์ json.loads๋ฅผ ํตํด dictionary๋ก ๋ง๋ค์ด์ค์ผ ํ๋ค.
# sys.exit(0)
access_token = json.loads(r.text)['access_token']
headers = {
'Authorization': "Bearer {}".format(access_token)
}
return headers
if __name__ == '__main__':
main()
|
5. Status Code
- Status Code๋ฅผ ์์์ผ ํ๋ ์ด์ : ๋ฐ์ดํฐ ์์ง๋์ด์ ์๋ชป์ด ์๋, Spotify ์๋ฒ์ ์ค๋ฅ ๋ฑ์ผ๋ก ์ธํ ๋ฌธ์ ์ธ์ง ์ฒดํฌํ ์ ์๋ค.
- Spotify Web API ๊ธฐ์ค์ด์ง๋ง, RFC 2616์ RFC 6585์ ์ํด ์ผ๋ฐ์ ์ผ๋ก ํต์ฉ๋๋ ๊ธฐ์ค์ด๋ค.
| STATUS CODE |
DESCRIPTION |
| 200 |
OK - The request has succeeded. The client can read the result of the request in the body and the headers of the response. |
| 201 |
Created - The request has been fulfilled and resulted in a new resource being created. |
| 202 |
Accepted - The request has been accepted for processing, but the processing has not been completed. |
| 204 |
No Content - The request has succeeded but returns no message body. |
| 304 |
Not Modified. See Conditional requests. |
| 400 |
Bad Request - The request could not be understood by the server due to malformed syntax. The message body will contain more information; see Response Schema. |
| 401 |
Unauthorized - The request requires user authentication or, if the request included authorization credentials, authorization has been refused for those credentials. |
| 403 |
Forbidden - The server understood the request, but is refusing to fulfill it. |
| 404 |
Not Found - The requested resource could not be found. This error can be due to a temporary or permanent condition. |
| 429 |
Too Many Requests - Rate limiting has been applied. |
| 500 |
Internal Server Error. You should never receive this error because our clever coders catch them all โฆ but if you are unlucky enough to get one, please report it to us through a comment at the bottom of this page. |
| 502 |
Bad Gateway - The server was acting as a gateway or proxy and received an invalid response from the upstream server. |
| 503 |
Service Unavailable - The server is currently unable to handle the request due to a temporary condition which will be alleviated after some delay. You can choose to resend the request again. |
6. ์๋ฌ ํธ๋ค๋ง
sys.exit(0)๊ณผ sys.exit(1) ์ฐจ์ด
1
2
3
4
|
# ํ๋ก๊ทธ๋จ์ ์ ์์ ์ผ๋ก ์ข
๋ฃ์ํค๊ณ ์ถ์ ๋
sys.exit(0)
# ํ๋ก๊ทธ๋จ์ ๊ฐ์ ์ ์ผ๋ก ์ข
๋ฃ์ํค๊ณ ์ถ์ ๋
sys.exit(1)
|
Status Code 401, 409 ์๋ฌ ํธ๋ค๋ง
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
r = requests.get('https://api.spotify.com/v1/search', params=params, headers=headers)
if r.status_code != 200:
logging.error(r.text)
## Too many requests
if r.status_code == 429:
retry_after = json.loads(r.headers)['Retry-After']
time.sleep(int(retry_after))
r = requests.get('https://api.spotify.com/v1/search', params=params, headers=headers)
## access_token expireed
elif r.status_code == 401:
headers = get_headers(client_id, client_secret)
r = requests.get('https://api.spotify.com/v1/search', params=params, headers=headers)
else:
sys.exit(1) #๊ฐ์ ์ข
๋ฃ
|
7. ํ์ด์ง๋ค์ด์
ํธ๋ค๋ง
์ฐธ๊ณ ์ฌ์ดํธ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
import sys
import requests
import base64
import json
import logging
client_id = '' # client_id ์
๋ ฅ
client_secret = '' # client_secret ์
๋ ฅ
def main():
headers = get_headers(client_id, client_secret)
# Get BTS' Albums
r = requests.get('https://api.spotify.com/v1/artists/3Nrfpe0tUJi4K4DXYWgMUX/albums', headers=headers)
raw = json.loads(r.text)
# total = raw['total'] # ์ด 104๊ฐ๊ฐ ์์์ ํ์ธ
# offset = raw['offset'] # ์์์ 0
# limit = raw['limit'] # 20๊ฐ์ฉ ๋ฝ๊ฒ ๋ค.
next = raw['next']
albums = []
albums.extend(raw['items'])
## ๋ 200๊ฐ๋ง ๋ฝ์ ์ค๊ฒ ๋ค.
count = 0
while count < 200 and next: # while next: ๋ผ๊ณ ๋ง ํ๋ฉด ๋๊น์ง ๊ฐ์ ธ์ค๊ฒ ๋๋ค.
r = requests.get(raw['next'], headers=headers)
raw = json.loads(r.text)
next = raw['next']
# print(next) # ๋งจ ๋ง์ง๋ง์๋ none์ด ๋์ค๊ฒ ๋๋ค. ์ด์ ๋ํด์๋ Spotify ํ์ด์ง๋ฅผ ์ฐธ๊ณ ํ๋ฉด ๋๋ค.
albums.extend(raw['items'])
count = len(albums)
print(len(albums))
def get_headers(client_id, client_secret):
endpoint = 'https://accounts.spotify.com/api/token'
encoded = base64.b64encode("{}:{}".format(client_id, client_secret).encode('utf-8')).decode('ascii')
headers = {'Authorization': 'Basic {}'.format(encoded)}
payload = {'grant_type': 'client_credentials'}
r = requests.post(endpoint, data=payload, headers=headers)
access_token = json.loads(r.text)['access_token']
headers = {'Authorization': "Bearer {}".format(access_token)}
return headers
if __name__ == '__main__':
main()
|