PythonでIMDbをスクレイピングする方法:本当に動くコード

最終更新日 April 16, 2026

최근에 “scrape IMDb with Python”으로 검색해 본 사람이라면, 아마 바로 느꼈을 겁니다. 나오는 튜토리얼의 상당수가 이미 고장 나 있다는 걸요. 그냥 “조금 오래됐다” 수준이 아니라, “결과가 0개고 NoneType 에러가 잔뜩 뜨는” 상태로 아예 안 돌아갑니다.

저는 지난 몇 주 동안 GeeksforGeeks, Medium, freeCodeCamp, Kaggle 노트북까지, 찾을 수 있는 주요 IMDb 스크래핑 글을 하나씩 직접 검증해 봤습니다. IMDb 스크래핑용으로 태그된 대부분도 IMDb가 Top 250 페이지를 2023년 6월에 다시 설계한 뒤 사라진 CSS 셀렉터(td.titleColumn, td.ratingColumn 등)를 그대로 참조하고 있었습니다. 그 결과 포럼에는 “왜 빈 결과만 나오냐”는 개발자들로 넘쳐났고, “각 파서를 전부 고치는 것 말고는 할 수 있는 게 많지 않다”고 인정한 상태입니다. 이 가이드에서는 지금 바로 쓸 수 있는 Python 방식 2가지, 페이지네이션과 흔한 에러 대응, 애초에 Python이 최선이 아닌 경우, 그리고 스크래퍼를 금방 낡지 않게 만드는 사고방식까지 한 번에 정리해 드립니다.

PythonでIMDbをスクレイピングするとはどういうこと?

웹 스크래핑은 웹페이지에서 데이터를 자동으로 뽑아내는 작업입니다. 손으로 복사·붙여넣기 하는 대신, 그 일을 스크립트에 맡기는 거죠. “IMDb를 스크레이핑한다”는 건 Python으로 IMDb 웹페이지에서 영화 데이터(제목, 평점, 장르, 출연진, 러닝타임, 투표 수 등)를 구조화해서 가져오는 것을 뜻합니다.

Python에서 흔히 쓰는 기본 조합은 세 가지입니다. 웹페이지를 가져오는 requests, HTML을 읽고 필요한 데이터를 찾는 BeautifulSoup, 결과를 정리하고 내보내는 pandas입니다. JavaScript 렌더링이 필요한 페이지에서는 Selenium이나 Playwright를 쓰는 경우도 있지만, 뒤에서 보겠지만 더 빠른 방법도 있습니다.

중요한 점 하나가 있습니다. 이 가이드의 내용은 2025년 중반 시점의 IMDb 현재 페이지 구조를 기준으로 확인한 것입니다. IMDb는 보통 6~12개월마다 구조를 바꾸기 때문에, 만약 이 글을 2027년에 보고 있다면 일부 셀렉터는 달라져 있을 수 있습니다. 그럴 때 어떻게 대응할지도 함께 설명하겠습니다.

なぜPythonで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 스크래핑이 자신의 상황에 맞는지 먼저 확인해야 합니다.

선택지는 이렇게 많습니다.

방법적합한 용도장점단점
Python + BeautifulSoup학습, 맞춤 추출자유도가 높음, 유연함깨지기 쉬움, 셀렉터가 자주 망가짐
JSON-LD / __NEXT_DATA__ 추출안정성을 중시하는 개발자JS 콘텐츠 대응, 비교적 견고함JSON 구조를 이해해야 함
IMDb 공식 데이터셋대규모 분석, 학술 용도합법적, 완전함, 2,600만 건 이상, 매일 갱신TSV 형식, 리뷰/이미지는 포함되지 않음
Cinemagoer(IMDbPY) 라이브러리제목 단위의 프로그램 접근Python다운 API, 풍부한 항목미해결 이슈가 88개, 마지막 릴리스는 2023년 5월
TMDb API영화 메타데이터 + 이미지무료 API 키, JSON, 문서가 잘 정리됨데이터 출처가 IMDb가 아님(IMDb 평점도 아님)
Thunderbit (노코드)비개발자, 바로 Excel로 내보내고 싶은 사람2번 클릭으로 스크래핑, AI가 항목 제안, Excel/Sheets로 출력대량 수집은 크레딧 기반

몇 가지 덧붙이면, Cinemagoer는 2023년 5월 이후 PyPI 릴리스가 없고, IMDb가 2025년 6월에 재설계를 진행한 뒤 많은 파서가 깨졌습니다. 지금 기준으로는 운영용으로 추천하기 어렵습니다. TMDb는 훌륭하지만 IMDb가 아니라 자체 평점 체계를 사용합니다. 또 IMDb 공식 엔터프라이즈 API는 AWS Data Exchange를 통해 연간 이 들어가므로, 대부분의 사람에게는 현실적인 선택이 아닙니다.

코드를 쓰고 싶지 않은 사람이라면 가 꽤 편합니다. IMDb 페이지를 읽고, 추출 항목(제목, 평점, 연도, 장르 등)을 자동으로 제안한 뒤, Excel, Google Sheets, Airtable, Notion으로 2번 클릭만에 내보낼 수 있습니다. IMDb 레이아웃이 바뀌어도 AI가 따라가므로 셀렉터를 직접 관리할 필요가 없습니다. 이 부분은 뒤에서 더 자세히 보겠습니다.

이제 Python으로 직접 하고 싶은 분들을 위해, 실제로 돌아가는 방법 2가지를 소개하겠습니다.

方法1:BeautifulSoupでIMDbをスクレイピングする(従来型)

많은 튜토리얼에서 가장 먼저 소개하는 정석적인 방식입니다. 동작은 하지만, 솔직히 말하면 이번 글에서 소개하는 방법 중 가장 쉽게 깨집니다. IMDb의 CSS 클래스명은 자동 생성되며, 디자인이 바뀔 때마다 달라지기 때문입니다. 그래도 웹 스크래핑의 기본을 익히기에는 가장 좋습니다.

ステップ1:Pythonライブラリをインストールして読み込む

필요한 패키지는 4개입니다.

1pip install requests beautifulsoup4 pandas lxml

각 역할은 다음과 같습니다.

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

임포트는 이렇게 합니다.

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

ステップ2:IMDbへHTTPリクエストを送る

초보자들이 가장 자주 막히는 지점이 여기입니다. IMDb는 적절한 User-Agent 헤더가 없는 요청을 차단합니다. 그러면 403 Forbidden이 뜹니다. Python Requests의 기본 UA 문자열(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"Failed to fetch page: {response.status_code}")
9else:
10    print("Page fetched successfully")

Accept-Language 헤더도 중요합니다. 이게 없으면 IP 위치에 따라 다른 언어로 내용이 반환될 수 있습니다.

ステップ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월 재설계 이후 한동안 안정적이긴 했지만, 다음에도 그대로일 거라는 보장은 없습니다.

ステップ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        movies.append({
12            "title": title,
13            "year": year,
14            "rating": rating
15        })
16    except Exception as e:
17        print(f"Error parsing movie: {e}")
18        continue
19print(f"Extracted {len(movies)} movies")

ステップ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. The Shawshank Redemption  1994    9.3
31           2. The Godfather    1972    9.2
42     3. The Dark Knight        2008    9.0
53  4. The Godfather Part II     1974    9.0
64         5. 12 Angry Men       1957    9.0

이렇게 하면 동작은 합니다. 다만 언제든 깨질 수 있는 CSS 셀렉터에 의존하고 있다는 점이 솔직한 현실입니다. 그래서 제가 실제로 더 추천하는 방법으로 넘어가 보겠습니다.

方法2:JSON-LDを使う — HTML解析を丸ごと飛ばす

이건 경쟁 글들이 거의 언급하지 않는 방식인데, 제대로 운영할 거라면 저는 이 방법을 씁니다. IMDb는 각 페이지의 <script type="application/ld+json"> 태그 안에 형태의 구조화 데이터를 넣어 둡니다. 이 데이터는 Schema.org 표준을 따르고, Google의 리치 결과에도 사용됩니다. CSS 클래스명보다 훨씬 덜 흔들립니다.

실무용 스크래퍼로 알려진 Apify의 IMDb Scraper도 추출 우선순위를 “JSON-LD > NEXT_DATA > DOM”으로 두고 있습니다. 저도 이 순서를 추천합니다.

なぜJSON-LDのほうがCSSセレクターより信頼できるのか

방법JavaScript 렌더링 대응?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データを抽出する

ステップ1:ページを取得する

할 일은 같습니다. 적절한 User-Agent 헤더를 붙여 requests를 사용하면 됩니다.

1import requests
2from bs4 import BeautifulSoup
3import json
4import pandas as pd
5url = "https://www.imdb.com/chart/top/"
6headers = {
7    "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",
8    "Accept-Language": "en-US,en;q=0.9"
9}
10response = requests.get(url, headers=headers)
11soup = BeautifulSoup(response.text, "lxml")

ステップ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"JSON-LD 타입: {data.get('@type', 'unknown')}")

ステップ3:構造化データを解析する

Top 250 페이지의 JSON-LD에는 250편의 영화가 들어 있는 itemListElement 배열이 있습니다. 각 항목에는 순위, 이름, URL, aggregateRating, 공개일, 장르, 설명, 감독, 출연진 배열 등이 들어 있습니다.

1movies = []
2for item in data.get("itemListElement", []):
3    movie = item.get("item", {})
4    rating_info = movie.get("aggregateRating", {})
5    movies.append({
6        "rank": item.get("position"),
7        "title": movie.get("name"),
8        "url": movie.get("url"),
9        "rating": rating_info.get("ratingValue"),
10        "vote_count": rating_info.get("ratingCount"),
11        "date_published": movie.get("datePublished"),
12        "genre": ", ".join(movie.get("genre", [])),
13        "description": movie.get("description"),
14    })

ステップ4:CSVへ出力する

1df = pd.DataFrame(movies)
2df.to_csv("imdb_top_250_json_ld.csv", index=False)
3print(df.head())

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

1   rank                      title                                     url  rating  vote_count date_published              genre
20     1  The Shawshank Redemption  https://www.imdb.com/title/tt0111161/     9.3     2900000     1994-10-14     Drama
31     2            The Godfather   https://www.imdb.com/title/tt0068646/     9.2     2000000     1972-03-24     Crime, Drama
42     3          The Dark Knight   https://www.imdb.com/title/tt0468569/     9.0     2800000     2008-07-18     Action, Crime, Drama

250편 전부 가져올 수 있습니다. 깔끔하고 구조화되어 있고, CSS 셀렉터를 이것저것 만질 필요도 없습니다. 게다가 이 데이터는 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월이름 페이지 재설계기존 이름 페이지 스크래퍼
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로 렌더링되기 때문입니다.

대처법: 위의 방법 2처럼 JSON-LD 추출로 바꾸세요. 데이터가 처음 HTML 응답 안에 들어 있으므로 JavaScript가 필요 없습니다.

403 Forbidden

IMDb는 를 사용해 봇을 감지하고 차단합니다. 가장 흔한 원인은 User-Agent 헤더가 없거나 너무 부자연스러운 경우입니다. 이 문제는 오픈소스 프로젝트와 IMDb의 에서도 보고되었고, IMDb 직원도 문제를 인정한 바 있습니다.

대처법: 현실적인 브라우저 User-AgentAccept-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를 쓰는 게 가장 좋습니다.

どう直すか:短期と長期の考え方

  • 즉시 대응: 모든 셀렉터를 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

결과를 순서대로 훑는 Python 루프는 다음과 같습니다.

1import time
2all_movies = []
3for start in range(1, 1001, 50):  # Top 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"Failed at start={start}: {response.status_code}")
8        break
9    soup = BeautifulSoup(response.text, "lxml")
10    # 원하는 방식으로 영화 데이터를 추출
11    # ...
12    print(f"Scraped page starting at {start}")
13    time.sleep(3)  # 예의상 기다리기. IMDb는 짧은 시간에 약 50번 요청하면 차단하기 시작함

time.sleep(3)는 꽤 중요합니다. 커뮤니티 보고에 따르면 IMDb는 짧은 시간에 약 50회 요청이 들어가면 IP 차단을 시작할 수 있습니다. 2~5초 정도의 랜덤 지연을 넣는 습관이 좋습니다.

そもそもスクレイピングしない選択:IMDb公式バルクデータセット

정말 대규모 처리가 필요하다면, IMDb는 에서 매일 갱신되는 무료 TSV 파일 7개를 제공합니다.

파일내용크기
title.basics.tsv.gz제목, 타입, 장르, 러닝타임, 연도약 800 MB
title.ratings.tsv.gz평균 평점, 투표 수약 25 MB
title.crew.tsv.gz감독, 각본약 300 MB
title.principals.tsv.gz주요 출연진/스태프약 2 GB
title.akas.tsv.gz지역별 대체 제목약 1.5 GB
title.episode.tsv.gzTV 에피소드 정보약 200 MB
name.basics.tsv.gz인물 이름, 출생연도, 대표작약 700 MB

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 데이터가 필요하지만 로직은 쓰고 싶지 않다면, 이 편합니다. 클릭식 페이지 넘김은 물론 무한 스크롤도 기본 지원합니다. 지시만 하면 지연 로딩 콘텐츠 스크롤까지 알아서 처리합니다.

PythonでIMDbをスクレイピングする:コピペですぐ動く完全版コード

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

スクリプトA:BeautifulSoup方式(CSSセレクター)

1import requests
2from bs4 import BeautifulSoup
3import pandas as pd
4url = "https://www.imdb.com/chart/top/"
5headers = {
6    "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",
7    "Accept-Language": "en-US,en;q=0.9"
8}
9response = requests.get(url, headers=headers)
10if response.status_code != 200:
11    print(f"Error: {response.status_code}")
12    exit()
13soup = BeautifulSoup(response.text, "lxml")
14movie_items = soup.select("li.ipc-metadata-list-summary-item")
15movies = []
16for item in movie_items:
17    try:
18        title = item.select_one("h3.ipc-title__text")
19        year = item.select_one("span.cli-title-metadata-item")
20        rating = item.select_one("span.ipc-rating-star--rating")
21        movies.append({
22            "title": title.text.strip() if title else "N/A",
23            "year": year.text.strip() if year else "N/A",
24            "rating": rating.text.strip() if rating else "N/A",
25        })
26    except Exception as e:
27        print(f"Skipping movie due to error: {e}")
28df = pd.DataFrame(movies)
29df.to_csv("imdb_top250_bs4.csv", index=False)
30print(f"Saved {len(df)} movies")
31print(df.head())

スクリプトB:JSON-LD方式(推奨)

1import requests
2from bs4 import BeautifulSoup
3import json
4import pandas as pd
5url = "https://www.imdb.com/chart/top/"
6headers = {
7    "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",
8    "Accept-Language": "en-US,en;q=0.9"
9}
10response = requests.get(url, headers=headers)
11if response.status_code != 200:
12    print(f"Error: {response.status_code}")
13    exit()
14soup = BeautifulSoup(response.text, "lxml")
15script_tag = soup.find("script", {"type": "application/ld+json"})
16if not script_tag:
17    print("JSON-LD 데이터를 찾을 수 없습니다")
18    exit()
19data = json.loads(script_tag.string)
20movies = []
21for item in data.get("itemListElement", []):
22    movie = item.get("item", {})
23    rating_info = movie.get("aggregateRating", {})
24    directors = movie.get("director", [])
25    director_names = ", ".join(
26        d.get("name", "") for d in (directors if isinstance(directors, list) else [directors])
27    )
28    movies.append({
29        "rank": item.get("position"),
30        "title": movie.get("name"),
31        "url": movie.get("url"),
32        "rating": rating_info.get("ratingValue"),
33        "votes": rating_info.get("ratingCount"),
34        "year": movie.get("datePublished", "")[:4],
35        "genre": ", ".join(movie.get("genre", [])),
36        "director": director_names,
37        "description": movie.get("description"),
38    })
39df = pd.DataFrame(movies)
40df.to_csv("imdb_top250_jsonld.csv", index=False)
41print(f"Saved {len(df)} movies")
42print(df.head())

두 스크립트 모두 에러 처리가 들어 있고, 깔끔한 CSV를 출력합니다. 스크립트 B는 감독, 설명, URL처럼 더 풍부한 데이터를 얻을 수 있고, 레이아웃 변경에도 훨씬 강합니다.

コードを書かずにIMDbをスクレイピングする方法(Thunderbitを使う)

모든 사람이 Python을 쓰고 싶어 하는 건 아닙니다. 이번 주 고평점 영화를 스프레드시트에 모아두고 싶은 업무 분석가일 수도 있고, 장르의 연도별 변화를 비교하고 싶은 콘텐츠 전략 담당자일 수도 있습니다. 이런 경우에는 직접 스크래퍼를 만드는 게 과한 일입니다.

으로 같은 데이터를 가져오는 흐름은 이렇게 간단합니다.

시작하기 전에:

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

1단계: 스크래핑할 IMDb 페이지를 엽니다. IMDb Top 250이나 원하는 IMDb 목록/검색 페이지를 Chrome에서 열어 주세요.

2단계: Thunderbit 사이드바에서 “AI Suggest Fields”를 클릭합니다. AI가 페이지를 분석해서 보통 Title, Year, Rating, Genre 같은 열을 제안합니다. 제안 항목의 미리보기 표가 나타납니다.

3단계: 필요한 대로 항목을 조정합니다. 필요 없는 열은 지우고, + Add Column을 눌러 “Director name”이나 “Number of votes”처럼 원하는 내용을 자연스러운 영어로 지정해 커스텀 열을 추가할 수 있습니다.

4단계: “Scrape”를 클릭합니다. Thunderbit가 데이터를 추출합니다. 무한 스크롤이나 페이지네이션이 있는 페이지도 자동 처리합니다.

5단계: 내보냅니다. Export 버튼을 눌러 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)에서는, 이용 약관에 동의하지 않은 사용자에게는 ToS가 구속력을 가지지 않을 수 있다는 점이 드러났습니다. 공개 데이터를 로그인 없이 가져오는 경우, ToS의 집행 가능성은 법적으로 여지가 있습니다. 다만 이 분야는 여전히 변하고 있습니다.

안전한 대안: IMDb의 은 개인·비상업적 사용이 명확히 허용됩니다. TMDb API도 무료 API 키로 비교적 자유롭게 사용할 수 있습니다. 안전 쪽으로 확실히 가고 싶다면 두 방법 모두 좋은 선택입니다.

실무 조언: 스크래핑을 한다면, 속도를 절제하고(time.sleep(3)처럼 요청 사이에 대기), 적절한 헤더를 넣고, robots.txt에서 막힌 경로는 건드리지 마세요. 상업적 프로젝트라면 법률 전문가와 상의하거나 공식 데이터셋/API를 사용하는 게 좋습니다.

Thunderbit 블로그에서는 도 자세히 다루고 있습니다.

まとめ:PythonでIMDbをスクレイピングする最適な方法を選ぶ

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

  • BeautifulSoup + CSS 셀렉터: 기초 학습용으로 좋습니다. 6~12개월마다 깨질 수 있다는 전제로 쓰세요. 에러 처리는 꼭 넣어야 합니다.
  • JSON-LD 추출: 지속적인 Python 프로젝트라면 제가 가장 추천하는 방식입니다. Schema.org 표준을 따르고, CSS 클래스보다 덜 바뀌며, JavaScript 렌더링 없이 정돈된 구조화 데이터를 얻을 수 있습니다.
  • __NEXT_DATA__ JSON: 개별 제목 페이지에서 상영 시간, 전체 출연진, 줄거리, 포스터 이미지 등을 보완할 때 씁니다.
  • IMDb 공식 데이터셋: 대규모 분석에 가장 적합합니다. 2,600만 건 이상, 매일 갱신, 스크래핑 불필요. 단, 개인·비상업적 사용만 가능합니다.
  • : 코드를 쓰지 않고 빠르게 데이터를 얻고 싶은 사람에게 최적입니다. AI가 레이아웃 변경을 따라가고, 페이지네이션도 처리하며, Excel/Sheets/Airtable/Notion으로 내보낼 수 있습니다.

이 가이드는 북마크해 두는 게 좋습니다. IMDb 구조가 다음에 또 바뀌면 업데이트하겠습니다. 코드를 아예 생략하고 싶다면 . IMDb 페이지를 깔끔한 스프레드시트로 바꾸는 속도를 직접 체감할 수 있을 겁니다. 다른 사이트에서도 작업한다면 도 같이 보시면 좋습니다.

IMDb와 다른 사이트용 AI 웹 스크래퍼를 사용해 보기

よくある質問

IMDb 스크래핑은 합법인가요?

IMDb 이용 약관은 동의 없는 스크래핑을 금지합니다. 다만 공개 데이터에 대한 ToS의 구속력은 2024년의 최근 판결 이후 법적으로 논쟁의 여지가 있습니다. 가장 안전한 방법은 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로 2번 클릭만에 내보낼 수 있습니다. 코드도 필요 없고, 셀렉터 유지보수도 필요 없습니다.

더 알아보기

Ke
Ke
CTO @ Thunderbit. Ke is the person everyone pings when data gets messy. He's spent his career turning tedious, repetitive work into quiet little automations that just run. If you've ever wished a spreadsheet could fill itself in, Ke has probably already built the thing that does it.
目次

Thunderbitを試す

リードや各種データをたった2クリックで取得。AI搭載。

Thunderbitを入手 無料です
AIでデータを抽出
Google Sheets、Airtable、Notionへ簡単にデータを転送
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week