Chapter 02 데이터 수집: API 사용하기

API 방식은 웹사이트나 다른 팀의 협조 없이도 가장 편리하게 데이터를 수집할 수 있는 방법이다. 공공 데이터 세트는 API를 사용해 제공하는 경우가 많다.



API?

데이터 분석가가 데이터베이스에 직접 접근하기 어려울 때가 있다. 데이터 베이스 접근 권한이 엄격히 관리되거나, 민감한 개인 정보가 있거나, 아예 네트워크가 분리되어 물리적인 접근이 불가능할 수도 있다. 이럴 때 인증된 URL만 있으면 언제든지 필요한 데이터에 편리하게 접근할 수 있는 방식이 바로 API 이다.


API(Application Programming Interface)는 두 프로그램이 서로 대화하기 위한 방법을 정의한것. 프로그램 A와 프로그램 B가 데이터를 주고 받는 규칙이 다르다면 올바르게 데이터를 처리하지 못한다.



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

웹사이트는 웹 페이지를 서비스하기 위해 웹 서버(web server) 소프트웨어를 사용한다.

대표적인 웹 서버 프로그램은 NGINX(엔진엑스), Apache(아파치) 등이 있다. 이런 웹 서버 프로그램은 웹 브라우저와 통신할 때 HTTP란 프로토콜(protocol)을 사용한다.

즉, HTTP(Hyper Text Transfer Protocol)는 인터넷에서 웹 페이지를 전송하는 기본 통신 방법이다. HTTP 프로토콜을 사용해 API를 만드는 것이 웹 기반 API라는 것과 데이터 분석가는 웹 기반 API를 사용하는 방법을 아는 것이 중요하다.


웹 페이지 문서: HTML

HTML(Hyper Text Markup Language)은 웹 브라우저가 화면에 표시할 수 있는 문서의 한 종류이자 웹 페이지를 위한 표준 언어이다. 웹 페이지의 HTML 내용을 보고자 할 때, 크롬 브라우저의 경우 마우스 우클릭 [페이지 소스 보기] 메뉴를 선택하면 된다.

HTML과 같은 언어를 마크업 언어라고 부르며 <div>와 같은 표시를 태그(tag)라고 부른다.


웹 기반 API는 웹 서버와 웹 브라우저가 대화하는 방식과 비슷하다. HTTP 프로토콜을 사용하지만 HTML을 주고 받는 것이 아니라 일반적으로 CSV, JSON, XML 같은 파일을 사용한다. 이런 파일을 선호하는 이유는 비교적 복잡한 구조인 HTML 소스 보다 단순해서 버그가 생길 가능성이 낮고, 오류를 찾거나 데이터를 확인할 때도 쉽게 이해할 수 있기 때문이다.


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

JASON은 JavaScript Object Notation의 약자이다. 자바스크립트 언어를 위해 만들어졌지만 현재는 범용 포맷으로 사용한다. 대부분의 프로그래밍 언어는 JSON 형태의 텍스트를 읽고 쓸 수 있다. JSON은 마치 파이썬의 딕셔너리(dictionary)와 리스트(list)를 중첩해 놓은 것과 비슷하다.


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

json 패키지에서 파이썬 객체를 JSON 형식에 맞는 텍스트로 바꿀 때는 json.dumps()함수를 사용한다.

json.dumps()함수를 사용할 때 ensure_ascii 매개변수를 False로 지정한 이유는 딕셔너리 d에 한글이 포함되어 있기 때문이다. 기본적으로 json.dumps() 함수는 아스키(ASCII) 문자 외의 다른 문자를 16진수로 출력하기 때문에 한글이 제대로 보이지 않는다. 그래서 ensure_ascii 매개변수를 False로 지정하여 원래 저장된 문자를 그대로 출력하도록 했다.

d = {"name": 혼자 공부하는 데이터 분석"}
print(d['name'])

import json
d_str = json.dumps(d, ensure_ascii=False)
print(d_str)


d_str이 문자열로 객체인지 파이썬의 type()함수로 확인해 보자

print(type(d_str))


웹 기반 API는 전송하려는 파이쎤 객체를 json.dumps()함수를 사용하여 JSON 문자열로 변환하여 전송한다. 그런데 이런 JSON 문자열을 파이썬 프로그램에 사용하려면 다시 파이썬 딕셔너리로 바꾸어야 한다.


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

Chapter 02 데이터 수집: API 사용하기


json.loads()함수로 d_str 문자열을 파이썬 딕셔너리로 바꾼다.

d2 = json.loads(d_str)
print(d2['name'])

print(type(d2))


따라서 웹 기반 API에서 전달되는 데이터가 JSON 문자열이라면, json.loads()함수를 사용해 파이
썬 객체로 변환한 다음 분석 프로그램에서 사용하면 된다.

앞서 파이썬 딕셔너리를 만들고 -> json.dumps() 함수로 문자열로 변환 -> json.loads()함수를 사용을 했는데, 매번 이렇게 하는 것은 번거롭다. JSON 문자열을 json.loads()함수에 직접 전달하면 된다.

d3 = json.loads('{}') <- 기본형태

d3 = json.loads('{"name": " 혼자 공부하는 데이터 분석", "author": "박해선", "year": 2024}')

print(d3['name'])
print(d3['author'])
print(d3['year'])

여러 개의 항목을 가진 JSON 문자열을 json.loads()함수에 전달하여 성공적으로 딕셔너리로 변경 할 수 있다.

“author” 키에 여러 항목을 넣을 수 있다. 이때 대괄호를 사용한다.

d3 = json.loads({"name": "혼자 공부하는 데이터 분석",
"author": ["박해선", "홍길동"],
"year": 2024})

print(d3['author'][1])

[1]은 두번째 항목인 홍길동이 출력된다.

위와 같은 방식으로 도서를 하나 더 추가 할 수 있다.

문자열이 길 때는 “”” 세겹따옴표를 사용하면 긴 문자열을 줄바꿈하여 입력할 수 있다.

d4_str = """
[
{"name": "혼자 공부하는 데이터 분석", "author": "박해선", "year": 2024},
{"name": "혼자 공부하는 머신러닝+딥러닝", "author": "박해선", "year": 2024}
]
"""

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

d4[0]은 파이썬 리스트의 첫 번째 딕셔너리가 된다. 따라서 d4[0][‘name’]은 첫 번째 딕셔너리의 “name” 키에 해당하는 값을 반환한다.


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

편리하게도 판다스는 JSON 문자열을 읽어서 데이터프레임으로 변환하는 read_json()함수를 제공한다.

import pandas as pd
pd.read_json(d4_str)


JSON을 데이터프레임으로 바꾸는 또 다른 방법은 JSON 문자열을 파이썬 객체로 만든 다음 Data Frame 클래스를 사용하는 것.

pd.DataFrame(d4)

웹 기반 API를 사용해 데이터를 수집하는 경우 JSON을 만날 가능성이 아주 높기 때문에 위 내용을 잘 이해하는 것이 좋다.

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

JSON과 함께 널리 사용되는 또 다른 텍스트 포맷인 XML.

XML은 eXtensible Markup Language의 약자이다. HTML은 웹 페이지를 표현하는 데는 뛰어나지만, 구조적이지 못하기 때문에 프로그램 간의 약속대로 전송하는 API에서는 적절하지 않다.

대신 XML은 컴퓨터와 사람이 모두 읽고 쓰기 편한 문서 포맷을 위해 고안되었다.


Chapter 02 데이터 수집: API 사용하기


XML은 엘리먼트(element)들이 계층 구조를 이루면서 정보를 표현한다. 그 형태는 시작 태그와 종료 태그로 감싸져있다. 태그는 <> 기호로 시작해서 기호로 끝나며 태그 이름은 영문자와 숫자를 사용한다. 시작태그와 종료 태그의 이름은 같아야 한다.

위 그림에서 볼 수 있듯이 <book>은 부모 엘리먼트(parent element) 또는 부모 노드(parent node) 라고 부른다. <name>, <author>, <year>은 book 엘리먼트의 자식 엘리먼트(child element)이다.

✔️ 태그 이름은 안에 담긴 정보가 잘 드러나도록 정하는 것이 좋다. 마치 데이터프레임의 열 이름이나 파이썬의 변수 이름을 정하는 것과 비슷하다. 또 동일한 자식 엘리먼트를 여러 개 포함하는 부모 엘리먼트는 복수형으로 사용하는 것이 이해하기 쉽다. 예를들어 <book> 엘리먼트를 여러 개 포함하는 부모 엘리먼트의 태그 이름은 <books>라고 정한다. 태그 이름은 특수 문자와 공백 문자를 포함할 수 없다. 그리고 ‘-‘, ‘.’와 숫자로 시작할 수 없다.



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

우선 XML을 파이썬의 세겹따옴표로 문자열을 만든 다음, 파이썬에서 제공하는 xml 패키지를 사용해 읽어 본다.

x_str = """
<book>
    <name>혼자 공부하는 데이터 분석</name>
    <author>박해선</author>
    <year>2024</year>
</book>
"""

여기서는 파이썬에서 기본으로 제공되는 xml 패키지는 XML 문서를 읽고 쓸 수 있는 간편한 API를 제공한다. xml.etree.ElemenTree 모듈의 fromstring()함수를 사용해 x_str 문자열을 XML로 변환한다.

import xml.etree.ElementTree as et
book = et.fromstring(x_str)

print(type(book)) 

json 패키지는 JSON 문자열을 파이썬 객체로 변환하지만, fromstring()함수가 반환하는 객체는 단순한 파이썬 객체가 아니라 ElementTree 모듈 아래에 정의된 Element 클래스의 객체이다.

타입을 확인해 보면 <class ‘xml.etree.ElementTree.Element’> 라는 것을 알 수 있다.


tag 속성을 출력하면 엘리먼트 이름을 쉽게 확인 할 수 있다.

print(book.tag)



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

위 xml 문서에서 추출하고자 하는 것은 도서명(name), 저자(author), 발행 연도(year)이다. 이를 위해 먼저 <book> 엘리먼트의 자식 엘리먼트를 구한 다음, 각각의 자식 엘리먼트에 담긴 텍스트를 읽을 수 있다.

book_childs = list(book)
print(book_childs)

실행결과 [<Element ‘name’ at 0x10f9908b0>, <Element ‘author’ at 0x10f990900>, <Element ‘year’ at 0x10f990950>] 이와 같이 순서대로 엘리먼트가 담겨있다.


text 속성으로 엘리먼트에 있는 텍스트를 출력

name, author, year = book_childs
print(name.text)
print(author.text)
print(year.text)

그러나 XML은 자식 엘리먼트 순서가 항상 일정하다는 것을 보장하지 않는다. 위처럼 book_childs에서 순서대로 자식 엘리먼트를 찾는 것은 위험하다.

book 객체의 findtext()메서드를 사용하면 해당하는 자식 엘리먼트를 탐색하여 자동으로 텍스트를 반환할 수 있다.

name = book.findtext('name')
author = book.findtext('author')
year = book.findtext('year')

print(name)
print(author)
print(year)

이런 방식은 자식 엘리먼트의 순서가 어떻게 되어 있든지 상관없기 때문에 안전하다.


조금 더 복잡한 XML 문서를 만들어 본다.

x2_str = """
<books>
    <book>
        <name>혼자 공부하는 데이터 분석</name>
        <author>박해선</author>
        <year>2022</year>
    </book>
    <book>
        <name>혼자 공부하는 머신러닝+딥러닝</name>
        <author>박해선</author>
        <year>20220</year>
    </book>
</books>
"""

books = et.fromstring(x2_str)
print(books.tag)

<books>엘리먼트 안에 두 개의<book> 엘리먼트를 포함시켰다.

여기서 부모 엘리먼트는<books>이다.

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

동일한 이름을 가진 여러 개의 자식 엘리먼트를 찾을 때는 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()

<books>의 자식 엘리먼트를 모두 찾아 그 안에 담긴 텍스트를 출력했다.


JSON의 경우 API에서 전달한 텍스트를 json.loads()함수를 사용해 파이썬 객체로 바꾸어 내용을 추출했다면, XML은 xml.etree.ElementTree 모듈에 있는 fromstring()함수를 사용하여 부모(루트) 엘리먼트를 얻고, findall()메서드로 자식 엘리먼트에 담긴 텍스트를 추출할 수 있다는 것을 기억하자.

✔️JSON 처럼 XML을 바로 판다스로 바꾸는 방법은, read_json()함수 처럼 read_xml()함수를 사용하면 XML을 데이터프레임으로 변환해준다.

pd.read_xml(x2_str)


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

도서관 정보나루 접속 > Open API 활용

API를 호출하는 URL 작성하기

Chapter 02 데이터 수집: API 사용하기

조회할 값은 호출 URL 뒤에 파라미터를 뒤에 연결하면 된다.

파라미터와 값은 =로 연결하고, 파라미터 사이는 &로 연결한다.

호출 URL과 파라미터는 ?로 연결한다. 이러한 방식을 HTTP GET 방식이라고 한다. 검색 및 포털 사이트의 주소에서 흔히 볼 수있다.

✔️ URL로 파라미터 값이나 데이터를 전달하는 것을 GET 방식이라고 한다.
? 문자 뒤에 연결된 파라미터와 값들은 쿼리 스트링(query string)이라고 한다.


API 인증키 발급하기

호출 URL을 사용하려면 API 인증키가 필요하다.


[🔗 출처 도서 링크]






답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다