낼름낼름 동동이

[ASAC 15일차] XML, JSON crawling 연습 본문

데이터분석/파이썬

[ASAC 15일차] XML, JSON crawling 연습

인죠인간 2024. 4. 12. 10:50
4월 11일의 기록

게임 분야의 프로젝트를 해보기 위해 이것저것 주제를 생각해보고 있는데, 정말 참신하고 마음에 드는 주제를 찾기가 어려운 것 같다. 그렇지만 생각만하고 흘려보낼 수는 없으니까 우선 아이디어 테이블에 하나씩 먼저 써보면서 내가 생각했을 때의 임팩트나 재밌는 가설이 나올만한 것들을 빠르게 써보면서 주제를 선정해봐야겠다.

 

 

1. kobis API 실습


API 연동하기

#실습 목적 : 영화 진흥 위원회에 있는 정보들 중에서 api를 이용해서 
# 최신 영화 관련 코드, 영화 영문 제목, 장르, 개봉일에 대한 정보들을 수집

#필요한 패키지들
import requests
import json
import pandas as pd

# headers = {
#      "Content-Type": "application/json;charset=UTF-8"
# }

# Step 1) 내가 필요한 정보들을 요청할 주소를 생성해야 한다.

#기본 주소 
url = " <http://www.kobis.or.kr/kobisopenapi/webservice/rest/movie/searchMovieList.json>"
# 필수 항목 : api key
mymovie_key = "thisisnotkey" # --> key 공개는 불가능!!
#부가적인 요청 사항 : itemPerPage --> 개수 40개 요청
itemperpage = "40" 

# 완성된 주소를 바탕으로 http 통신을 하려고 한다.
response = requests.get(url + '?key='+ mymovie_key + "&itemPerPage=" + itemperpage )

JSON으로 변환

# 받아온 response를 json형식으로 변환한다.
movie_data = response.json()

#직접 출력해보기

# 1번 영화의 영화코드값을 출력
movie_data["movieListResult"]["movieList"][0]['movieCd']

# 1번 영화의 영화 제목 출력
movie_data["movieListResult"]["movieList"][0]['movieNm']

# 1번 영화의 영문 제목 
movie_data["movieListResult"]["movieList"][0]['movieNmEn']

#1번 영화의 개봉년도
movie_data["movieListResult"]["movieList"][0]['prdtYear']

#1번 영화의 감독 이름
movie_data["movieListResult"]["movieList"][0]['directors'][0]['peopleNm']

DF으로 변환

## 40개 영화에 대해서 위의 정보들을 DF에 정리

# ==> 중복된 부분에 대한 수정
# 개별 영화에 대한 정보
temp = movie_data["movieListResult"]["movieList"][0]
# --> 수집된 데이터를 처리하실 떄에는 샘플 단위별로 처리!!!!
print(temp["movieCd"])
print(temp["movieNm"])
print(temp["movieNmEn"])
print(temp["openDt"])
if temp["directors"] != []:
    print(temp["directors"][0]["peopleNm"])
else:
    print("감독정보없음")

# 위의 코드들을 내가 받은 영화 수 만큼 돌려야 하니
tot_cnt = len(movie_data["movieListResult"]["movieList"])
print("처리할 영화 수:",tot_cnt)

for i in range(tot_cnt):
    # i번째 개별 영화에 대한 정보
    temp = movie_data["movieListResult"]["movieList"][i]
    # --> i번째 영화의 코드, 제목, 개봉일, 감독에 대한 정보.!!
    print(temp["movieCd"])
    print(temp["movieNm"])
    print(temp["movieNmEn"])
    print(temp["openDt"])
    if temp["directors"] != []:
        print(temp["directors"][0]["peopleNm"])
    else:
        print("감독정보없음")
    print("*"*100)
   

# 할 일 : 위의 정보들을 DF에 담아보자!!!!!
#         ==> 방법1) list 계열을 활용(deque)
tot_data = []
for idx, data in enumerate( movie_data["movieListResult"]["movieList"]):
    # print(data)
    # print("*"*100)
    # data ---> 개별 영화의 정보!!!!!!!Dict
    i_code = data["movieCd"]
    i_name = data["movieNm"]
    i_name_e = data["movieNmEn"]
    i_day    = data["openDt"]
    if data["directors"] != []:
        i_dir = data["directors"][0]["peopleNm"]
    else:
        i_dir = ""
    tot_data.append([i_code, i_name, i_name_e, i_day, i_dir])

#리스트에 저장했다면?
#이제 DF에 값을 집어넣기
movie_data["movieListResult"]["movieList"]
# ==> type : 리스트
# ==> 우리가 필요한 정보 : 리스트의 원소
for idx, data in enumerate( movie_data["movieListResult"]["movieList"]):
    print(data)
    print("*"*100)

실습 과제

  • 받아온 영화 리스트에서 각 영화의 상세 정보를 받아오기

JSON으로 만들기

# 필요한 패키지
import pandas as pd   # 데이터 처리를 위한 도구
import requests 
import json

# 기본 주소
url = "<http://www.kobis.or.kr/kobisopenapi/webservice/rest/movie/searchMovieList.json>"
#  필수 항목 : key
body = {
    "key" : "a1c9909058d214387fc77b8bff57870b",
    "itemPerPage" : 40
}
    

res = requests.get(url, params= body)
movie_json = res.json()

movie_list = []
for idx, data in enumerate(movie_json['movieListResult']['movieList']): #영화안의 데이터를 각각 가져와서 진행
        # data : 개별 영화에 대한 tag로 작성된 정보!!!!!
    # *** 중요 *** 데이터 정보 추출의 단위가 샘플/영화별!!!
    code = data['movieCd']
    name = data['movieNm']
    ename = data['movieNmEn']
    date = data['openDt']
    if data["directors"] != []:
        dir_name = data["directors"][0]["peopleNm"]
    else:
        dir_name = ""
    movie_list.append( [code, name, ename,date,dir_name])
    
    
movie_df = pd.DataFrame(
    data = movie_list,
    columns = ["moiveCd", "movieTitle","movieETitle", "openDay","DirName"]
)

# 2. date 정보를 각각 year, month, day로 분리하기
movie_df.head()
movie_df["year"] = movie_df.loc[:, "openDay"].apply(lambda x : x[:4])
movie_df["month"] = movie_df.loc[:, "openDay"].apply(lambda x : x[4:6])
movie_df["day"] = movie_df.loc[:, "openDay"].apply(lambda x : x[6:])

# 3. 각 영화별로 상세영화정보 요청해서(json),
#    1번 장르, 배우수, 1번 배우 이름, 1번 배우 배역이름
#    DF에다가 추가하세요!!!!!

genres = []
actor_names = []
actor_casts = []
detail_url_p1 = "<http://www.kobis.or.kr/kobisopenapi/webservice/rest/movie/searchMovieInfo.json>"

for code in movie_df.index:
    body = {
        "key" : "a1c9909058d214387fc77b8bff57870b",
        "movieCd" : code
    }
    res = requests.get(detail_url_p1, params = body)
    res_json = res.json()

    # 장르 정보 추출
    genres_list = [genre['genreNm'] for genre in res_json['movieInfoResult']['movieInfo']['genres']] 
    if genres_list:
        genres.append(genres_list[0])
    else:
        genres.append("")

    # 배우 정보 추출
    actors_list = [actor['peopleNm'] for actor in res_json['movieInfoResult']['movieInfo']['actors']]
    if actors_list:
        actor_names.append(actors_list[0])  # 첫 번째 배우의 이름만 사용
    else:
        actor_names.append("")

    # 배역 정보 추출
    casts_list = [actor['cast'] for actor in res_json['movieInfoResult']['movieInfo']['actors']]
    if casts_list:
        actor_casts.append(casts_list[0])  # 첫 번째 배우의 배역만 사용
    else:
        actor_casts.append("")

movie_df['genre'] = genres
movie_df['actor_name'] = actor_names
movie_df['actor_cast'] = actor_casts

XML로 만들기

# 필요한 패키지
import pandas as pd   # 데이터 처리를 위한 도구
import requests 
# xml/ html tag중심의 언어들에 대한 처리 : BeautifulSoup
from bs4 import BeautifulSoup

# 기본 주소
url_p1 = "<http://www.kobis.or.kr/kobisopenapi/webservice/rest/movie/searchMovieList.xml>"
#  필수 항목 : key
key = "a1c9909058d214387fc77b8bff57870b" #mykey
# 부가적인 요청 사항 : itemPerPage --> 갯수를 40개 요청
url_p2 = "40"
# --> 위의 정보들을 바탕으로 요청하는 url을 완성!!!!!!!!!
url = url_p1 + "?key="+key+"&itemPerPage="+url_p2

res = requests.get(url)
soup = BeautifulSoup(res.text, "html.parser")

movie_list = []
for idx, data in enumerate(soup.find_all("movie")):
    # data : 개별 영화에 대한 tag로 작성된 정보!!!!!
    # *** 중요 *** 데이터 정보 추출의 단위가 샘플/영화별!!!
    code = data.find("moviecd").text
    name = data.find("movienm").text
    ename = data.find("movienmen").text
    date = data.find("opendt").text
    if data.find_all("peoplenm") != []:
        dir_name = data.find("peoplenm").text
    else:
        dir_name = "X" # ---> 애 빼면,,,데이터가 밀림!!!
    movie_list.append( [code, name, ename,date,dir_name])
print("Done!!!")

movie_df = pd.DataFrame(movie_list,
             columns=["Code","Title","E-Title","openDay","Dir_Name"])
movie_df.head()

len(movie_df.loc[:,"Code"].unique()) # 유니크한 값들 갯수 또는 movie_df.set_index('Code') # set_index로 유니크하게 하기 

# 2. openDay의 컬럼을 보고, year, month, day 컬럼 생성
movie_df["year"] = movie_df.loc[:, "openDay"].apply(lambda x : x[:4])
movie_df["month"] = movie_df.loc[:, "openDay"].apply(lambda x : x[4:6])
movie_df["day"] = movie_df.loc[:, "openDay"].apply(lambda x : x[6:])

# 3. 각 영화별로 상세영화정보 요청해서(xml),
#    1번 장르, 배우수, 2번 배우 이름, 3번 배우 배역이름
#    DF에다가 추가하세요!!!!!
# *** xml양식으로 처리 ***

detail_url_p1 = "<http://www.kobis.or.kr/kobisopenapi/webservice/rest/movie/searchMovieInfo.xml>"

genres = []
actor_names = []
actor_casts = []
#  필수 항목 : key

for idx, data in enumerate(movie_df['Code']):
    body = {
        "key" : "a1c9909058d214387fc77b8bff57870b",
        "movieCd" : data
    }
    res = requests.get(detail_url_p1, params= body)
    soup = BeautifulSoup(res.text, "html.parser")

    # genre, actor_name, actor_cast 정보를 추출하여 리스트에 추가
    genre_tag = soup.find("genrenm")
    if genre_tag:
        genres.append(genre_tag.text)
    else:
        genres.append("")

    actor_tag = soup.find("peoplenm")
    if actor_tag:
        actor_names.append(actor_tag.text)
    else:
        actor_names.append("")

    cast_tag = soup.find("cast")
    if cast_tag:
        actor_casts.append(cast_tag.text)
    else:
        actor_casts.append("")

movie_df['genre'] = genres
movie_df['actor_name'] = actor_names
movie_df['actor_cast'] = actor_casts