본문 바로가기
혼공학습단9기

혼자 공부하는 데이터 분석 with 파이썬 : 2주차(Chapter 02-1)

by 이두스 2023. 1. 11.

Chapter 02는 양이 많아서 나눠서 작성하려 한다.

Chapter 02-1의 주제는 "API 사용하기"이다.

API란

  • API는 두 프로그램이 서로 대화 하기 위한 방법을 정의한 것이다.
  • 예시로 윈도우나 맥OS같은 운영체제는 문서 작성 프로그램이 디스크에 있는 파일을 읽고 쓸 수 있도록 API를 제공한다
  • API를 구현하는 방법은 다양하고 각기 장단점이 있다. 이 책에서는 웹 기반의 API에 초점을 맞추어 설명한다.

웹 페이지를 전송하기 위한 통신 규약: HTTP

웹 사이트는 웹 서버 소프트웨어를 사용한다.

웹 서버 프로그램은 웹 브라우저와 통신할 때 HTTP란 프로토콜(통신 규약)을 사용한다.

HTTP:인터넷에서 웹 페이지를 전송하는 기본 통신 방법이다.
웹 서버(운영) <-요청- 웹 브라우저(설치)
웹 서버(운영) -전송-> 웹 브라우저(설치) 의 관계로 보면 된다

웹 페이지 문서: HTML

  • 웹 서버와 웹 브라우저는 HTTP 프로토콜을 사용해 안정적이고 편리하게 웹 페이지를 구성하는 HTML 데이터를 주고 받는다
  • HTML은 웹 브라우저가 화면에 표시할 수 있는 문서의 한 종류이자 웹 페이지를 위한 표준 언어
  • 크롬 브라우저: [마우스 오른쪽 버튼] → [페이지 소스 보기] 선택
  • 하지만 HTML보다 CSV, JSON, XML같은 파일 사용

파이썬에서 JSON 데이터 다루기

  • JSON은 JavaScript Object Notation의 약자이다. 자바스크립트용으로 만들어졌지만 현재는 범용적인 포맷으로 사용한다.
  • 대부분의 프로그래밍 언어는 JSON형태의 텍스트를 읽고 쓸 수 있다.(파이썬 포함)
  • JSON은 파이썬의 딕셔너리와 리스트를 중첩해 놓은 것과 비슷하다.
# JSON 형식의 파이썬 딕셔너리
d = {"name": "혼자 공부하는 데이터 분석"}
print(d['name'])

파이썬 객체를 JSON 문자열로 변환하기: json.dumps() 함수

import json
d_str = json.dumps(d, ensure_ascii=False) # ensure_ascii가 False인 이유: 딕셔너리 d에 한글이 포함되어 있기 때문
print(d_str)

# d_str이 문자열 객체인지 파이썬의 type()함수 사용
print(type(d_str))
  • 웹 기반 API는 전송하려는 파이썬 객체를 json.dumps() 함수를 사용하여 JSON 문자열로 변환하여 전송.
  • 파이썬에서 사용하려면 다시 파이썬 딕셔너리로 변환.

JSON 문자열을 파이썬 객체로 변환하기: json.loads() 함수

  • json.loads() 함수는 JSON 문자열을 파이썬 객체로 변환해줌
  • HTTP 프로토콜로 데이터를 전송하려면 객체를 텍스트로 변환.
    • 직렬화(serialization): 프로그램 상의 객체를 저장하거나 읽을 수 있는 형태로 변환하는 것
    • 역직렬화(deserialization): 직렬화된 정보를 다시 프로그램에서 실행 가능한 객체로 변환하는 것
d2 = json.loads(d_str)
print(d2['name'])

# 타입 확인
print(type(d2))

 

 

그럼 어떻게 해야될까?

  • 웹 기반 API가 JSON 문자열이라면 json.loads()를 사용하여 사용
# 조금 더 복잡한 딕셔너리 
d3 = json.loads('{"name": "혼자 공부하는 데이터 분석", "author":"박해선", "year":2022 }') # json.loads에 바로 연결 
print(d3['name'])
print(d3['author'])
print(d3['year'])

# 조금 더 복잡한 딕셔너리2 : 작가가 복수?
d3 = json.loads('{"name": "혼자 공부하는 데이터 분석", "author":["박해선","홍길동"], "year":2022 }') 
print(d3['author'][1])

# 조금 더 복잡한 딕셔너리3 : 도서가 복수? = JSON배열
# 문자열이 길어 세겹따옴표(""") 사용
d4_str = """[
    {"name": "혼자 공부하는 데이터 분석", "author":"박해선", "year":2022 },
    {"name": "혼자 공부하는 머신러닝+딥러닝", "author":"박해선", "year":2020 }
]"""

d4 = json.loads(d4_str)
print(d4[0]['name'])

 

JSON 문자열을 데이터프레임으로 변환하기: read_json() 함수

# 방법 1 : read_json()
import pandas as pd
pd.read_json(d4_str)

# 방법 2 : DataFrame 클래스 사용
pd.DataFrame(d4)

파이썬에서 XML 데이터 다루기

  • XML(eXtensible Markup Language)은 앨리먼트들이 계층 구조를 이루면서 정보를 표현한다.  
  • XML 예시 : 엘리먼트들이 계층 구조를 이루면서 정보를 표현

<book>

    <name>혼자 공부하는 데이터 분석</name> 

    <author>박해선</author>

    <year>2022</year> 

  •  태그(<>): 시작태그<> 종료태그 </>, 안에 담긴 정보가 잘 드러나도록 정하는 게 좋음. 특수 문자나 공백 문자를 포함할 수 없고 '-','.'와 숫자로 시작 불가
  •  book 엘리먼트는 세 개의 하위 엘리먼트를 가짐 book은 부모 엘리먼트 혹은 부모 노드, 나머지는 자식 엘리먼트라고 부름

XML 문자열을 파이썬 객체로 변환하기: fromstring() 함수

# XML 문자열을 x_str 변수에 저장
x_str = """
<book>
    <name>혼자 공부하는 데이터 분석</name>
    <author>박해선</author>
    <year>2022</year>
</book>
"""

# 파이썬에서 제공되는 xml패키지는 xml문서를 읽고 쓸 수 있는 간편한 API 제공
# xml.etree.ElementTree 모듈의 fromstring()함수 사용: 문자열 -> XML
import xml.etree.ElementTree as et
book = et.fromstring(x_str)

# 여기서 반환된 객체는 ElementTree 모듈 아래 정의된 Element 클래스의 객체임
print(type(book))

# book 객체는 부모 엘리먼트인 book에 해당
# book 객체의 tag속성을 출력
print(book.tag)

자식 엘리먼트 확인하기: findtext() 메서드

book_childs = list(book) # 리스트로 변환 : list()
print(book_childs)

# 리스트 항목을 순서대로 name, author, year 변수에 할당하고 text 속성으로 엘리먼트에 있는 텍스트 확인
name, author, year = book_childs
print(name.text)
print(author.text)
print(year.text)

하지만 XML은 자식 엘리먼트 순서가 항상 일정하다는 것을 보장하지 않음

# findtext() 메서드
name = book.findtext('name')
author = book.findtext('author')
year = book.findtext('year')
print(name)
print(author)
print(year)
# JSON처럼 배열구조는 없지만, 만약 다음과 같다면?
x2_str = """
<books>
    <book>
        <name>혼자 공부하는 데이터 분석</name>
        <author>박해선</author>
        <year>2022</year>
    </book>
    <book>
        <name>혼자 공부하는 머신러닝+딥러닝</name>
        <author>박해선</author>
        <year>2020</year>
    </book>
</books>
"""

# 부모 엘리먼트 확인
books = et.fromstring(x2_str)
print(books.tag)

여러 개의 자식 엘리먼트 확인하기: findall() 메서드와 for문

for book in books.findall('book'):
    name = book.findtext('name')
    author = book.findtext('author')
    year = book.findtext('year')
    print(name)
    print(author)
    print(year)
    print()

# json의 read_json()처럼 문자열을 바로 판다스 데이터프레임으로 변환하려면 read_xml()을 사용하면된다.
pd.read_xml(x2_str)

API로 20대가 가장 좋아하는 도서 찾기

  • 도서관 정보나루에서 데이터 활용-Open API 활용방법-이용절차
  • 인증키 전에 API매뉴얼다운로드 보기
  • https://data4library.kr/

API를 호출하는 URL 작성하기

호출 URL을 사용함=HTTP 프로토콜을 사용한다는 의미
  • 호출 URL: http://data4library.kr/api/loanItemSrch 
  • 파라미터
    • format: 지정하지 않으면 XML 문서로 반환. json으로 받을 예정
    • startDt: 검색 시작 일자. 2021년 4월 1일로 지정
    • endDt: 검색 종료 일자. 2021년 4월 30일로 지정
    • age: 연령대. 20으로 지정
    • authKey: 인증키
  • HTTP GET 방식
    • 파라미터와 값 : =
    • 파라미터 사이 : &
    • 호출 URL과 파라미터 : ?
호출 URL : http://data4library.kr/api/loanItemSrch?format=json&startDt=2021-04-01&endDt=2021-04-30&age=20&authKey=인증키

인증키만 있으면 된다.

API 인증키 발급하기

  1. 회원가입
  2. 로그인 후 [마이페이지] 클릭
  3. [인증키발급]

파이썬으로 API 호출하기: requests 패키지

import requests

url = ""

# get 함수가 반환하는 값은 API 호출의 결과를 담고 있는 requests 패키지의 Response 클래스 객체
r = requests.get(url)

# 이 객체는 여러 메서드 제공. 그 중 json메서드를 이용해 json문자열을 파이썬 객체로 변환하여 반환한다
data = r.json()
print(data)

data
docs 키와 doc 키는 각각 하나의 리스트와 하나의 딕셔너리만 가지고 있기 때문에 계층 구조를 표현하는 것 외에는 큰 역할이 없다. 
실제 도서 정보는 doc 키에 매핑된 딕셔너리에 있다. 그래서 data 딕셔너리 구조를 books에 다시 넣어 바꿈
 
books = []
for d in data['reponse']['docs']:
    books.append(d['doc'])
    
# 리스트 내포
books = [d['doc'] for d in data['response']['docs']]

# 리스트를 판다스 DataFrame 클래스로 옮김
books_df = pd.DataFrame(books)
books_df.head()

# JSON 파일로 저장
books_df.to_json('20s_best_book.json')