원래 강의에서는 네이버 영화 평점 사이트로 분석을 하는데 230331일 부로 네이버 영화 평점 사이트 운영 종료....ㅠㅠ
네이버를 할 수 없으니 강의를 보면서 다음 영화 평점 사이트로 대체 해보기로 했다.
좀 다른데 잘 될지는 모르겠지만 스스로 해보면 더 늘겠지;)
영화 랭킹 탭 이동
영화 랭킹에서 평점순(현재 상영 영화) 선택
https://movie.daum.net/ranking/boxoffice/weekly?date=20230321
웹 페이지 주소에는 많은 정보가 담겨있다.
원하는 정보를 얻기 위해서 변화시켜줘야하는 주소의 규칙을 찾을 수 있다.
여기에서는 날짜 정보를 변경해주면 해당 페이지에 접근이 가능하다.
# requirements
import pandas as pd
from urllib.request import urlopen
from bs4 import BeautifulSoup
url = "https://movie.daum.net/ranking/boxoffice/weekly?date=20230404"
response = urlopen(url)
# 이 웹 페이지는 유저 헤더 정보를 주지 않아도 바로 응답해줌
# response.status
soup = BeautifulSoup(response, "html.parser")
print(soup.prettify())
찾아야 하는 것 -> 영화 제목, 평점
네이버 평점 사이트는 랭킹 메인 화면에 제목, 평점이 나와있는데 다음은 영화 제목, 개봉일이 나와있다. 영화 상세 페이지에 접근해야만 평점이 나온다.
앞서 시카고 매거진 처럼 해봐야지...ㅠ
다양한 방법들이 있다.
soup.select("strong.tit_item")[0].a["href"]
end = len(soup.select("strong.tit_item"))
base_url = "https://movie.daum.net"
movie_name = []
movie_url = []
for n in range(0, end):
movie_name.append(soup.select("strong.tit_item")[n].a.string)
movie_url.append(base_url + soup.select("strong.tit_item")[n].a["href"])
영화제목, URL을 DataFrame에 담자
import pandas as pd
data = {
"Movie": movie_name,
"URL": movie_url,
}
df = pd.DataFrame(data)
df
네이버 영화에서는 평점이 랭킹에 있었지만 다음은 없기 때문에 상세 페이지에 접근해서 가져오도록 하자.
req = urlopen(df["URL"][0])
# 이 웹 페이지는 유저 헤더 정보를 주지 않아도 바로 응답해줌
req.status
soup = BeautifulSoup(req, "html.parser")
print(soup.prettify())
movie_star = soup.select(".inner_cont")[1].select_one("dd").text
movie_star
end = len(soup.select("strong.tit_item"))
movie_star =[]
for n in range(0, end):
req = urlopen(df["URL"][n])
soup_req = BeautifulSoup(req, "html.parser")
movie_star.append(soup_req.select(".inner_cont")[1].select_one("dd").text)
movie_star
https://movie.daum.net/ranking/boxoffice/weekly?date=20230404
날짜만 변경하면 우리가 원하는 기간 만큼 데이터를 얻을 수 있다.
date = pd.date_range("2022.12.22", periods=100, freq="D") # 하루기준
date
date[0].strftime("%Y-%m-%d")
date[0].strftime("%Y.%m.%d")
date[0].strftime("%Y%m%d")
# 문자열 format
test_string = "Hi, I'm {name}"
test_string.format(name="Young")
import time
from tqdm import tqdm
movie_date = []
movie_name = []
movie_url = []
movie_point = []
base_url = "https://movie.daum.net"
for today in tqdm(date):
url = "https://movie.daum.net/ranking/boxoffice/weekly?date={date}"
response = urlopen(url.format(date=today.strftime("%Y%m%d")))
soup = BeautifulSoup(response, "html.parser")
end = len(soup.select("strong.tit_item"))
movie_date.extend([today for _ in range(0, end)])
for n in range(0, end):
movie_name.append(soup.select("strong.tit_item")[n].a.string)
now_url = base_url + soup.select("strong.tit_item")[n].a["href"]
movie_url.append(now_url)
# 영화 상세 페이지 - 평점 추출
req = urlopen(now_url)
soup_req = BeautifulSoup(req, "html.parser")
movie_point.append(soup_req.select(".inner_cont")[1].select_one("dd").text)
# 사이트에 사람이 아닌 속도로 접근하면 해킹이라고 인식할 수 있다.
time.sleep(0.5)
평점이 없는 페이지가 있어서 중간 중간 에러가 발생했다.
같은 태그인 평점 대신 관람객 수가 들어왔던 것!!
if문이나 예외처리로 하면 되겠지만 지금은 그것이 목적이 아니라서 최대한 평점이 있는 영화들 날짜로 피해서 연습을 했다.
# 데이터 프레임 생성
movie = pd.DataFrame({
"date": movie_date,
"title": movie_name,
"point": movie_point,
})
movie.tail()
movie.info()
movie["point"] = movie["point"].astype(float) # object -> float으로 변경
movie.info()
movie.to_csv(
"../data/03. daum_movie_data.csv", sep=",", encoding="utf-8"
)
df = pd.read_csv("../data/03. daum_movie_data.csv", index_col=0)
df
- 영화 이름으로 인덱스를 잡는다.
- 점수의 합산을 구한다.
- 다음은 날짜 별 평점이 없을 것이기 때문에 같은 평점이 계속 더해질 것
- 100일 간 네이버 영화 평점 합산 기준 베스트 & 워스트 10 선정
import numpy as np
import pandas as pd
movie = pd.read_csv("../data/03. daum_movie_data.csv", index_col=0)
movie.tail()
movie_unique = pd.pivot_table(data=movie, index="title", aggfunc=np.sum)
movie_unique
movie_best = movie_unique.sort_values(by="point", ascending=False) # 내림차순
movie_best.head()
주의⚠️
네이버가 아닌 다음 영화 상세 페이지에서 가져온 평점(최종 현재 평점)이기 때문에 평점이 모두 일치하다.
tmp = movie.query("title == ['더 배트맨']")
tmp
# 시각화
import matplotlib.pyplot as plt
from matplotlib import rc
rc("font", family="Malgun Gothic")
%matplotlib inline
plt.figure(figsize=(15, 8)) # x 15, y 8
plt.plot(tmp["date"], tmp["point"]) # 선 그래프 x축 - 날짜, y축 - 평점 => 날짜에 따른 평점 변화ㅏ를 선그래프로 표현(시계열)
plt.title("날짜별 평점")
plt.xlabel("날짜")
plt.ylabel("평점")
plt.legend(labels=["평점 추이"], loc="best")
plt.grid(True)
plt.figure(figsize=(15, 8)) # x 15, y 8
plt.plot(tmp["date"], tmp["point"]) # 선 그래프 x축 - 날짜, y축 - 평점 => 날짜에 따른 평점 변화ㅏ를 선그래프로 표현(시계열)
plt.title("날짜별 평점")
plt.xticks(rotation="vertical") # 날짜를 세로
plt.xlabel("날짜")
plt.ylabel("평점")
plt.legend(labels=["평점 추이"], loc="best")
plt.grid(True)
평점이 날짜 별 다른 데이터가 아닌 점, 날짜별로 상영 시작, 상영 종료 영화가 있기 때문에 상위, 하위라고 하기엔 문제가 있지만 실습하는 것에 의미를 둬야한다.
# 상위 10개 영화
movie_best.head(10)
# 하위 10개 영화
movie_best.tail(10)
movie_pivot = pd.pivot_table(data=movie, index="date", columns="title", values="point")
movie_pivot.head()
movie_pivot.to_excel("../data/03. movie_pivot.xlsx")
import platform
import seaborn as sns
from matplotlib import font_manager, rc
path = "C:/Windows/Fonts/malgun.ttf"
if platform.system() == "Darwin":
rc("font", family="Arial Unicode Ms")
elif platform.system() == "Windows":
font_name = font_manager.FontProperties(fname=path).get_name()
rc("font", family=font_name)
else:
print("Unknown system. sorry")
target_col = ["해적: 도깨비 깃발", "스파이더맨: 노 웨이 홈", "이상한 나라의 수학자", "배드 가이즈", "신비한 동물사전"]
plt.figure(figsize=(20, 8))
plt.title("날짜별 평점")
plt.xlabel("날짜")
plt.ylabel('평점')
plt.xticks(rotation="vertical")
plt.plot(movie_pivot[target_col])
plt.legend(target_col, loc="best")
plt.grid(True)
날짜를 선으로 구분
target_col = ["해적: 도깨비 깃발", "스파이더맨: 노 웨이 홈", "이상한 나라의 수학자", "배드 가이즈", "신비한 동물사전"]
plt.figure(figsize=(20, 8))
plt.title("날짜별 평점")
plt.xlabel("날짜")
plt.ylabel('평점')
plt.xticks(rotation="vertical")
plt.tick_params(bottom="off", labelbottom="off")
plt.plot(movie_pivot[target_col])
plt.legend(target_col, loc="best")
plt.grid(True)
네이버 영화 페이지가 운영 종료되는 바람에 다음 영화 페이지로 바꿔서 실습을 해본다고 훨씬 더 많은 시간이 소비되었다.
페이지 구성이 달라서 상세에 한 번 더 접근해야했던 점, 영화가 아닌 다른 관람영상이 포함되어 평점이 없었던 점 등등 시간이 걸리는 요소가 너무 많았다.
하지만 강의 내용과 다르게 스스로 배웠던 걸 적용해봄으로써 복습이 된 점은 좋았다.
그리고 컴퓨터가 왜 이렇게 느리지ㅠㅠ 정말 바꿀 때가 된것인가!!!
"이 글은 제로베이스 데이터 취업 스쿨 강의를 듣고 작성한 내용으로 제로베이스 데이터 취업 스쿨 강의 자료 일부를 발췌한 내용이 포함되어 있습니다."