Python을 사용하여 IMDB 데이터를 스크랩하는 방법

댓글: 0

오늘날에는 IMDB와 같은 온라인 소셜 플랫폼에서 데이터를 추출하는 것이 연구나 즐거움을 위해 꼭 필요한 영화 관련 정보를 수집하는 효과적인 방법이 될 수 있습니다. 이 튜토리얼에서는 Python을 사용하여 IMDB에서 상위 250개 영화를 스크랩하고 영화 제목, 영화 요약, 평점, 장르 등과 같은 세부 정보를 추출하는 방법을 안내합니다.

IMDB와 같은 웹사이트를 스크랩할 때는 탐지 위험을 최소화하고 성공적인 데이터 검색을 보장하기 위해 실제 사용자의 행동을 시뮬레이션하는 것이 중요합니다. 다음은 사용할 수 있는 몇 가지 전략입니다:

  1. IP 차단을 피하세요: 웹사이트는 스크래핑을 방지하기 위해 단일 IP 주소에서 수행할 수 있는 요청 횟수를 제한하는 경우가 많습니다. 프록시를 사용하면 여러 IP 주소로 요청을 분산하여 차단될 위험을 줄일 수 있습니다.
  2. 익명성 보장: 프록시는 사용자의 실제 IP 주소를 마스킹하여 개인정보를 보호할 뿐만 아니라 웹사이트가 스크래핑 활동을 추적하기 어렵게 만듭니다.
  3. 속도 제한 준수: 여러 프록시를 통해 요청을 분산하면 쿼리 빈도를 관리하여 웹사이트의 속도 제한을 준수하고 스크래핑 방지 조치가 트리거될 가능성을 줄일 수 있습니다.
  4. 서버 의심 우회: 사용자 에이전트와 같이 일반적인 브라우저의 헤더를 모방하는 헤더를 통합하면 스크래핑 요청이 정상적인 사용자 요청처럼 보이게 할 수 있습니다. 이렇게 하면 서버가 사용자의 활동을 의심스러운 것으로 플래그 지정하지 못하게 할 수 있습니다.

1단계: 스크래퍼 준비하기

이 튜토리얼에서는 웹 콘텐츠를 다운로드하기 위해 Python의 요청 라이브러리, HTML 구문 분석을 위한 lxml, 필요에 따라 형식이 지정된 데이터를 처리하기 위한 json 라이브러리를 사용하겠습니다. 먼저 필요한 라이브러리를 설치합니다.

라이브러리 설치하기

시작하기 전에 필요한 Python 라이브러리를 설치해야 합니다. 터미널에서 다음 명령을 실행하여 설치하세요:


pip install requests lxml

이러한 라이브러리는 HTTP 요청을 하고, HTML 콘텐츠를 구문 분석하고, 추출된 데이터를 처리하는 데 사용됩니다.

HTTP 요청 헤더 구성하기

우리의 요청을 실제 웹 브라우저의 요청과 유사하게 만들려면 HTTP 헤더를 적절히 설정하는 것이 중요합니다. 다음은 스크립트에서 이러한 헤더를 구성하는 방법의 예시입니다:


import requests

headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'accept-language': 'en-IN,en;q=0.9',
    'cache-control': 'no-cache',
    'dnt': '1',  # 추적 금지 헤더
    'pragma': 'no-cache',
    'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Linux"',
    'sec-fetch-dest': 'document',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-site': 'none',
    'sec-fetch-user': '?1',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
}

response = requests.get('https://www.imdb.com/chart/top/', headers=headers)

프록시 설정하기

프록시는 대규모 스크래핑에 유용합니다. 여러 IP로 요청을 분산하여 차단되는 것을 방지할 수 있습니다. 프록시를 추가하는 방법은 다음과 같습니다:


proxies = {
    "http": "http://your_proxy_server",
    "https": "https://your_proxy_server"
}

response = requests.get('https://www.imdb.com/chart/top/', headers=headers, proxies=proxies)

"your_proxy_server"를 액세스 권한이 있는 실제 프록시 세부 정보로 바꾸세요. 이렇게 하면 IP 주소가 노출되지 않고 차단되는 것을 방지할 수 있습니다.

2단계: HTML 콘텐츠 구문 분석

웹페이지 콘텐츠를 가져온 후에는 이를 파싱하여 동영상 세부 정보를 추출해야 합니다. HTML을 구문 분석하는 데는 lxml을 사용하고 구조화된 데이터를 처리하는 데는 json을 사용합니다:


from lxml.html import fromstring
import json

# HTML 응답 구문 분석
parser = fromstring(response.text)

# 스크립트 태그에서 JSON-LD 데이터(구조화된 데이터)를 추출합니다.
raw_data = parser.xpath('//script[@type="application/ld+json"]/text()')[0]
json_data = json.loads(raw_data)

# 이제 JSON 형식의 구조화된 동영상 데이터가 생겼습니다.

3단계: 동영상 세부 정보 추출

IMDB Top 250 페이지에는 HTML에 내장된 구조화된 데이터가 포함되어 있으며, XPath를 사용하여 쉽게 액세스하고 JSON으로 구문 분석할 수 있습니다. 이름, 설명, 평점, 장르 등과 같은 영화 세부 정보를 추출하겠습니다:


movies_details = json_data.get('itemListElement')

# 동영상 데이터 반복 재생
movies_data = []
for movie in movies_details:
    movie_type = movie['item']['@type']
    url = movie['item']['url']
    name = movie['item']['name']
    description = movie['item']['description']
    image = movie['item']['image']
    bestRating = movie['item']['aggregateRating']['bestRating']
    worstRating = movie['item']['aggregateRating']['worstRating']
    ratingValue = movie['item']['aggregateRating']['ratingValue']
    ratingCount = movie['item']['aggregateRating']['ratingCount']
    contentRating = movie['item'].get('contentRating')
    genre = movie['item']['genre']
    duration = movie['item']['duration']
    
    # 각 동영상의 데이터를 목록에 추가합니다.
    movies_data.append({
        'movie_type': movie_type,
        'url': url,
        'name': name,
        'description': description,
        'image': image,
        'bestRating': bestRating,
        'worstRating': worstRating,
        'ratingValue': ratingValue,
        'ratingCount': ratingCount,
        'contentRating': contentRating,
        'genre': genre,
        'duration': duration
    })

4단계: 데이터 저장

데이터를 추출한 후에는 분석하기 쉬운 형식으로 저장하는 것이 중요합니다. 여기서는 pandas 라이브러리를 사용하여 CSV 파일로 저장하겠습니다:


import pandas as pd

# 영화 목록을 판다 데이터프레임으로 변환하기
df = pd.DataFrame(movies_data)

# 데이터를 CSV 파일로 저장
df.to_csv('imdb_top_250_movies.csv', index=False)

print("IMDB Top 250 movies data saved to imdb_top_250_movies.csv")

코드 완성

다음은 IMDB의 상위 250개 영화를 스크랩하는 전체 코드입니다:


import requests
from lxml.html import fromstring
import json
import pandas as pd

# 요청에 대한 헤더 정의
headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'accept-language': 'en-IN,en;q=0.9',
    'cache-control': 'no-cache',
    'dnt': '1',
    'pragma': 'no-cache',
    'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Linux"',
    'sec-fetch-dest': 'document',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-site': 'none',
    'sec-fetch-user': '?1',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
}

# 선택 사항으로 프록시 설정
proxies = {
    "http": "http://your_proxy_server",
    "https": "https://your_proxy_server"
}

# IMDB Top 250 페이지로 요청 보내기
response = requests.get('https://www.imdb.com/chart/top/', headers=headers, proxies=proxies)

# HTML 응답 구문 분석
parser = fromstring(response.text)

# JSON-LD 데이터 추출
raw_data = parser.xpath('//script[@type="application/ld+json"]/text()')[0]
json_data = json.loads(raw_data)

# 동영상 세부 정보 추출
movies_details = json_data.get('itemListElement')

movies_data = []
for movie in movies_details:
    movie_type = movie['item']['@type']
    url = movie['item']['url']
    name = movie['item']['name']
    description = movie['item']['description']
    image = movie['item']['image']
    bestRating = movie['item']['aggregateRating']['bestRating']
    worstRating = movie['item']['aggregateRating']['worstRating']
    ratingValue = movie['item']['aggregateRating']['ratingValue']
    ratingCount = movie['item']['aggregateRating']['ratingCount']
    contentRating = movie['item'].get('contentRating')
    genre = movie['item']['genre']
    duration = movie['item']['duration']
    
    movies_data.append({
        'movie_type': movie_type,
        'url': url,
        'name': name,
        'description': description,
        'image': image,
        'bestRating': bestRating,
        'worstRating': worstRating,
        'ratingValue': ratingValue,
        'ratingCount': ratingCount,
        'contentRating': contentRating,
        'genre': genre,
        'duration': duration
    })

# 데이터를 CSV 파일로 저장
df = pd.DataFrame(movies_data)
df.to_csv('imdb_top_250_movies.csv', index=False)
print("IMDB Top 250 movies data saved to imdb_top_250_movies.csv")

윤리적 고려 사항

웹사이트를 스크랩하기 전에 윤리적 및 법적 문제를 고려하는 것이 중요합니다:

  • Respect the Robots.txt: 웹사이트의 스크랩이 허용되는 부분을 확인하려면 IMDB의 robots.txt 파일을 확인하세요. 항상 웹사이트의 정책을 준수하세요.
  • 서버 과부하를 피하세요: 서버에 불필요한 부하가 걸리지 않도록 요청 빈도를 제한하여 책임감 있게 데이터를 스크랩하세요.
  • 서비스 약관을 존중하세요: 스크래핑이 IMDB의 서비스 약관을 위반하지 않는지 확인하세요.

항상 규칙을 염두에 두고 합법적인 목적으로 웹 스크래핑을 사용하세요.

댓글:

0 댓글