[혼공분석] 2주차_API 사용하기
[한빛미디어] 혼자 공부하는 데이터 분석 with 파이썬
좋은 개발자는 컴퓨터를 분석의 대상으로 바라볼 뿐, 두려워하지 않는다!‘전공서가 너무 어려워서 쉽게 배우고 싶을 때’, ‘개발자가 되고 싶은데 뭐부터 봐야 하는지 모를 때’ ‘기술 면접
hongong.hanbit.co.kr
API 사용하기
API란
두 프로그램이 서로 대화하기 위한 방법을 정의한 것이다.
파이썬에서 JSON 다루기
JSON은 JavaScript Object Notation의 약자이다. 원래는 자바스크립트 언어를 위해 만들어졌지만 현재는 범용적인 포맷으로 사용되며 대부분의 프로그래밍 언어는 JSON 형태의 텍스트를 읽고 쓸 수 있다.
JSON은 마치 파이썬의 딕셔너리와 리스트를 중첩해 놓은 것과 비슷하다.
{"name":"혼자 공부하는 데이터 분석"}
파이썬 객체를 JSON 문자열로 변환하기
파이썬의 json 패키지를 사용해 딕셔너리를 JSON 형식에 맞는 문자열로 바꿀 수 있다.
import json
# json.dumps() 함수는 아스키 문자 외의 다른 문자를 16진수로 출력하기 때문에
# 'ensure_ascii = False'로 지정하여 원래 저장된 문자를 그대로 출력하도록 한다.
d_str = json.dumps(d, ensure_ascii = False_
JSON 문자열을 파이썬 객체로 변환하기
json.loads() 함수를 사용하면 JSON 문자열을 파이썬 객체로 변환할 수 있다.
d2 = json.loads(d_str)
print(d2['name'])
파이썬에서 XML 다루기
XML은 extensible markup language의 약자이다. HTML은 웹 페이지를 표현하는 데는 뛰어나지만, 구조적이지 못하기 때문에 컴퓨터와 사람이 모두 읽고 쓰기 편한 문서 포맷을 위해 고안되었다.
<book>
<name> 혼자 공부하는 데이터 분석 </name>
<author> 박해선 </author>
<year> 2022 </year>
</book>
XML 문자열을 파이썬 객체로 변환하기(fromstring() 함수)
x_str = '''<book>
<name> 혼자 공부하는 데이터 분석 </name>
<author> 박해선 </author>
<year> 2022 </year>
</book>
'''
import xml.etree.ElementTree as et
book = et.fromstring(x_str)
print(type(book))
자식 엘리먼트 확인하기(findtext() 메서드)
name = book.findtext('name')
author = book.findtext('author')
year = book.findtext('year')
book 객체의 findtext() 메서드를 사용하면 해당하는 자식 엘리먼트를 자동으로 텍스트로 변환할 수 있다.
동일한 이름을 가진 여러 개의 자식 엘리멘트를 찾을 때는 findall() 메서드와 for 문을 함께 사용하면 편리하다.
x2_str = """
<books>
<book>
<name> 혼자 공부하는 데이터 분석 </name>
<author> 박해선 </author>
<year> 2022 </year>
</book>
<book>
<name> 혼자 공부하는 머신러닝 + 딥러닝 </name>
<author> 박해선 </author>
<year> 2020 </year>
</book>
</books>
"""
for book in book.findall('book'):
name = book.findtext('name')
author = book.findtext('author')
year = book.findtext('year')
print(name)
print(author)
print(year)
print()
API로 20대가 좋아하는 도서 찾기
파이썬으로 API 호출하기: requests 패키지
파이썬에서 URL을 호출하여 데이터를 받을 수 있는 방법은 많지만 requests가 그중에서 간편하고 널리 사용된다.
import requests
url = "http://....................."
r = requests.get(url)
data = r.json()
여기서 r은 reponse 객체로 웹 서버로부터 받은 JSON 문자열을 파이썬 객체로 변환할 수 있는 json() 메서드를 제공한다.
이렇게 얻어진 data에서 도서에 대한 정보만 추출하기 위해 다음과 같이 반복문을 사용할 수 있다. 그 결과를 판다스의 DataFrame으로 변환한다.
books = []
for d in data['reponse']['docs']:
books.append(d['doc'])
# 리스트 내포를 사용할 수도 있다.
books = [[d['doc'] for d in data['reponse']['docs']]
books_df = pd.DataFrame(books)
books_df
웹 스크래핑 사용하기
검색 결과 페이지에서 HTML 가지고 오기
이번에는 requests.get()으로 도서 검색 결과를 가져온 후 검색 결과에서 도서 상세 페이지로 연결되는 링크 URL을 찾고, 다시 requests.get()으로 도서 상세페이지를 가지고 오고, 여기서 도서의 페이지를 추출해 본다.
import requests
isbn = 9791190090018
url = 'http://www.yes24.com/Product/Search?domain=BOOK&query={}'
r = requests.get(url.format(isbn))
HTML에서 데이터 추출하기: 뷰티플수프
파이썬에서 웹 페이지나 웹 기반 API를 호출하는데 requests 패키지를 많이 사용하듯이 HTML 안에 있는 내용을 찾을 때는 뷰티플수프가 널리 사용된다.
from bs4 import BeautifulSoup
soup = BeautifulSoup(r.text, 'html.parser')
prd_link = soup.find('a', attrs = {'class':'get_name'})
이 방법으로 링크 주소인 href 속성의 값을 얻을 수 있다.
도서 상세 페이지 HTML 가지고 오기
검색 결과 페이지를 가지고 온 것처럼 상세 페이지 주소를 만들어 requests.get() 함수를 호출한다.
url = 'http://www.yes34.com' + prd_link['href']
r = requests.get(url)
위의 결과로 원하는 책의 상세 페이지를 가지고 올 수 있다. 다음은 쪽수 정보가 담긴 HTML의 위치를 찾는 것이다.
find() 메서드로 품목정보 <div> 태그를 찾는다. find() 함수가 반환하는 결과는 BeautifulSoup 객체의 Tag 클래스 객체이다.
prd_detail = soup.find('div', attrs = {'id':'infoset_specific'})
<div> 태그로 찾은 품목정보 테이블에서 쪽수, 무게, 크기에 해당하는 행인 <tr> 태그를 찾아 <td> 태그 안에 있는 텍스트를 가지고 온다. find() 메서드를 사용해 특정 HTML 태그를 모두 찾아 리스트로 반환한다.
그리고 이 리스트를 for 문을 사용하여 태그 안의 텍스트가 '쪽수, 무게, 크'기에 해당하는지 검사한다. 여기서는 find_all() 메서드가 특정 HTML 태그를 모두 찾아 리스트로 반환해 준다.
prd_tr_list = prd_detail.find_all('tr)
for tr in prd_tr_list:
page_td = tr.find('td').get_text()
break
이 결과를 반복하기 위해 지금까지의 과정을 하나의 함수로 만들고 DataFrame에 apply() 함수를 사용하여 반복적으로 처리하면 원하는 결과를 모두 반환받을 수 있다.
def get_page_cnt(isbn):
url = 'http:''www.yes24.com/Product/Search?domain=800k&query={}'
r = requests.get(url.format(isbn))
soup = BeautifulSoup(r.text, 'html.parser')
prd_info = soup.find('a', attrs = {'class':''gd_name'})
if prd_info ==None:
return ''
url = 'http://www.yes24.com' + prd_info['href']
r = requests.get(url)
soup = BeautifulSoup(r.text, 'html.parser')
prd_detail = soup.find('div', attrs = {'id':'infoset_specific'})
prd_tr_list = prd_detail.find_all('tr')
for tr in prd_tr_list:
if tr.find('tr').get_text() == '쪽수, 무게, 크기':
return tr.find('td').get_text().split()[0]
return ''