02-1 API 사용하기
API
Application Programming Interface 두 프로그램이 서로 대화하기 위한 방법을 정의한 것. 내가 찾아봤던 것 중에는 쉬웠던 게 메뉴판이라고 생각하는 거 ex)프로그램 A가 메뉴판을 만들어 두면 프로그램 B가 와서 원하는 메뉴(데이터)를 주문할 수 있다!
앱 간의 상호작용에서는 웹 기반의 API가 많이 쓰임
HTTP
웹 브라우저가 서버에 정보를 요청할 때의 통신 규약 말이 어려운데 어떤 서버에서 정보를 가지고 올때 으로 말해야 하는지(ex. 스테이크 주문 시 굽기는 미디엄 레어로, 후추는 빼주시고)에 관한 약속
HTML
웹 페이지 문서, 즉 단순 텍스트인데 웹 브라우저가 이해할 수 있는 구조로 되어있다 요런 언어를 마크업 언어라고 부른다 → 처음 알았다!
웹 기반 API는 웹 서버와 웹 브라우저가 대화하는 방식과 유사하다. 웹 브라우저가 HTTP 형식으로 하이 서버, 네이버 띄워줘 하면 네이버라는 웹 페이지(HTML)를 불러와주는 것처럼 웹 기반 API는 HTTP 형식으로 요청을 하면 JSON, XML, CSV 등의 데이터를 얻을 수 있다
웹 기반 API에서 데이터를 HTML로 받지 않는 이유는 HTML 자체가 이미 복잡하기 때문에 오류 발생 가능성이 있고, 발생해도 잡기 힘들기 때문!
CSV ↔ JSON, XML CSV는 행과 열로만 이루어져 있어서 복잡한 데이터 표현이 어렵고 콤마 갯수가 맞지 않으면 멘탈이 나갈 수 있기 때문에 JSON, XML을 주로 사용한다
JSON
“키”와 “값”으로 이루어진 데이터
파이썬에서 JSON에 접근하려면
d = {"key":"value"}
d['key']
이런식으로 접근하게 된다
파이썬 객체 → JSON 문자열 변환
json.dumps( ) 함수를 사용한다 → 파이썬 객체를 ‘문자열’로 만들 수 있다
근데 이 함수는 API가 데이터를 줄 때 이미 API 측에서 이미 실행해서 전달해 준다 즉, 데이터를 받을 때 파이썬 객체가 아닌 ‘문자열’을 준다는 것이다 why? HTTP가 텍스트 기반으로 주문하기로 약속했기 때문
JSON 문자열 → 파이썬 객체 변환
json.loads( ) 함수를 사용한다
example_str = """
[
{"date":9, "day":"Tue", "time":23},
{"date":10, "day":"Wed", "time":21}
]
"""
ex=json.loads(ex_str)
이런 구조를 지닌 JSON이 있는데 두번째 day값에 접근하고 싶다면 ex[1][’day’]이런식으로 접근한다
JSON 문자열 → 데이터프레임
간단하다! 판다스의 read_json( ) 을 쓰면 데이터프레임으로 바꿔준다 pd.read_json(example_str)을 하면 데이터프레임을 볼 수 있다
혹은 파이썬 객체를 pd.DataFrame( )에 넣으면 된다! ex)pd.DataFrame(example)
※함수에 들어가는 게 문자열인지 파이썬 객체인지 잘 기억해 둘 것!
XML
HTML보다 구조적인 표현으로 컴퓨터와 사람 모두 읽고 쓰기 편한 문서 포맷
엘리먼트들의 계층 구조로 이루어진다
<name></name>이런 식으로 HTML과 유사한 태그 표현
XML 문자열 → 파이썬 객체
간단하지는 않지만 xml.etree.Elementree를 import 해서 써야 한다
import xml.etree.Elememtree as et
et.fromstring()
으로 활용한다 근데 특이한 게 여기서 et.fromstring( )을 거치면 데이터 형식이 xml.etree.Elementree.Element가 된다
xml2_str="""
<books>
<book>
<name>hon-gong data analyze</name>
<author>Haesun Park</author>
<year>2022</year>
</book>
<book>
<name>hon-gong ML+DL</name>
<author>Haesun Park</author>
<year>2020</year>
</book>
</books>
"""
이런 구조의 xml이 있을 때 내가 name, author, year를 차례대로 보고 싶다면 그 순서에 맞게 findtext( )를 통해서 데이터를 먼저 담아줘야 한다. why? xml은 자식 엘리먼트들에 대한 순서를 보장해주지 않기 때문
위에서 year, name, author 순으로 모두 출력하고 싶다면
- 모든 자식 엘리먼트를 찾기 위해 findall( )을
- 순서를 위해 findtext( )를
- 모두 출력을 위해 for문을
활용하면 된다
books = et.fromstring(xml2_str)을 거친 후
for book in books.findall('book'):
year = book.findtext('year');
name = book.findtext('name');
author = book.findtext('author');
print(year)
print(name)
print(author)
쓰고 보니 이미 위에서 데이터를 담아줬기 때문에 출력으로 순서 조절이 가능하다
print(book.findtext('year'));
print(book.findtext('name'));
print(book.findtext('author'));
이런 식으로 출력한다면 이게 순서 자체이므로 주의해야 할 것이고
여하튼 위에 for문을 돌려주면 xml2의 모든 값이 출력된다
XML → 데이터프레임
read_json( )처럼 read_xml( )을 사용하면 데이터프레임으로 변환이 가능하다 read_json( )에 문자열이 들어갔던 걸 기억해 보면 read_xml( )에도 문자열이 들어가야 한다는 점!
EX) pd.read_xml(xml2_str)
API 호출 URL 형식
호출 URL(주소)? 파라미터=값? 파라미터=값 ? 파라미터=값 ? … ※호출 주소 뒤에 [파라미터=값]들을 쿼리 스트링이라 부른다
이런 주소를 치면 HTTP GET 형식으로 요청하게 된다
API는 필요에 따라 개별 사용자에게 인증키가 필요한 경우가 있다 이 인증키 또한 쿼리스트링의 한 부분으로 인증키=f192l90290230? 이런 식으로 주소창에 같이 들어가면 된다(순서는 상관없다)
파이썬으로 API 호출하기 : request 패키지
requests.get( )에 API의 링크를 넣어주면 request.Response 클래스 객체를 반환한다 이 객체 안에는 json( ) 메서드가 있어서 json문자열을 파이썬 객체로 바꿔준다
책에서는
r = requests.get(url)
data = r.json()
data = requests.get(url). json() 이런 식으로도 작성이 가능하다
요렇게 API로 받은 자료는 우리가 원하는 형식으로 되어있지 않을 수 있기 때문에 보기 좋게 가공하는 과정이 필요하다
{'response': {'request': {'startDt': '2021-04-01',
'endDt': '2021-04-30',
'age': '20',
'pageNo': 1,
'pageSize': 200},
'resultNum': 200,
'numFound': 5000,
'docs': [{'doc': {'no': 1,
'ranking': '1',
'bookname': '우리가 빛의 속도로 갈 수 없다면 :김초엽 소설 ',
'authors': '지은이: 김초엽',
'publisher': '허블',
'publication_year': '2019',
'isbn13': '9791190090018',
'addition_symbol': '03810',
'vol': '',
'class_no': '813.7',
'class_nm': '문학 > 한국문학 > 소설',
'loan_count': '461',
'bookImageURL': 'https://image.aladin.co.kr/product/19359/16/cover/s972635417_1.jpg'}},
{'doc': {'no': 2,
'ranking': '2',
'bookname': '달러구트 꿈 백화점.이미예 장편소설 ',
'authors': '지은이: 이미예',
'publisher': '팩토리나인',
...
'bookImageURL': 'https://bookthumb-phinf.pstatic.net/cover/084/030/08403038.jpg?type=m1&udate=20171223'}}]}}
크게 response라는 키에는 여러 값이 있지만 우리가 보고 싶은 것은 docs라는 키안에 있는 doc키의 값이다
- [’response’][’docs’]를 통해 접근을 하고
- 이 안에 있는 모든 doc키의 값들을 for문으로 빼서
- 비어있는 배열에 넣어줄 것이다
books = []
for d in data['response']['docs']:
books.append(d['doc'])
이제 books에는 우리가 원하는 형식의 데이터인
{'no': 1,
'ranking': '1',
'bookname': '우리가 빛의 속도로 갈 수 없다면 :김초엽 소설 ',
'authors': '지은이: 김초엽',
'publisher': '허블',
'publication_year': '2019',
'isbn13': '9791190090018',
'addition_symbol': '03810',
'vol': '',
'class_no': '813.7',
'class_nm': '문학 > 한국문학 > 소설',
'loan_count': '461',
'bookImageURL': 'https://image.aladin.co.kr/product/19359/16/cover/s972635417_1.jpg'}
이런 데이터가 들어있게 된다
books는 이미 파이썬 객체이기 때문에 판다스의 DataFrame()을 쓸 수 있다
books_df = pd.DataFrame(books)
print(books_df)
하면 우리가 원하는 형식의 표를 볼 수 있다!
처음 우리가 받았을 때는 우리가 원하는 JSON형식이 아니었기 때문에 데이터프레임으로 변환하는 과정을 거쳤지만 이제는 우리가 원하는 형태가 되었기 때문에 다시 JSON으로 변환해서 저장해 주도록 한다
판다스에는 to_csv()와 비슷하게 JSON으로 바꿔주는 to_json() 메서드도 있다!
books_df.to_json(’20s_best_book.json’)
‘ ’안에 적힌 것들이 파일명이므로 20s_best_book이라는 JSON파일을 얻을 수 있다
앞으로도 웹 API를 사용하기 위해 requests는 많이 쓰일 것이다!
'데이터 분석 > 혼공단' 카테고리의 다른 글
[혼공단 9기] 혼공분석 3주차 미션 (0) | 2023.01.25 |
---|---|
[혼공단 9기] 혼공분석 2주차 미션 (0) | 2023.01.16 |
[혼공단 9기] 혼공분석 Chpater 02-2 정리 (0) | 2023.01.16 |
[혼공단 9기] 1주차 미션 (0) | 2023.01.08 |
[혼공단 9기] Chapter 1 정리 (0) | 2023.01.08 |