멋사 AISCOOL 7기 Python/OUTPUT(project)

MINI-PRO1. 네이버영화 랭킹 및 평점 크롤링, 교보문고 베스트셀러 크롤링

dundunee 2022. 10. 4. 22:25

1. 네이버영화 랭킹 및 평점 크롤링

 

라이브러리로드

import pandas as pd
import numpy as np
import requests
from datetime import datetime, timedelta

 

네이버 영화 랭킹 페이지 살펴보기

랭킹은 모두 3가지 타입으로 나타나 있으며, 각각의 URL을 살펴본 결과 찾은 특징은 다음과 같다.
 

#조회순 sel = cnt
#평점순(현재상영) sel = cur
#평점순(모든영화) sel = pnt
 
 
주간 영화 랭킹 - 평점순(현재상영)받아오기
# 하루 랭킹 페이지를 받아오는 함수
def get_day_rank(sel, date):
    url = f"https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel={sel}&date={date}"
    response =  requests.get(url)

    table = pd.read_html(response.text)
    tmp = table[0]

    df = tmp[["영화명"]]
    df = df.dropna()
    df = df.reset_index(drop=True)
    df.columns = [date]

    return df

1) url을 받아온다.

2) requests로 요청해 응답을 받는다

3) pd.read_html로 table테그를 받아오고, 인덱싱을 통해 정보가 있는 데이터프레임을 생성한다.

- 이 때 beatifulsoup과 css selector를 통해 응답받은 html내에 table태그가 들어있는지 확인했다.

4) 필요한 컬럼만 출력한다. 

 

# 9월 마지막주(월-금)의 랭킹 페이지를 받아오는 함수
def get_month_rank(sel, date):
    rank = pd.DataFrame()

    date1 = datetime.strptime(date, "%Y%m%d") #날짜 데이터 타입 변환, 날짜 연산을 위해
    date2 = date1 + timedelta(days = 4) #입력받은 날짜로부터 4일뒤의 날짜가 변수에 담긴다

    # 종료일 까지 반복
    while date1 <= date2:
        dates = date1.strftime("%Y%m%d")
        df = get_day_rank(sel, dates)
        rank = pd.concat([rank, df], axis = 1)
        # 하루 더하기
        date1 += timedelta(days=1)

    return rank

1) 빈 데이터프레임을 만든다.

2) 반복문을 사용하기 위해 날짜 데이터를 변경 및 연산한다.

3) while반복문을 사용해 9월 마지막주의 월 ~금까지의 일별 랭킹을 데이터프레임에 담는다.

 

sel = "cur" #평점순(현재상영영화)랭킹
date = "20220926"
get_month_rank(sel, date)

(49, 5)

 

9월 한주간 영화 평점 수집하기
def get_week_score(sel, date):
    url = f"<https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel={sel}&tg=0&date={date}>"

    response = requests.get(url)

    table = pd.read_html(response.text)
    tmp = table[0]

    df = tmp[["영화명","평점.1"]] #영화와 평점을 같이 받아온다.
    df = df.dropna()
    df = df.reset_index(drop=True)
    df.columns = ["영화", date]

    return df
def get_total_rank(sel, date):
    rank = pd.DataFrame()

    date1 = datetime.strptime(date, "%Y%m%d")
    date2 = date1+timedelta(days = 4)

    # 종료일 까지 반복
    while date1 <= date2:
        dates = date1.strftime("%Y%m%d")
        df = get_week_score(sel, dates)

        if dates == date:
            rank = pd.concat([rank, df], axis = 1) #받아오는 날의 시작일의 영화가 index가 될 수 있게 한다.
        else:
            rank = pd.merge(rank, df, how = 'outer', on = "영화") #pd.merge함수를 사용해 영화 '평점'만 합친다.

        # 하루 더하기
        date1 += timedelta(days=1)

    return rank
sel = "cur"
date = "20220926"
get_total_rank(sel, date)

(54,6)

 

날짜 데이터를 조정하여 한 달간 일주일 단위의 영화 평점을 불러오는 코드는 아래와 같다.

import pandas as pd
import numpy as np
import requests
from datetime import datetime
from dateutil.relativedelta import relativedelta

def get_total_rank(sel, date):
    rank = pd.DataFrame()

    date1 = datetime.strptime(date, "%Y%m%d")
    date2 = date1 - relativedelta(months=1) #종료일은 기준일(date1)로부터 한달 전

    # 종료일 까지 반복
    while date1 > date2:
        dates = date1.strftime("%Y%m%d")
        df = get_week_score(sel, dates)

        if dates == date:
            rank = pd.concat([rank, df], axis = 1)
        else:
            rank = pd.merge(rank, df, how = 'outer', on = "영화")

        # 일주일 빼기
        date1 = date1 - relativedelta(days=7) #기준을로부터 일주일씩 뺀 날을 다시 date1에 넣는다.

    return rank

2. 교보분고 베스트셀러 크롤링하기

 

라이브러리로드

import pandas as pd
import numpy as np
import requests
from datetime import datetime, timedelta

 

교보문고 베스트셀러 페이지 살펴보기

각 페이지의 kind=0/2/3으로 주간, 연간, 월간이 구분됨을 알 수 있다.

 

8월 주간 베스트셀러 받아오기
def week_rank(year, month):

    year = str(year)
    month = str(month)

    url = '<http://www.kyobobook.co.kr/bestSellerNew/bestseller.laf?orderClick=D0a>'
    rank = pd.DataFrame()

    # payload에 들어갈 month형식을 맞추기위해, 예)2022084 = 8월4주, 2022101 = 10월1주
    if len(month) == 1:
        month = f'0{month}'
    else:
        month = month

    for i in range(1, 5):
        week = str(i)
        payload = {'kind': '0','perPage' : '50', "selBestYmw" : f'{year}{month}{week}'}
            
        response = requests.get(url, params = payload)
        html = bs4(response.text)

        titles = html.select('div.title > a > strong') #제목이 있는 태그
        
        title_list = []

        for i in range(len(titles)):
            title_list.append(titles[i].text.strip())

        df = pd.DataFrame(title_list)
        df.columns = [f"{month}월 {week}주 베스트셀러"]
        rank = pd.concat([rank, df], axis = 1)
        
    return rank

 

월간 베스트셀러 받아오기
def month_rank(year, month):

    year = str(year)

    url = '<http://www.kyobobook.co.kr/bestSellerNew/bestseller.laf?orderClick=D0a>'
    rank = pd.DataFrame()

    while month > 0:
        month = str(month)
        if len(month) == 1:
            month = f'0{month}'
        else:
            month = month

        payload = {'kind': '2','perPage' : '20', "selBestYmw" : f'{year}{month}0'} #kind=2는 월간, 20페이지씩 받아오기, selBestYmw는 월간날짜
            
        response = requests.get(url, params = payload)
        html = bs4(response.text)

        titles = html.select('div.title > a > strong') #책 제목이 있는 위치
        title_list = []

        for i in range(len(titles)):
            title_list.append(titles[i].text.strip())

        df = pd.DataFrame(title_list)
        df.columns = [f"{month}월 베스트셀러"]
        rank = pd.concat([rank, df], axis = 1)

        month = int(month) - 1
        
    return rank