파이썬으로 IMDb 스크래핑하기: 실제로 작동하는 코드

최종 업데이트: April 28, 2026

최근에 "파이썬으로 IMDb 스크래핑"을 검색해 보셨다면 아마 이런 점을 느끼셨을 거예요. 대부분의 튜토리얼이 이미 깨져 있습니다. 그냥 "조금 오래됨" 수준이 아니라, "결과는 0개고 NoneType 오류가 쏟아지는" 수준이죠.

지난 몇 주 동안 GeeksforGeeks, Medium, freeCodeCamp, Kaggle 노트북 등 찾을 수 있는 주요 IMDb 스크래핑 튜토리얼을 전부 테스트해 봤어요. 중 대다수는 IMDb가 Top 250 페이지를 재설계한 2023년 6월 이후로는 더 이상 존재하지 않는 CSS 선택자(td.titleColumn, td.ratingColumn)를 참고하고 있었습니다. 그 결과는? 왜 내 코드가 빈 결과를 반환하느냐고 묻는 개발자들로 가득한 포럼, 그리고 "모든 파서를 고치는 것 말고는 우리가 할 수 있는 게 많지 않다"고 인정하는 상황이었죠. 이 가이드에서는 지금 바로 실제로 작동하는 두 가지 파이썬 방법, 페이지네이션과 흔한 오류를 다루는 법, 파이썬이 아예 적절한 도구가 아닐 때, 그리고 스크래퍼가 금세 쓸모없어지지 않도록 미래 대응성을 높이는 방법까지 다룹니다.

파이썬으로 IMDb를 스크래핑한다는 건 무슨 뜻일까요?

웹 스크래핑은 웹페이지에서 데이터를 프로그램으로 추출하는 과정이에요. 손으로 복사하고 붙여넣는 대신, 그 일을 해 주는 스크립트를 작성하는 거죠. "IMDb를 스크래핑한다"는 말은 파이썬을 사용해 IMDb 웹페이지에서 제목, 평점, 장르, 출연진, 상영 시간, 투표 수 같은 구조화된 영화 데이터를 가져오는 것을 뜻합니다.

이 작업에 흔히 쓰는 파이썬 스택은 세 가지 라이브러리로 구성돼요. requests는 웹페이지를 가져오고, BeautifulSoup는 HTML을 파싱해 데이터를 찾으며, pandas는 결과를 정리하고 내보내는 역할을 합니다. 자바스크립트 렌더링이 필요한 페이지에서는 Selenium이나 Playwright를 쓰는 튜토리얼도 있지만, 곧 보시겠지만 더 빠른 방법도 있습니다.

중요한 주의사항 하나: 이 가이드의 내용은 2025년 중반 기준 IMDb의 현재 페이지 구조를 바탕으로 검증했어요. IMDb는 대략 6~12개월마다 구조를 바꾸므로, 2027년에 이 글을 읽고 있다면 일부 선택자가 달라졌을 수도 있습니다. (그 대응법도 설명할게요.)

왜 파이썬으로 IMDb를 스크래핑할까요? 실제 활용 사례

코드를 한 줄도 쓰기 전에 먼저 생각해 볼 질문이 있어요. IMDb 데이터로 실제로 뭘 할 수 있을까요? 답은 누구인지에 따라 달라집니다.

IMDb 리뷰 데이터셋은 전 세계에서 가장 널리 쓰이는 NLP 벤치마크 중 하나예요. Maas 외(2011)의 기반 논문은 됐고, 이 데이터셋은 TensorFlow, Keras, PyTorch에 기본으로 포함돼 있습니다. Hugging Face에서는 stanfordnlp/imdb 데이터셋이 월 213,321회 다운로드되며 1,500개 이상의 모델 학습에 사용됐어요. 즉, 머신러닝을 한다면 이미 IMDb 데이터를 익숙하게 다루고 있을 가능성이 높습니다.

하지만 활용 범위는 학계에만 머물지 않아요.

활용 사례대상필요한 데이터 필드
영화 추천 엔진데이터 과학자, 취미 개발자제목, 장르, 평점, 출연진
스트리밍 플랫폼 콘텐츠 전략제품/콘텐츠 팀평점, 투표 수, 개봉 연도, 장르
감성 분석 / NLP 학습ML 연구자, 학생리뷰, 평점
경쟁 콘텐츠 분석엔터테인먼트 업계 분석가흥행 성적, 개봉일, 평점 추이
영화 관광 연구관광청, 여행사촬영지, 인기도 지표
학술 연구대학 연구자구조화된 영화 메타데이터 전반

영화 관광 시장만 해도 2025년 전 세계 기준 약 규모로 추정돼요. Netflix는 2024년에 콘텐츠에 170억 달러 이상을 썼고, 가 개인화 추천에서 비롯됐습니다. 즉, IMDb 데이터는 여러 산업에서 실제 의사결정에 쓰이고 있어요.

코드를 쓰기 전에 알아둘 IMDb 데이터 확보 방법

이 부분은 대부분의 튜토리얼이 통째로 건너뛰는 내용이에요. 그냥 pip install beautifulsoup4부터 시작하면서, 지금 상황에서 파이썬 스크래핑이 정말 맞는지 묻지 않거든요.

전체 선택지는 이렇습니다.

방법적합한 경우장점단점
Python + BeautifulSoup학습, 맞춤 추출완전한 제어, 유연함선택자가 취약하고 자주 깨짐
JSON-LD / __NEXT_DATA__ 추출안정성을 원하는 개발자JS 콘텐츠 처리, 더 견고함JSON 구조를 이해해야 함
IMDb 공식 데이터셋대규모 분석, 학술용합법적, 완전한 데이터, 2,600만+ 타이틀, 일일 업데이트TSV 형식, 리뷰/이미지 없음
Cinemagoer (IMDbPY) 라이브러리타이틀별 프로그램 조회파이썬다운 API, 풍부한 필드열린 이슈 88개, 마지막 릴리스 2023년 5월
TMDb API영화 메타데이터 + 이미지무료 API 키, JSON, 문서화 잘 됨소스가 다름(IMDb 평점 아님)
Thunderbit (노코드)비개발자, 빠른 내보내기2번 클릭 스크래핑, AI가 필드 제안, Excel/Sheets로 내보내기대량 스크래핑은 크레딧 기반

이 옵션들에 대해 몇 가지 덧붙이면, Cinemagoer는 2023년 5월 이후 PyPI 릴리스가 없고, IMDb의 2025년 6월 재설계 이후 대부분의 파서가 깨졌어요. 지금 당장 운영 환경에 쓰는 건 추천하지 않습니다. TMDb는 훌륭하지만 IMDb가 아닌 자체 평점 체계를 사용해요. 그리고 IMDb의 공식 엔터프라이즈 API는 AWS Data Exchange를 통해 연간 이 들기 때문에 대부분의 사람에게는 현실적인 선택지가 아닙니다.

코드를 전혀 쓰고 싶지 않은 분이라면, 가 IMDb 페이지를 읽고, 추출 필드(제목, 평점, 연도, 장르 등)를 자동으로 제안한 뒤, Excel, Google Sheets, Airtable, Notion으로 두 번의 클릭만에 내보내 줍니다. IMDb가 레이아웃을 바꿔도 AI가 적응하므로 유지해야 할 선택자가 없습니다. 이 부분은 뒤에서 더 자세히 설명할게요.

이제, 파이썬으로 직접 작성하고 싶은 분들을 위해 실제로 작동하는 두 가지 방법을 소개하겠습니다.

방법 1: BeautifulSoup으로 IMDb를 스크래핑하기 (전통적인 방식)

이건 대부분의 튜토리얼에서 볼 수 있는 고전적인 방식이에요. 잘 작동하긴 하지만, 먼저 분명히 말씀드릴게요. 오늘 다룰 방법들 중 가장 취약합니다. IMDb의 CSS 클래스 이름은 자동 생성되며, 재설계 때마다 바뀌거든요. 그래도 웹 스크래핑의 기초를 배우기엔 가장 좋은 방법입니다.

STEP 1: 파이썬 라이브러리 설치 및 import

다음 네 가지 패키지가 필요합니다.

1pip install requests beautifulsoup4 pandas lxml

각각의 역할은 이렇습니다.

  • requests — 웹페이지를 가져오기 위해 HTTP 요청을 보냄
  • beautifulsoup4 — HTML을 파싱해 특정 요소를 찾을 수 있게 함
  • pandas — 추출한 데이터를 표로 정리하고 CSV/Excel로 내보냄
  • lxml — 빠른 HTML 파서(BeautifulSoup의 백엔드로 사용 가능)

This paragraph contains content that cannot be parsed and has been skipped.

1import requests
2from bs4 import BeautifulSoup
3import pandas as pd

STEP 2: IMDb에 HTTP 요청 보내기

대부분의 초보자가 여기서 첫 벽을 만나요. IMDb는 올바른 User-Agent 헤더가 없는 요청을 차단합니다. 그러면 403 Forbidden 오류가 나와요. Python Requests의 기본 user-agent 문자열(python-requests/2.31.0)은 바로 차단됩니다.

1url = "https://www.imdb.com/chart/top/"
2headers = {
3    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
4    "Accept-Language": "en-US,en;q=0.9"
5}
6response = requests.get(url, headers=headers)
7if response.status_code != 200:
8    print(f"페이지 가져오기 실패: {response.status_code}")
9else:
10    print("페이지를 성공적으로 가져왔습니다")

Accept-Language 헤더도 중요해요. 이 값이 없으면 IMDb가 IP의 지리적 위치에 따라 다른 언어로 콘텐츠를 반환할 수 있습니다.

STEP 3: BeautifulSoup으로 HTML 파싱하기

HTML을 가져왔다면 BeautifulSoup 객체를 만들고 원하는 요소를 찾기 시작하면 됩니다. Chrome에서 IMDb Top 250 페이지를 열고, 영화 제목을 마우스 오른쪽 버튼으로 클릭한 뒤 "검사"를 눌러 HTML 구조를 확인해 보세요.

1soup = BeautifulSoup(response.text, "lxml")

2025년 중반 기준 Top 250 페이지는 다음 선택자를 사용합니다.

  • 영화 컨테이너: li.ipc-metadata-list-summary-item
  • 제목: h3.ipc-title__text
  • 연도: span.cli-title-metadata-item (첫 번째 span)
  • 평점: span.ipc-rating-star--rating

주의할 점은, ipc-로 시작하는 클래스 이름은 IMDb의 컴포넌트 시스템이 생성한 값이라는 거예요. 2023년 6월 재설계 이후 안정적으로 유지되고 있지만, 다시 바뀌지 않으리라는 보장은 없습니다.

STEP 4: 영화 데이터 추출하기(제목, 연도, 평점)

여기서는 많은 튜토리얼과 다르게 try/except 오류 처리를 넣었습니다. 제가 검토한 경쟁 가이드 대부분은 이 부분이 없었는데, 선택자가 바뀌었을 때 코드가 조용히 깨지는 이유가 바로 그거예요.

1movies = []
2movie_items = soup.select("li.ipc-metadata-list-summary-item")
3for item in movie_items:
4    try:
5        title_tag = item.select_one("h3.ipc-title__text")
6        title = title_tag.text.strip() if title_tag else "N/A"
7        year_tag = item.select_one("span.cli-title-metadata-item")
8        year = year_tag.text.strip() if year_tag else "N/A"
9        rating_tag = item.select_one("span.ipc-rating-star--rating")
10        rating = rating_tag.text.strip() if rating_tag else "N/A"
11> This paragraph contains content that cannot be parsed and has been skipped.
12print(f"{len(movies)}개의 영화를 추출했습니다")

STEP 5: Pandas로 CSV 또는 Excel에 저장하기

1df = pd.DataFrame(movies)
2df.to_csv("imdb_top_250.csv", index=False)
3df.to_excel("imdb_top_250.xlsx", index=False)
4print(df.head())

예시 출력은 다음과 같습니다.

1                          title  year rating
20  1. 쇼생크 탈출                1994    9.3
31           2. 대부              1972    9.2
42     3. 다크 나이트             2008    9.0
53  4. 대부 2                    1974    9.0
64         5. 12인의 성난 사람들  1957    9.0

작동은 합니다. 하지만 CSS 선택자에 매달려 있어서 언제든 깨질 수 있죠. 그래서 제가 실제로 추천하는 접근은 다음 방법입니다.

방법 2: JSON-LD 트릭 — HTML 파싱을 아예 건너뛰기

이건 경쟁 기사에서 거의 다루지 않는 기법이고, 진지한 프로젝트라면 제가 사용할 방식이기도 해요. IMDb는 모든 페이지의 <script type="application/ld+json"> 태그 안에 (Linked Data용 JavaScript Object Notation) 형식의 구조화 데이터를 넣습니다. 이 데이터는 Schema.org 표준을 따르고, Google의 리치 검색 결과에도 사용되며, CSS 클래스 이름보다 훨씬 덜 자주 바뀝니다.

프로덕션급 도구인 Apify IMDb Scraper도 추출 우선순위를 "JSON-LD > NEXT_DATA > DOM" 순으로 둡니다. 저도 그 순서를 추천해요.

JSON-LD가 CSS 선택자보다 더 안정적인 이유

접근 방식JS 콘텐츠 처리 가능?UI 변경에 강한가?속도복잡도
BeautifulSoup + CSS 선택자❌ 아니요⚠️ 취약함(클래스명이 바뀜)빠름낮음
JSON-LD 추출✅ 예✅ Schema.org 표준을 따름빠름낮음~중간
__NEXT_DATA__ JSON 추출✅ 예✅ 비교적 안정적빠름낮음~중간
Selenium / Playwright✅ 예⚠️ 취약함느림중간~높음
Thunderbit (노코드, 2번 클릭)✅ 예(AI가 페이지를 읽음)✅ AI가 자동으로 적응함빠름없음

ipc-metadata-list-summary-item 같은 CSS 클래스명은 IMDb의 React 컴포넌트 시스템이 자동 생성한 값이며, 재설계 때마다 바뀝니다. 반면 JSON-LD 스키마는 표시 계층이 아니라 실제 데이터 모델을 표현해요. 책의 목차를 읽는 것과, 글자 크기만 보고 장을 구분하려는 것의 차이라고 보면 됩니다.

css-selectors-vs-json-ld.webp

단계별: JSON-LD에서 IMDb 데이터 추출하기

STEP 1: 페이지 가져오기

앞과 동일하게, 올바른 User-Agent 헤더와 함께 requests를 사용합니다.

1import requests
2from bs4 import BeautifulSoup
3import json
4import pandas as pd
5> This paragraph contains content that cannot be parsed and has been skipped.
6response = requests.get(url, headers=headers)
7soup = BeautifulSoup(response.text, "lxml")

STEP 2: JSON-LD script 태그 찾기

1script_tag = soup.find("script", {"type": "application/ld+json"})
2if not script_tag:
3    print("이 페이지에서 JSON-LD를 찾지 못했습니다")
4else:
5    data = json.loads(script_tag.string)
6    print(f"유형이 {data.get('@type', 'unknown')}인 JSON-LD를 찾았습니다")

STEP 3: 구조화 데이터 파싱하기

Top 250 페이지의 JSON-LD에는 250개 영화가 모두 들어 있는 itemListElement 배열이 있습니다. 각 항목에는 순위, 이름, URL, aggregateRating, datePublished, genre, description, director, actor 배열이 포함돼요.

1movies = []
2for item in data.get("itemListElement", []):
3    movie = item.get("item", {})
4    rating_info = movie.get("aggregateRating", {})
5> This paragraph contains content that cannot be parsed and has been skipped.
6#### STEP 4: CSV로 내보내기
7```python
8df = pd.DataFrame(movies)
9df.to_csv("imdb_top_250_json_ld.csv", index=False)
10print(df.head())

예시 출력:

1   rank                      title                                     url  rating  vote_count date_published              genre
20     1  쇼생크 탈출                  https://www.imdb.com/title/tt0111161/     9.3     2900000     1994-10-14     드라마
31     2            대부              https://www.imdb.com/title/tt0068646/     9.2     2000000     1972-03-24     범죄, 드라마
42     3          다크 나이트          https://www.imdb.com/title/tt0468569/     9.0     2800000     2008-07-18     액션, 범죄, 드라마

250개 영화가 전부 나옵니다. 깔끔하고 구조화되어 있으며, CSS 선택자 잡기 게임도 필요 없어요. 그리고 이 데이터는 Google 검색 결과에 쓰이는 Schema.org 표준을 따르기 때문에, 시각적 레이아웃보다 훨씬 바뀔 가능성이 낮습니다.

보너스: 개별 영화 페이지의 __NEXT_DATA__

개별 타이틀 페이지에서 더 풍부한 데이터(상영 시간, 전체 출연진, 줄거리 요약, 포스터 이미지 등)가 필요하다면 IMDb는 __NEXT_DATA__ JSON 객체도 함께 넣습니다. 이건 React가 페이지를 하이드레이션할 때 사용하는 데이터라서, 사이트가 망가지지 않는 한 제거될 수 없습니다.

1# /title/tt0111161/ 같은 개별 영화 페이지에서
2next_data_tag = soup.find("script", {"id": "__NEXT_DATA__"})
3if next_data_tag:
4    next_data = json.loads(next_data_tag.string)
5    above_fold = next_data["props"]["pageProps"]["aboveTheFoldData"]
6    title = above_fold["titleText"]["text"]
7    year = above_fold["releaseYear"]["year"]
8    rating = above_fold["ratingsSummary"]["aggregateRating"]
9    runtime_seconds = above_fold.get("runtime", {}).get("seconds", 0)
10    genres = [g["text"] for g in above_fold["genres"]["genres"]]
11    plot = above_fold["plot"]["plotText"]["plainText"]

차트/목록 페이지에는 JSON-LD를 쓰고, 개별 타이틀 페이지에는 __NEXT_DATA__를 사용하세요. 그게 프로덕션급 접근법입니다.

왜 IMDb 스크래퍼가 자꾸 깨질까요? 그리고 어떻게 고칠까요?

제가 확인한 모든 IMDb 스크래핑 포럼에서 가장 많이 나온 불만이 바로 이거예요. 사람들은 이렇게 씁니다. "UI 변경 때문에 일부 코드가 깨졌어요", "2024년에는 작동하지 않아요!" 그리고 반응은 대개 침묵이거나 "Selenium을 써 보세요"뿐이죠.

근본 원인은 IMDb가 React/Next.js 프런트엔드로 계속 전환하고 있기 때문입니다. 주요 깨짐 변화의 타임라인은 이렇습니다.

날짜변경 내용깨진 것
2022년 11월Name Pages 재설계기존 이름 페이지 스크래퍼
2023년 6월Top 250 페이지 재설계모든 td.titleColumn / td.ratingColumn 선택자
2023년 4월타이틀 하위 페이지 재설계소개, 수상, 뉴스 스크래퍼
2023년 10월고급 검색 재설계검색 기반 스크래퍼
2025년 6월/reference 페이지 재설계Cinemagoer 라이브러리 (대부분의 파서)

즉, 대략 6~12개월마다 한 번씩 큰 변경이 생기는 셈이에요. 스크래퍼가 CSS 클래스명에 의존한다면, 계속 달리는 러닝머신 위에 올라타 있는 것과 같습니다.

흔한 오류와 해결 방법

빈 결과 / NoneType 오류

가장 흔한 오류예요. AttributeError: 'NoneType' object has no attribute 'text'를 보게 됩니다. 이건 BeautifulSoup이 찾고 있는 요소를 발견하지 못했다는 뜻으로, 보통 CSS 클래스명이 바뀌었거나 콘텐츠가 JavaScript로 렌더링되기 때문입니다.

해결: JSON-LD 추출(위의 방법 2)로 전환하세요. 데이터가 초기 HTML 응답 안에 있어서 JavaScript가 필요 없습니다.

403 Forbidden

IMDb는 를 사용해 봇을 탐지하고 차단합니다. 가장 흔한 트리거는 User-Agent 헤더가 없거나 너무 명백히 가짜인 경우예요. 이 문제는 오픈소스 프로젝트와 에서 보고됐고, IMDb 직원도 이를 인정한 바 있습니다.

해결: 현실적인 브라우저 User-Agent 문자열과 Accept-Language: en-US 헤더를 항상 넣으세요. 연결 풀링을 위해 requests.Session()을 사용하세요.

결과가 25개만 나옴

IMDb 검색 페이지와 "Most Popular" 목록은 지연 로딩을 사용합니다. 처음에는 약 25개 정도만 렌더링하고, 스크롤할 때 AJAX로 나머지를 불러와요.

해결: 다음 섹션에서 설명할 URL 파라미터 페이지네이션을 사용하거나, 한 번의 응답으로 250개를 모두 불러오는 Top 250 페이지로 전환하세요.

갑자기 선택자가 작동하지 않음

더 이상 작동하지 않는 예전 선택자: td.titleColumn, td.ratingColumn, .lister-item-header, .inline-block.ratings-imdb-rating. 코드에 이 중 하나라도 쓰고 있다면 깨진 상태입니다.

해결: 자동 생성 클래스명보다 data-testid 속성(예: h1[data-testid="hero-title-block__title"])을 우선하세요. 가능하면 JSON-LD를 쓰는 것이 더 좋습니다.

의사결정 프레임워크: 단기 vs 장기 해결책

  • 단기 해결: 모든 선택자에 try/except를 추가하고, HTTP 상태 코드를 검증하며, 오류를 중단 대신 기록하기
  • 중기 해결: CSS 선택자에서 JSON-LD 추출로 전환하기(위의 방법 2)
  • 장기 해결: 대규모 분석에는 을 사용하거나, 페이지 구조를 매번 새로 읽어 AI가 자동 적응하는 같은 도구를 사용하기 — 유지해야 할 선택자가 없습니다

25개 결과 제한을 넘어서: IMDb 페이지네이션과 대용량 데이터 스크래핑

제가 검토한 경쟁 튜토리얼은 전부 딱 한 페이지만 스크래핑합니다. 페이지네이션은 다루지 않아요. 하지만 한 목록보다 더 많은 데이터가 필요하다면 금방 한계에 부딪힙니다.

페이지네이션이 필요 없는 페이지

좋은 소식이 있어요. Top 250 페이지는 서버 렌더링 응답 한 번에 250개 영화를 모두 불러옵니다. JSON-LD와 __NEXT_DATA__ 모두 전체 데이터셋을 담고 있어요. 페이지네이션이 필요 없습니다.

IMDb 검색 페이지네이션은 어떻게 작동할까요?

IMDb 검색 페이지는 start= URL 파라미터를 사용하며 50씩 증가합니다.

1https://www.imdb.com/search/title/?groups=top_1000&start=1
2https://www.imdb.com/search/title/?groups=top_1000&start=51
3https://www.imdb.com/search/title/?groups=top_1000&start=101

다음은 결과를 페이지 단위로 가져오는 파이썬 루프예요.

1import time
2all_movies = []
3for start in range(1, 1001, 50):  # 상위 1000개를 페이지 단위로 순회
4    url = f"https://www.imdb.com/search/title/?groups=top_1000&start={start}"
5    response = requests.get(url, headers=headers)
6    if response.status_code != 200:
7        print(f"start={start}에서 실패: {response.status_code}")
8        break
9    soup = BeautifulSoup(response.text, "lxml")
10    # 원하는 방법으로 영화 추출
11    # ...
12    print(f"start={start}부터 시작하는 페이지를 스크래핑했습니다")
13    time.sleep(3)  # 예의를 지키세요 — IMDb는 빠른 요청 약 50회 이후 차단할 수 있습니다

여기서 time.sleep(3)은 중요합니다. 커뮤니티 보고에 따르면 IMDb는 약 50회의 빠른 요청 이후 IP를 차단하기 시작합니다. 2~5초 사이의 랜덤 지연을 넣는 것이 좋은 습관이에요.

스크래핑을 아예 건너뛰는 경우: IMDb 공식 대량 데이터셋

정말 대규모 데이터가 필요하다면 IMDb는 에서 매일 갱신되는 7개의 무료 TSV 파일을 제공합니다.

파일내용크기
title.basics.tsv.gz제목, 유형, 장르, 상영 시간, 연도약 800MB
title.ratings.tsv.gz평균 평점, 투표 수약 25MB
title.crew.tsv.gz감독, 작가약 300MB
title.principals.tsv.gz주요 출연/제작진약 2GB
title.akas.tsv.gz지역별 대체 제목약 1.5GB
title.episode.tsv.gzTV 에피소드 정보약 200MB
name.basics.tsv.gz인물: 이름, 출생 연도, 대표작약 700MB

Pandas에 불러오는 것도 간단합니다.

1ratings = pd.read_csv("title.ratings.tsv.gz", sep="\t", compression="gzip")
2basics = pd.read_csv("title.basics.tsv.gz", sep="\t", compression="gzip", low_memory=False)
3# tconst(IMDb 타이틀 ID) 기준으로 병합
4merged = basics.merge(ratings, on="tconst")
5top_movies = merged[merged["titleType"] == "movie"].nlargest(250, "averageRating")

이 데이터셋은 2,600만 개 이상의 타이틀을 다룹니다. 페이지네이션도, 선택자도, 403 오류도 없습니다. 다만 라이선스는 개인 및 비상업적 사용에만 허용되므로, 데이터를 재배포하거나 재판매할 수는 없습니다.

노코드로 빠르게: Thunderbit가 페이지네이션까지 처리해 줍니다

페이지네이션이 있는 IMDb 데이터가 필요하지만 직접 페이지네이션 로직을 짜고 싶지 않은 분들을 위해, 는 클릭 기반 페이지네이션과 무한 스크롤을 모두 기본 지원합니다. 스크래핑하라고만 말하면 나머지는 Thunderbit이 처리해요. 지연 로딩 콘텐츠를 스크롤하는 것까지 포함해서요.

파이썬으로 IMDb 스크래핑하기: 완전한 작동 코드(복사해서 바로 실행 가능)

지금 바로 실행할 수 있는 독립형 스크립트 두 개를 소개합니다.

스크립트 A: BeautifulSoup 방식(CSS 선택자)

1import requests
2from bs4 import BeautifulSoup
3import pandas as pd
4> This paragraph contains content that cannot be parsed and has been skipped.
5response = requests.get(url, headers=headers)
6if response.status_code != 200:
7    print(f"오류: {response.status_code}")
8    exit()
9soup = BeautifulSoup(response.text, "lxml")
10movie_items = soup.select("li.ipc-metadata-list-summary-item")
11movies = []
12for item in movie_items:
13    try:
14        title = item.select_one("h3.ipc-title__text")
15        year = item.select_one("span.cli-title-metadata-item")
16        rating = item.select_one("span.ipc-rating-star--rating")
17> This paragraph contains content that cannot be parsed and has been skipped.
18df = pd.DataFrame(movies)
19df.to_csv("imdb_top250_bs4.csv", index=False)
20print(f"{len(df)}편의 영화를 저장했습니다")
21print(df.head())

스크립트 B: JSON-LD 방식(추천)

1import requests
2from bs4 import BeautifulSoup
3import json
4import pandas as pd
5> This paragraph contains content that cannot be parsed and has been skipped.
6response = requests.get(url, headers=headers)
7if response.status_code != 200:
8    print(f"오류: {response.status_code}")
9    exit()
10> This paragraph contains content that cannot be parsed and has been skipped.
11if not script_tag:
12    print("JSON-LD 데이터를 찾지 못했습니다")
13    exit()
14data = json.loads(script_tag.string)
15movies = []
16for item in data.get("itemListElement", []):
17    movie = item.get("item", {})
18    rating_info = movie.get("aggregateRating", {})
19    directors = movie.get("director", [])
20    director_names = ", ".join(
21        d.get("name", "") for d in (directors if isinstance(directors, list) else [directors])
22    )
23> This paragraph contains content that cannot be parsed and has been skipped.
24df = pd.DataFrame(movies)
25df.to_csv("imdb_top250_jsonld.csv", index=False)
26print(f"{len(df)}편의 영화를 저장했습니다")
27print(df.head())

두 스크립트 모두 오류 처리가 들어 있고, 깔끔한 CSV 출력을 만듭니다. 스크립트 B는 감독, 설명, URL까지 더 풍부한 데이터를 제공하며 레이아웃 변화에도 더 강합니다.

코딩 없이 IMDb를 스크래핑하는 방법(Thunderbit 사용)

모두가 파이썬을 쓰고 싶거나 쓸 필요가 있는 건 아니에요. 이번 주의 최고 평점 영화들을 스프레드시트로 바로 받고 싶은 운영 분석가일 수도 있고, 연도별 장르 추세를 비교하려는 콘텐츠 전략가일 수도 있죠. 그런 경우엔 스크래퍼를 직접 짜는 건 과한 일입니다.

로 같은 데이터를 얻는 방법은 이렇습니다.

시작 전에:

  • 난이도: 초급
  • 소요 시간: 약 2분
  • 준비물: Chrome 브라우저, (무료 플랜 사용 가능)

STEP 1: 스크래핑하려는 IMDb 페이지로 이동합니다. Chrome에서 IMDb Top 250(또는 다른 IMDb 목록/검색 페이지)을 엽니다.

STEP 2: Thunderbit 사이드바에서 "AI 필드 추천"을 클릭합니다. AI가 페이지를 스캔해 열을 추천해 줍니다. 보통 제목, 연도, 평점, 장르 등이 페이지에 따라 몇 가지 더 포함돼요. 추천된 필드가 들어간 미리보기 표가 표시됩니다.

STEP 3: 필요하면 필드를 조정합니다. 필요 없는 열은 지우고, "+ 열 추가"를 눌러 평이한 영어로 원하는 내용을 설명해 커스텀 열을 추가할 수 있어요(예: "감독 이름" 또는 "투표 수").

STEP 4: "스크래핑"을 클릭합니다. Thunderbit가 데이터를 추출합니다. 무한 스크롤이나 페이지네이션이 있는 페이지도 자동으로 스크롤을 처리해 줍니다.

STEP 5: 내보내기. 내보내기 버튼을 클릭하고 Excel, Google Sheets, CSV, Airtable, Notion 중 원하는 형식을 선택하세요. 데이터가 몇 초 안에 목적지에 들어갑니다.

여기서 핵심 장점은 편의성만이 아니에요. Thunderbit의 AI가 매번 페이지 구조를 새로 읽는다는 점입니다. IMDb가 레이아웃을 바꾸더라도 AI가 적응하죠. 업데이트할 선택자도, 고칠 코드도 없습니다. 마감 직전에 새벽 2시에 깨진 스크래퍼 때문에 당황해 본 사람이라면, 이건 정말 큰 가치예요.

Thunderbit는 서브페이지 스크래핑도 지원합니다. 각 영화 상세 페이지로 들어가 출연진, 감독, 상영 시간처럼 목록 페이지에는 보이지 않는 필드까지 표에 풍부하게 추가할 수 있어요. 실제 사용 모습을 보고 싶다면 을 확인해 보세요.

IMDb 스크래핑은 합법일까요? 알아야 할 것들

포럼에서 사용자는 이렇게 직접 묻곤 해요. "이런 식으로 하는 게 합법인가요? IMDb는 사람들이 자기 웹사이트를 스크래핑하는 걸 원하지 않잖아요." 좋은 질문이고, 경쟁 기사들은 이 부분을 다루지 않습니다.

IMDb의 robots.txt: Top 250 차트(/chart/top/), 개별 타이틀 페이지(/title/ttXXXXXXX/), 이름 페이지(/name/nmXXXXXXX/)는 robots.txt에서 차단되어 있지 않습니다. 차단된 경로에는 /find, /_json/*, /search/name-text, /user/ur*/ratings, 그리고 여러 AJAX 엔드포인트가 포함돼요. Crawl-delay 지시문은 따로 없습니다.

IMDb의 이용 약관: 관련 조항은 이렇게 말합니다. "귀하는 당사의 명시적인 서면 동의 없이 이 사이트에서 데이터 마이닝, 로봇, 화면 스크래핑 또는 유사한 데이터 수집 및 추출 도구를 사용할 수 없습니다." 또 다른 조항은 스크래핑한 데이터의 재판매나 상업적 사용을 금지합니다.

실무적으로 이게 뜻하는 바: 최근 2024년의 법원 판결들(Meta v. Bright Data, X Corp v. Bright Data)에서는, 약관에 동의한 적이 없는 사용자에게는 Terms of Service가 구속력이 없을 수도 있다고 판단했어요. 공개적으로 접근 가능한 데이터를 로그인 없이 스크래핑하는 경우, 약관의 집행 가능성은 여전히 논쟁적입니다. 다만 이 법적 영역은 계속 바뀌고 있습니다.

안전한 대안: IMDb의 은 개인 및 비상업적 사용이 명시적으로 허용됩니다. TMDb API는 무료 API 키로 비교적 자유롭게 사용할 수 있어요. 명확하게 안전한 길을 원한다면 둘 다 좋은 선택입니다.

실무 가이드: 스크래핑을 하더라도 요청 사이에 적절한 지연(time.sleep(3))을 두고, 올바른 헤더를 설정하며, robots.txt에서 차단된 경로는 건드리지 마세요. 상업적 프로젝트라면 법률 전문가와 상의하거나 공식 데이터셋/API를 사용하세요.

Thunderbit 블로그에서는 를 자세히 다뤘습니다.

결론: 파이썬으로 IMDb를 스크래핑하는 가장 적절한 방법을 고르세요

짧게 정리하면 이렇습니다.

  • BeautifulSoup + CSS 선택자: 기초를 배우기 좋습니다. 하지만 6~12개월마다 깨질 가능성을 예상하세요. 항상 오류 처리를 넣으세요.
  • JSON-LD 추출: 지속적인 파이썬 프로젝트라면 제가 추천하는 방식입니다. Schema.org 표준을 따르고, CSS 클래스보다 훨씬 덜 자주 바뀌며, JavaScript 렌더링 없이도 깔끔한 구조화 데이터를 얻을 수 있어요.
  • __NEXT_DATA__ JSON: 개별 타이틀 페이지에서 더 풍부한 데이터(상영 시간, 전체 출연진, 줄거리, 포스터 이미지 등)가 필요할 때 보조적으로 사용하세요.
  • IMDb 공식 데이터셋: 대규모 분석에 가장 적합합니다. 2,600만 개 이상의 타이틀, 일일 업데이트, 스크래핑 불필요. 개인/비상업적 사용만 가능합니다.
  • : 코딩을 원하지 않거나 유지보수 없이 빠르게 데이터를 얻고 싶은 사람에게 가장 좋은 선택입니다. AI가 레이아웃 변화에 적응하고, 페이지네이션을 처리하며, Excel/Sheets/Airtable/Notion으로 내보냅니다.

이 가이드를 북마크해 두세요. IMDb 구조가 또 바뀌면 제가 업데이트할게요. 그리고 코드를 아예 건너뛰고 싶다면 . IMDb 페이지에서 깔끔한 스프레드시트까지 얼마나 빨리 갈 수 있는지 확인해 보실 수 있을 거예요. 다른 사이트도 함께 다루고 있다면, 가이드에서 더 넓은 워크플로를 다룹니다.

IMDb와 그 밖의 사이트를 위한 AI 웹 스크래퍼 체험하기

자주 묻는 질문

IMDb를 스크래핑하는 건 합법인가요?

IMDb의 이용 약관은 동의 없는 스크래핑을 금지하지만, 최근 2024년 법원 판결 이후 공개적으로 접근 가능한 데이터에 대한 ToS의 집행 가능성은 법적으로 여전히 논쟁 중입니다. 가장 안전한 선택은 IMDb의 (개인/비상업적 사용)이나 TMDb API(무료 키)입니다. 스크래핑을 한다면 robots.txt를 지키고, 요청 사이에 적절한 지연을 두며, 차단된 경로는 피하세요. 상업적 사용이라면 법률 전문가와 상담하세요.

왜 내 IMDb 스크래퍼는 빈 결과를 반환하나요?

대부분의 경우 원인은 오래된 CSS 선택자예요. td.titleColumn이나 td.ratingColumn 같은 클래스는 2023년 6월 이후 더 이상 존재하지 않습니다. 해결책은 JSON-LD 추출(<script type="application/ld+json"> 태그 파싱)로 전환하거나, 현재의 ipc- 접두사 클래스에 맞게 선택자를 업데이트하는 것입니다. 또 올바른 User-Agent 헤더를 넣고 있는지도 확인하세요. 헤더가 없으면 403 오류가 나고, 이게 빈 결과처럼 보일 수 있습니다.

IMDb에서 25개보다 많은 결과를 어떻게 스크래핑하나요?

Top 250 페이지는 250개 영화를 한 번에 불러오므로 페이지네이션이 필요 없습니다. 검색 결과는 start= URL 파라미터를 50씩 증가시키며 페이지를 넘기세요. 예를 들면 start=1, start=51, start=101입니다. 차단을 피하려면 요청 사이에 time.sleep(3)을 넣으세요. 또는 의 IMDb 공식 데이터셋은 2,600만 개 이상의 타이틀을 포함하므로 페이지네이션이 아예 필요 없습니다.

__NEXT_DATA__는 무엇이고, 왜 IMDb 스크래핑에 써야 하나요?

__NEXT_DATA__는 IMDb의 React/Next.js 페이지 안에 있는 <script id="__NEXT_DATA__"> 태그에 포함된 JSON 객체입니다. 페이지를 렌더링하는 데 React가 사용하는 전체 구조화 데이터를 담고 있어요. 제목, 평점, 출연진, 장르, 상영 시간 등 화면 레이아웃이 아니라 실제 데이터 모델을 나타내므로, CSS 선택자보다 UI 재설계에 훨씬 강합니다. 가장 견고한 추출 방법을 원한다면 JSON-LD와 함께 사용하세요.

코딩 없이 IMDb를 스크래핑할 수 있나요?

네. 대표적인 방법은 두 가지입니다. (1) IMDb의 을 내려받기 — 2,600만 개 이상의 타이틀을 담은 7개의 TSV 파일, 일일 업데이트, 비상업적 사용 무료. (2) 사용 — IMDb 페이지를 읽고 추출 필드를 자동 추천한 뒤, 두 번의 클릭으로 Excel, Google Sheets, CSV로 내보냅니다. 코드도 없고, 유지할 선택자도 없습니다.

더 알아보기

목차

Thunderbit 사용해 보기

단 2번 클릭으로 리드와 기타 데이터를 추출하세요. AI로 구동됩니다.

Thunderbit 받기 무료입니다
AI로 데이터 추출하기
Google Sheets, Airtable, Notion으로 데이터를 쉽게 전송하세요
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week