[Python] 네이버 영화 페이지 크롤링
Database / Python / MongoDB / Sparta
2021.07.25.

image.info

네이버 영화 랭킹, 제목, 평점 가져오기

네이버 영화 페이지에서 크롤링을 통해 데이터를 제어하고자 한다. 네이버 영화 바로가기

image.info

🔽 파이썬에 requests, BeautifulSoup, pymongo 패키지를 설치한다.

image.info

🔽 위 패키지들을 import 시키고, mongoDB client를 불러준다. database name은 ‘testdb’로 정했다.

# crawling_movie_list.py
import requests
from bs4 import BeautifulSoup
from pymongo import MongoClient

client = MongoClient('localhost', 27017)
db = client.testdb

🔽 크롤링을 위해 기본 브라우저 속성을 잡아주고, 데이터를 받아온다.

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://movie.naver.com/movie/sdb/rank/rmovie.nhn?sel=pnt&date=20210723', headers=headers)

🔽 위에서 본 네이버 영화 페이지의 전체 를 모두 가져온다

soup = BeautifulSoup(data.text, 'html.parser')

🔽 이제 우리가 필요한 영화 제목들을 가져와보자.

크롤링한 source 코드를 보고 가져올 부분 근처를 보고, 가장 가까운 부모 id값을 찾아 #태그로 불러준다.

Chrome Browser를 이용하면 해당 부분에서 우클릭으로 copy > copy selector 기능을 통해 가져올 수 있다.

각 영화 정보는 <tr 태그> 안에 담겨져 있다.

tr_tags = soup.select('#old_content > table > tbody > tr')

🔽 이제 영화 제목이 담긴 <a 태그> 부분을 가져온다.

for tr in tr_tags:
    a_tag = tr.select_one('td.title > div > a')

🔽 네이버 영화 페이지에는 10개 영화마다 구분선이 존재하는데, 구분선도 <tr 태그> 안에 담겨 있기 때문에, for loop를 돌려 하위 값을 불러오고자하면 오류가 발생한다. 따라서 구분선 제외하는 작업이 필요하다.

구분선을 제외하고, 영화 제목을 출력해보면 아래와 같이 50개의 영화 제목이 출력된다.

if a_tag is not None:
    title = a_tag.text
    print(title)
    
>> 그린 북
가버나움
디지몬 어드벤처 라스트 에볼루션 : 인연
...
쉰들러 리스트
클레멘타인
여인의 향기

🔽 제목이 잘 들어오는 것을 확인했다면, 이제 순위, 제목, 평점을 가져와보자.

순위는 <img 태그> 안의 alt 속성안에 들어있고, 평점은 <td 태그> 중 class=“point” 인 태그안에 들어있다.

결과를 확인하면 아래와 같이 rank, title, stars 순으로 출력해준다.

if a_tag is not None:
    rank = tr.select_one('td:nth-child(1) > img')['alt']
    title = a_tag.text
    stars = tr.select_one('td.point').text

    print(rank, title, stars)

>> 01 그린 북 9.60
02 가버나움 9.59
03 디지몬 어드벤처 라스트 에볼루션 : 인연 9.54
...
48 쉰들러 리스트 9.37
49 클레멘타인 9.37
50 여인의 향기 9.37

🔽 이제 mongoDB에 넣어보자. 앞서 mongoDB에 testdb라는 collection을 만들어 두었다. 이제 아래 코드를 통해 movies라는 테이블을 만들고, 그 안에 영화 목록을 넣어보자.

영화 순위, 제목, 평점을 딕셔너리로 묶어주고 insert_one()을 통해 movies 테이블 안으로 인서트 해준다.

if a_tag is not None:
    rank = tr.select_one('td:nth-child(1) > img')['alt']
    title = a_tag.text
    stars = tr.select_one('td.point').text

    # print(rank, title, stars)
    item = {
        'rank': rank,
        'title': title,
        'stars': stars
    }
    db.movies.insert_one(item)

🔽 MongoDB를 확인해보면 아래와 같이 들어오는 것을 볼 수 있다.

MongoDB를 확인하기 위해 ‘Robo 3T’라는 open-source MongoDB GUI를 사용했다. Robo 3T 바로가기

image.info

🔽 전체 코드를 보면 다음과 같다.

import requests
from bs4 import BeautifulSoup
from pymongo import MongoClient

client = MongoClient('localhost', 27017)
db = client.testdb

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) '
                         'Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://movie.naver.com/movie/sdb/rank/rmovie.nhn?sel=pnt&date=20210723', headers=headers)

# 해당 페이지의 Elements 를 모두 가져오자
soup = BeautifulSoup(data.text, 'html.parser')

# 영화 제목들 가져오기 (.select)
tr_tags = soup.select('#old_content > table > tbody > tr')

for tr in tr_tags:
    # 책 제목이 담긴 <a 태그> 부분을 가져오자
    a_tag = tr.select_one('td.title > div > a')

    # week3-3 부분들이 None 처리되어 들어온다
    # None 부분들을 필터하고 제목들 가져오자
    if a_tag is not None:

        # rank, title, evaluation 확인하기
        # rank 값이 들어있는 부분인 <img 태그>를 가져오자
        # rank 값은 'alt' 속성에 담겨있다
        rank = tr.select_one('td:nth-child(1) > img')['alt']
        title = a_tag.text
        stars = tr.select_one('td.point').text

        item = {
            'rank': rank,
            'title': title,
            'stars': stars
        }
        db.movies.insert_one(item)
Thank You for Visiting My Blog, Have a Good Day 😆
© 2021 Bae Kim, Powered By Gatsby.