Coding Feature.

파이썬으로 IMDb 크롤링 실습 #1 with Beautiful Soup 본문

Programming Language/Python

파이썬으로 IMDb 크롤링 실습 #1 with Beautiful Soup

codingfeature 2023. 7. 23. 21:14

Made with Stable Diffusion

 

Video

위 영상을 참고하며 실습해보았다.

 

IMDb 라는 유명한 영화 관련 웹사이트의 컨텐츠를 추출하기 위해 requests라는 python 용 HTTP 라이브러리와 Beautiful Soup 라는 파이썬 패키지를 사용한다. 

뷰티풀 수프(Beautiful Soup)는 HTML과 XML 문서들의 구문을 분석하기 위한 파이썬 패키지이다. HTML로부터 데이터를 추출하기 위해 사용할 수 있는 파싱된 페이지의 파스 트리를 만드는데, 이는 웹 스크래핑에 유용하다.

(출처: 위키백과)

(항상 느끼는 거지만 개발자들의 작명 센스는 역시 명불허전이다.)

 

IMDb top 100 영화들의 제목을 스크래핑 하기 위해 아래와 같은 코드를 작성해보았다.

import requests
from bs4 import BeautifulSoup

url = 'https://www.imdb.com/search/title/?groups=top_100&sort=user_rating,desc'
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')

movie_name = []

movie_data = soup.findAll('div', attrs= {'class': 'lister-item mode-advanced'})

for i in movie_data:
    movie_name.append(i.h3.a.text)

print(movie_name)

 

url 변수에 먼저 IMDb top 100 영화 리스트가 존재하는 url string 값을 넣어주고,

requests 라이브러리의 get 함수로 페이지의 HTTP를 요청하고 Response 객체를 받는다.

 

그리고 

soup = BeautifulSoup(response.content, 'html.parser')

에서 soup에 위 Response의 content(바이트 문자열)를 BeautifulSoup 클래스의 객체 형태로 받게 된다.

 

그 다음

movie_data = soup.findAll('div', attrs= {'class': 'lister-item mode-advanced'})

에서 BeautifulSoup 클래스의 findAll 함수를 통해 클래스가 lister-item mode-advanced인 div 태그를 모두 가져온 뒤 movie_data에 저장한다.

movie_data에 저장되는 값은 ResultSet이라는 형식인데 list와 유사한 형식이라고 한다.

 

따라서 for 문을 통해 movie_data 리스트에서 div 태그 내 h3 태크 내 a 태크 내 text 값(영화 제목, i.h3.a.text)을 movie_name 리스트에 append 시키면 영화 제목 list를 만들 수 있는 것이다.

 

print 결과

여기에

1) 평점을 매긴 사람의 수가 많아 평점의 신빙성이 높아야 하고, (500,000명 이상)

2) 상업적으로 꽤 성공한(1억 달러 이상의 수입)

조건을 추가하여 데이터를 추출해보기로 했다.

 

 

IMDb 웹사이트의 경우, 평점 수와 수입이 모두 name 속성이 'nv'인 span 태그에 있었다.

따라서 이 둘을 구별하기 위해 find_all 이라는 함수를 사용했다.

find_all 함수의 경우, find와는 달리 반환을 list 형식으로 해주기 때문에 name 속성이 'nv'인 span 태그 여러 개를 리스트 형식으로 받아올 수 있었다. (더 정확히는 ResultSet 객체, 리스트와 비슷한 형식.)

 

평점 수는 name이 'nv'인 태그 중 첫 번째 span 태그에, 수익은 두 번째 span 태그에 있었다.

따라서 temp에 find_all 함수를 통해 위 태그를 리스트 형식으로 받아오고,

각각 temp[0]과 temp[1] 로 구분지을 수 있었다.

검색해본 결과 위 방법으로 해도 되고 selector 를 통해서 다른 방식으로도 할 수 있다고 하는데 이는 좀 더 공부해봐야겠다.

 

그리고 data-value 라는 태그의 속성 값에 평점 수와 수익이 있어서 그걸 가져오기 위해 ['data-value']를 뒤에 붙였다.

결국 평점 수와 수익은 다음과 같은 코드를 통해 가져올 수 있었다.

temp = i.find('p', attrs = {'class': 'sort-num_votes-visible'}).find_all('span', attrs = {'name': 'nv'})
int(temp[0]['data-value']) #data-value 속성 값 가져오기
int(temp[1]['data-value'].replace(',','')))

그리고 수익은 값 중간에 ',' 문자가 있어서 이를 제거하기 위해 replace(',' , '') 함수를 사용했다.

그리고 integer 값으로 변경시키기 위해 int 함수를 사용했다.

 

최종 코드는 다음과 같다.

import requests
from bs4 import BeautifulSoup

url = 'https://www.imdb.com/search/title/?groups=top_100&sort=user_rating,desc'
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')

movie_name = []
movie_votes = []
movie_grosses = []

movie_data = soup.findAll('div', attrs= {'class': 'lister-item mode-advanced'})

for i in movie_data:
    movie_name.append(i.h3.a.text)

    temp = i.find('p', attrs = {'class': 'sort-num_votes-visible'}).find_all('span', attrs = {'name': 'nv'}) #find_all은 list 형식으로 반환
    movie_votes.append(int(temp[0]['data-value'])) #data-value 속성 값 가져오기
    movie_grosses.append(int(temp[1]['data-value'].replace(',','')))

for i in range(len(movie_data)):
    if(movie_votes[i] > 500000 and movie_grosses[i] > 100000000):
        print(movie_name[i] + ', 평점 수 : ' + str(movie_votes[i]) + ', 영화 수입($) : ' + str(movie_grosses[i]))

 

결과 prompt. 상당히 훌륭한 영화 리스트이다.

위 결과값을 보면  "스파이더맨 어크로스 더 스파이더버스" 나 "오펜하이머" 는 분명히 top 100에 들어가지만 최근에 개봉한 것이므로 평점 수 부족으로 리스트에 빠진 것을 확인할 수 있었다.

이렇게 양질의 정보를 추출, 가공할 수 있었다.

 

위 실습은 한 페이지만 가지고 했기 때문에 정보량에 제한이 있었다.

그 다음은 여러 페이지에 대해서 스크래핑을 하는 방법을 생각해봐야겠다.

또한 단순히 실습이 아니라 이러한 스크래핑을 어떻게 실제 프로젝트에 적용해볼 수 있는지도 생각해봐야겠다.

 

요약.

- Beautiful Soup 라는 파이썬 패키지를 통해 웹 스크래핑 가능.