데이터 분석/혼공단

[혼공단 9기] 혼공분석 Chpater 02-1 정리

GRONG 2023. 1. 16. 00:28

02-1 정리 썸네일

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 순으로 모두 출력하고 싶다면

  1. 모든 자식 엘리먼트를 찾기 위해 findall( )을
  2. 순서를 위해 findtext( )를
  3. 모두 출력을 위해 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키의 값이다

  1. [’response’][’docs’]를 통해 접근을 하고
  2. 이 안에 있는 모든 doc키의 값들을 for문으로 빼서
  3. 비어있는 배열에 넣어줄 것이다
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는 많이 쓰일 것이다!