Si últimamente has buscado "scrape IMDb with Python", probablemente hayas notado algo: la mayoría de los tutoriales que encuentras están rotos. Y no rotos en plan "un poco desactualizados"; más bien rotos en plan "devuelven cero resultados y una pared de errores NoneType".
He pasado las últimas semanas probando todos los tutoriales importantes de scraping de IMDb que pude encontrar: GeeksforGeeks, Medium, freeCodeCamp, notebooks de Kaggle, lo que sea. De los etiquetados para scraping de IMDb, la gran mayoría usan selectores CSS (td.titleColumn, td.ratingColumn) que no existen desde junio de 2023, cuando IMDb rediseñó su página Top 250. ¿El resultado? Foros llenos de desarrolladores preguntando "¿por qué mi código devuelve vacío?" y mantenedores de bibliotecas populares como que "no hay mucho que podamos hacer, aparte de arreglar cada parser". Esta guía cubre dos métodos en Python que sí funcionan ahora mismo, cómo manejar la paginación y los errores comunes, cuándo Python ni siquiera es la herramienta adecuada y cómo preparar tu scraper para que no acabe en el cementerio.
¿Qué significa extraer IMDb con Python?
El web scraping es el proceso de extraer datos de páginas web de forma programática: en lugar de copiar y pegar manualmente, escribes un script que lo hace por ti. Cuando hablamos de "scrapear IMDb", nos referimos a extraer datos estructurados de películas (títulos, valoraciones, géneros, reparto, duración, número de votos) de las páginas de IMDb usando Python.
La pila típica de Python para esto incluye tres bibliotecas: requests (para obtener la página web), BeautifulSoup (para analizar el HTML y encontrar los datos) y pandas (para organizar y exportar los resultados). Algunos tutoriales también usan Selenium o Playwright para páginas que requieren renderizado con JavaScript, pero como verás, hay enfoques más rápidos.
Una advertencia importante: todo lo que aparece en esta guía está verificado contra la estructura actual de IMDb a mediados de 2025. IMDb cambia las cosas aproximadamente cada 6–12 meses, así que si estás leyendo esto en 2027, algunos selectores pueden haber cambiado. (También te explicaré cómo manejar eso.)
¿Por qué extraer IMDb con Python? Casos de uso reales
Antes de escribir una sola línea de código, ¿qué harías realmente con los datos de IMDb? La respuesta depende de quién seas.
El conjunto de datos de reseñas de IMDb es uno de los benchmarks de NLP más usados del mundo: el artículo fundacional de Maas et al. (2011) ha acumulado , y el conjunto de datos está integrado en TensorFlow, Keras y PyTorch. En Hugging Face, el dataset stanfordnlp/imdb recibe 213.321 descargas al mes y se ha usado para entrenar más de 1.500 modelos. Así que, si trabajas en machine learning, seguramente ya estés familiarizado con los datos de IMDb.
Pero los casos de uso van mucho más allá del ámbito académico:
| Caso de uso | Para quién es | Campos de datos necesarios |
|---|---|---|
| Motor de recomendación de películas | Científicos de datos, aficionados | Títulos, géneros, valoraciones, reparto |
| Estrategia de contenido para plataformas de streaming | Equipos de producto/contenido | Valoraciones, votos, año de estreno, géneros |
| Análisis de sentimiento / entrenamiento de NLP | Investigadores de ML, estudiantes | Reseñas, valoraciones |
| Análisis competitivo de contenido | Analistas de la industria del entretenimiento | Taquilla, fechas de estreno, tendencias de valoraciones |
| Investigación sobre turismo cinematográfico | Organismos de turismo, agencias de viajes | Localizaciones de rodaje, métricas de popularidad |
| Investigación académica | Investigadores universitarios | Cualquier metadato estructurado de películas |
Solo el mercado del turismo cinematográfico se valora en unos . Netflix gastó más de 17.000 millones de dólares en contenido en 2024, y estuvo impulsada por recomendaciones personalizadas. La idea es esta: los datos de IMDb alimentan decisiones reales en distintos sectores.
Tus opciones para obtener datos de IMDb (antes de escribir una línea de código)
Esta es la sección que la mayoría de los tutoriales omite por completo. Saltan directamente a pip install beautifulsoup4 sin preguntarse si el scraping con Python es realmente la mejor opción para tu caso.
Este es el panorama completo:
| Ruta | Ideal para | Ventajas | Desventajas |
|---|---|---|---|
| Python + BeautifulSoup | Aprendizaje, extracción personalizada | Control total, flexible | Selectores frágiles, se rompe a menudo |
Extracción de JSON-LD / __NEXT_DATA__ | Desarrolladores que buscan estabilidad | Maneja contenido JS, más resistente | Requiere entender la estructura JSON |
| IMDb Official Datasets | Análisis a gran escala, uso académico | Legal, completo, más de 26 millones de títulos, actualizaciones diarias | Formato TSV, sin reseñas/imágenes |
| Biblioteca Cinemagoer (IMDbPY) | Búsquedas programáticas por título | API con estilo Python, muchos campos | 88 issues abiertos, última versión en mayo de 2023 |
| API de TMDb | Metadatos de películas + imágenes | Clave API gratuita, JSON, bien documentada | Fuente distinta (no son valoraciones de IMDb) |
| Thunderbit (sin código) | Personas no técnicas, exportaciones rápidas | Scraping en 2 clics, la IA sugiere campos, exporta a Excel/Sheets | Basado en créditos para scrapes grandes |
Algunas notas sobre estas opciones. Cinemagoer no ha tenido una versión en PyPI desde mayo de 2023 y la mayoría de sus parsers se rompieron tras el rediseño de IMDb en junio de 2025; ahora mismo no lo recomendaría para producción. TMDb es excelente, pero usa su propio sistema de valoración, no el de IMDb. Y la API empresarial oficial de IMDb cuesta a través de AWS Data Exchange, así que no es una opción para la mayoría.
Para los lectores que no quieren escribir código en absoluto, lee la página de IMDb, sugiere automáticamente los campos de extracción (título, valoración, año, género) y exporta a Excel, Google Sheets, Airtable o Notion en dos clics. La IA se adapta cuando IMDb cambia su diseño, así que no hay selectores que mantener. Más sobre eso más adelante.
Ahora bien, para quienes sí quieren escribir Python, aquí van dos métodos que funcionan.
Método 1: extraer IMDb con Python usando BeautifulSoup (enfoque tradicional)
Este es el enfoque clásico que encontrarás en la mayoría de los tutoriales. Funciona, pero quiero ser claro: es el más frágil de los métodos que cubriré. Los nombres de clase CSS de IMDb se generan automáticamente y cambian con los rediseños. Dicho eso, es la mejor forma de aprender los fundamentos del web scraping.
Paso 1: instala e importa tus bibliotecas de Python
Necesitas cuatro paquetes:
1pip install requests beautifulsoup4 pandas lxml
Esto es lo que hace cada uno:
requests— envía solicitudes HTTP para obtener la página webbeautifulsoup4— analiza el HTML para que puedas buscar elementos concretospandas— organiza los datos extraídos en tablas y los exporta a CSV/Excellxml— un analizador HTML rápido (BeautifulSoup puede usarlo como backend)
Tu bloque de importación:
1import requests
2from bs4 import BeautifulSoup
3import pandas as pd
Paso 2: envía una solicitud HTTP a IMDb
Aquí es donde muchos principiantes se topan con su primer muro. IMDb bloquea solicitudes que no incluyen un encabezado User-Agent adecuado: obtendrás un error 403 Forbidden. La cadena de user-agent predeterminada de Requests de Python (python-requests/2.31.0) se detecta al instante.
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"No se pudo obtener la página: {response.status_code}")
9else:
10 print("Página obtenida correctamente")
El encabezado Accept-Language también importa: sin él, IMDb puede devolver contenido en otro idioma según la geolocalización de tu IP.
Paso 3: analiza el HTML con BeautifulSoup
Una vez que tengas el HTML, crea un objeto BeautifulSoup y empieza a buscar los elementos correctos. Abre la página Top 250 de IMDb en Chrome, haz clic derecho sobre el título de una película y selecciona "Inspect" para ver la estructura HTML subyacente.
1soup = BeautifulSoup(response.text, "lxml")
A mediados de 2025, la página Top 250 usa estos selectores:
- Contenedor de película:
li.ipc-metadata-list-summary-item - Título:
h3.ipc-title__text - Año:
span.cli-title-metadata-item(primerspan) - Valoración:
span.ipc-rating-star--rating
Aviso: esos nombres de clase con prefijo ipc- los genera el sistema de componentes de IMDb. Han sido estables desde el rediseño de junio de 2023, pero no hay garantía de que no cambien otra vez.
Paso 4: extrae los datos de la película (título, año, valoración)
Aquí es donde me diferencio de la mayoría de los tutoriales: incluyo gestión de errores con try/except. Ninguna de las guías de la competencia que revisé hace esto, y precisamente por eso su código falla en silencio cuando cambia un selector.
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 al analizar la película: {e}")
18 continue
19print(f"Se extrajeron {len(movies)} películas")
Paso 5: guarda en CSV o Excel con Pandas
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())
Salida de ejemplo:
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
Eso funciona. Pero está sostenido por selectores CSS que podrían romperse cualquier día, y eso nos lleva al enfoque que realmente recomiendo.
Método 2: el truco de JSON-LD — salta por completo el análisis del HTML
Esta es la técnica que no cubre ningún artículo de la competencia, y la que yo usaría en cualquier proyecto serio. IMDb incrusta datos estructurados como (notación de objetos de JavaScript para datos enlazados) en etiquetas <script type="application/ld+json"> en cada página. Estos datos siguen el estándar Schema.org, los usa Google para resultados enriquecidos y cambian mucho menos que los nombres de clase CSS.
Apify IMDb Scraper, una herramienta de nivel producción, usa este orden de prioridad de extracción: "JSON-LD > NEXT_DATA > DOM". Esa es también la jerarquía que yo recomendaría.
Por qué JSON-LD es más fiable que los selectores CSS
| Enfoque | ¿Maneja contenido JS? | ¿Resiste cambios de UI? | Velocidad | Complejidad |
|---|---|---|---|---|
| BeautifulSoup + selectores CSS | ❌ No | ⚠️ Frágil (cambian los nombres de clase) | Rápido | Baja |
| Extracción JSON-LD | ✅ Sí | ✅ Sigue el estándar Schema.org | Rápido | Baja-media |
Extracción JSON __NEXT_DATA__ | ✅ Sí | ✅ Bastante estable | Rápido | Baja-media |
| Selenium / Playwright | ✅ Sí | ⚠️ Frágil | Lento | Media-alta |
| Thunderbit (sin código, 2 clics) | ✅ Sí (la IA lee la página) | ✅ La IA se adapta automáticamente | Rápido | Ninguna |
Los nombres de clase como ipc-metadata-list-summary-item los genera automáticamente el sistema de componentes React de IMDb y cambian con cada rediseño. El esquema JSON-LD representa el modelo real de datos, no la capa de presentación. Es como la diferencia entre leer el índice de un libro o intentar identificar los capítulos por el tamaño de la fuente.

Paso a paso: extraer datos de IMDb desde JSON-LD
Paso 1: obtén la página
Igual que antes: usa requests con un encabezado User-Agent adecuado.
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")
Paso 2: encuentra la etiqueta <script> de JSON-LD
1script_tag = soup.find("script", {"type": "application/ld+json"})
2if not script_tag:
3 print("No se encontró JSON-LD en esta página")
4else:
5 data = json.loads(script_tag.string)
6 print(f"Se encontró JSON-LD con tipo: {data.get('@type', 'desconocido')}")
Paso 3: analiza los datos estructurados
En la página Top 250, el JSON-LD contiene una matriz itemListElement con las 250 películas. Cada entrada incluye posición, nombre, URL, aggregateRating, datePublished, género, descripción, director y matrices de actores.
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 })
Paso 4: exporta a CSV
1df = pd.DataFrame(movies)
2df.to_csv("imdb_top_250_json_ld.csv", index=False)
3print(df.head())
Salida de ejemplo:
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
Las 250 películas. Limpias, estructuradas, sin malabares con selectores CSS. Y como estos datos siguen el estándar Schema.org (del que depende Google para los resultados de búsqueda), es mucho menos probable que cambien que el diseño visual.
Extra: __NEXT_DATA__ para páginas de películas individuales
Para obtener datos más ricos de páginas de títulos individuales (duración, reparto completo, resumen de la trama, imágenes del póster), IMDb también incrusta un objeto JSON __NEXT_DATA__. Este es el dato que React usa para hidratar la página; no se puede eliminar sin romper el sitio.
1# En una página individual de película como /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"]
Usa JSON-LD para páginas de listas o rankings, y __NEXT_DATA__ para páginas individuales de títulos. Ese es el enfoque de nivel producción.
Por qué tu scraper de IMDb sigue rompiéndose (y cómo solucionarlo)
Este es el punto de dolor que más se repite en todos los foros de scraping de IMDb que revisé. La gente escribe: "Parte del código se rompió por cambios en la interfaz" y "¡No funciona en 2024!", y la respuesta suele ser silencio o un "prueba con Selenium".
La causa de fondo es la migración continua de IMDb hacia un frontend basado en React/Next.js. Esta es la cronología de los principales cambios que rompieron cosas:
| Fecha | Qué cambió | Qué se rompió |
|---|---|---|
| Nov. 2022 | Rediseño de las Name Pages | Los scrapers antiguos de páginas de nombres |
| Jun. 2023 | Rediseño de la página Top 250 | Todos los selectores td.titleColumn / td.ratingColumn |
| Abr. 2023 | Rediseño de las subpáginas de títulos | Scrapers de biografías, premios y noticias |
| Oct. 2023 | Rediseño de la búsqueda avanzada | Scrapers basados en búsquedas |
| Jun. 2025 | Rediseño de las páginas /reference | Biblioteca Cinemagoer (la mayoría de parsers) |
Eso supone aproximadamente un cambio importante que rompe cosas cada 6–12 meses. Si tu scraper depende de nombres de clase CSS, estás en una cinta de correr.
Errores comunes y cómo solucionarlos
Resultados vacíos / errores NoneType
El error más común. Verás AttributeError: 'NoneType' object has no attribute 'text'. Eso significa que BeautifulSoup no pudo encontrar el elemento que estabas buscando, normalmente porque cambió el nombre de la clase CSS o porque el contenido se renderiza con JavaScript.
Solución: cambia a la extracción JSON-LD (Método 2 más arriba). Los datos están en la respuesta HTML inicial; no hace falta JavaScript.
403 Forbidden
IMDb usa para detectar y bloquear bots. El desencadenante número uno es un encabezado User-Agent faltante o obviamente falso. Esto está documentado en proyectos de código abierto y en , donde un empleado de IMDb reconoció el problema.
Solución: incluye siempre una cadena User-Agent de navegador realista y el encabezado Accept-Language: en-US. Usa requests.Session() para la agrupación de conexiones.
Solo se devuelven 25 resultados
Las páginas de búsqueda de IMDb y las listas de "Más populares" usan carga diferida: al principio solo muestran unos 25 resultados y cargan más por AJAX a medida que haces scroll.
Solución: usa paginación con parámetros de URL (cubierta en la siguiente sección) o cambia a la página Top 250, que carga las 250 películas en una sola respuesta.
Los selectores dejan de funcionar de repente
Selectores antiguos que ya no funcionan: td.titleColumn, td.ratingColumn, .lister-item-header, .inline-block.ratings-imdb-rating. Si tu código usa alguno de estos, está roto.
Solución: prioriza atributos data-testid (como h1[data-testid="hero-title-block__title"]) en lugar de nombres de clase generados automáticamente. Mejor aún, usa JSON-LD.
Un marco de decisión: soluciones a corto frente a largo plazo
- Arreglo rápido: añade bloques
try/exceptalrededor de cada selector, valida los códigos de estado HTTP, registra los errores en lugar de hacer que el programa se cierre - Arreglo a medio plazo: cambia de selectores CSS a extracción JSON-LD (Método 2)
- Arreglo a largo plazo: usa los para análisis a gran escala, o una herramienta como que usa IA para volver a leer la estructura de la página cada vez; sin selectores que mantener, la IA se adapta automáticamente a los cambios de diseño
Más allá del muro de los 25 resultados: scraping de la paginación y grandes conjuntos de datos de IMDb
Todos los tutoriales de la competencia que revisé extraen exactamente una página. Nadie cubre la paginación. Pero si necesitas más que una sola lista, te toparás con límites muy rápido.
Páginas que no necesitan paginación
Buena noticia: la página Top 250 carga las 250 películas en una sola respuesta renderizada en el servidor. Tanto JSON-LD como __NEXT_DATA__ contienen el conjunto de datos completo. No hace falta paginación.
Cómo funciona la paginación de búsqueda de IMDb
Las páginas de búsqueda de IMDb usan un parámetro de URL start=, que incrementa de 50 en 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
Aquí tienes un bucle en Python que recorre los resultados por páginas:
1import time
2all_movies = []
3for start in range(1, 1001, 50): # Recorre el top 1000 por páginas
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"Falló en start={start}: {response.status_code}")
8 break
9 soup = BeautifulSoup(response.text, "lxml")
10 # Extrae las películas usando el método que prefieras
11 # ...
12 print(f"Página extraída a partir de {start}")
13 time.sleep(3) # Sé respetuoso: IMDb bloquea tras ~50 solicitudes rápidas
Ese time.sleep(3) importa. Los reportes de la comunidad sugieren que IMDb empieza a bloquear IPs después de unas 50 solicitudes rápidas. Un retraso aleatorio entre 2 y 5 segundos es una buena práctica.
Cuándo saltarse el scraping por completo: los datasets oficiales masivos de IMDb
Para necesidades realmente grandes, IMDb ofrece 7 archivos TSV gratuitos en , actualizados a diario:
| Archivo | Contenido | Tamaño |
|---|---|---|
| title.basics.tsv.gz | Títulos, tipos, géneros, duración, año | ~800 MB |
| title.ratings.tsv.gz | Valoración media, número de votos | ~25 MB |
| title.crew.tsv.gz | Directores, guionistas | ~300 MB |
| title.principals.tsv.gz | Reparto/equipo principal | ~2 GB |
| title.akas.tsv.gz | Títulos alternativos por región | ~1,5 GB |
| title.episode.tsv.gz | Información de episodios de TV | ~200 MB |
| name.basics.tsv.gz | Personas: nombre, año de nacimiento, títulos conocidos | ~700 MB |
Cargarlos en Pandas es sencillo:
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# Combina por tconst (ID de título de IMDb)
4merged = basics.merge(ratings, on="tconst")
5top_movies = merged[merged["titleType"] == "movie"].nlargest(250, "averageRating")
Estos datasets cubren más de 26 millones de títulos. Sin paginación, sin selectores, sin errores 403. La licencia es solo para uso personal y no comercial; no puedes republicar ni revender los datos.
El atajo sin código: Thunderbit se encarga de la paginación por ti
Para quienes necesitan datos de IMDb paginados pero no quieren escribir la lógica de paginación, admite de forma nativa tanto la paginación por clic como el scroll infinito. Tú le indicas que extraiga datos y él se encarga del resto, incluido el desplazamiento por contenido cargado de forma diferida.
Extraer IMDb con Python: código completo que funciona listo para copiar y pegar
Aquí tienes dos scripts autocontenidos que puedes ejecutar ahora mismo.
Script A: método con BeautifulSoup (selectores 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"Se omitió una película por un error: {e}")
28df = pd.DataFrame(movies)
29df.to_csv("imdb_top250_bs4.csv", index=False)
30print(f"Se guardaron {len(df)} películas")
31print(df.head())
Script B: método JSON-LD (recomendado)
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("No se encontraron datos 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"Se guardaron {len(df)} películas")
42print(df.head())
Ambos scripts incluyen gestión de errores y generan un CSV limpio. El Script B te da datos más ricos — director, descripción, URL — y es más resistente a cambios en el diseño.
Cómo extraer IMDb sin escribir código (usando Thunderbit)
No todo el mundo necesita o quiere escribir Python. Quizá seas analista de operaciones y solo necesites las películas mejor valoradas de esta semana en una hoja de cálculo. Quizá seas estratega de contenido y quieras comparar tendencias de géneros entre años. En esos casos, escribir un scraper es demasiado.
Así puedes obtener los mismos datos usando :
Antes de empezar:
- Dificultad: principiante
- Tiempo necesario: ~2 minutos
- Lo que necesitas: navegador Chrome, (el plan gratuito funciona)
Paso 1: navega a la página de IMDb que quieres extraer. Abre IMDb Top 250 (o cualquier otra página de lista/búsqueda de IMDb) en Chrome.
Paso 2: haz clic en "AI Suggest Fields" en la barra lateral de Thunderbit. La IA analiza la página y recomienda columnas, normalmente Título, Año, Valoración, Género y algunas más según la página. Verás una tabla de vista previa con los campos sugeridos.
Paso 3: ajusta los campos si hace falta. Elimina columnas que no necesites o añade otras personalizadas haciendo clic en "+ Add Column" y describiendo lo que quieres en lenguaje natural (por ejemplo, "Nombre del director" o "Número de votos").
Paso 4: haz clic en "Scrape". Thunderbit extrae los datos. En páginas con scroll infinito o paginación, se encarga del desplazamiento automáticamente.
Paso 5: exporta. Haz clic en el botón de exportación y elige el formato: Excel, Google Sheets, CSV, Airtable o Notion. Los datos llegan a tu destino en segundos.
La ventaja clave aquí no es solo la comodidad: es que la IA de Thunderbit lee la estructura de la página desde cero cada vez. Cuando IMDb cambia su diseño (y lo hará), la IA se adapta. Sin selectores que actualizar, sin código que arreglar. Para cualquiera que haya sufrido un scraper roto a las 2 de la madrugada antes de una fecha límite, eso vale mucho.
Thunderbit también admite scraping de subpáginas: puedes entrar en la página de detalle de cada película y enriquecer tu tabla con reparto, director, duración y otros campos que no aparecen en la lista. Si quieres verlo en acción, visita el .
¿Es legal extraer datos de IMDb? Lo que necesitas saber
Los usuarios preguntan esto explícitamente en los foros: "¿Es legal algo así?... IMDb no quiere que la gente scrapee su web". Es una pregunta justa, y ningún artículo de la competencia la aborda.
robots.txt de IMDb: la tabla Top 250 (/chart/top/), las páginas individuales de títulos (/title/ttXXXXXXX/) y las páginas de nombres (/name/nmXXXXXXX/) NO están bloqueadas por robots.txt. Las rutas bloqueadas incluyen /find, /_json/*, /search/name-text, /user/ur*/ratings y varios endpoints AJAX. No se especifica ninguna directiva Crawl-delay.
Condiciones de uso de IMDb: la cláusula relevante dice: "No puedes usar data mining, robots, screen scraping ni herramientas similares de recopilación y extracción de datos en este sitio, salvo con nuestro consentimiento expreso por escrito." Otra cláusula prohíbe la reventa o el uso comercial de los datos extraídos.
Qué significa esto en la práctica: recientes fallos judiciales de 2024 (Meta v. Bright Data, X Corp v. Bright Data) concluyeron que los Términos de Servicio pueden no vincular a usuarios que nunca los aceptaron; si estás extrayendo datos públicos sin iniciar sesión, la aplicabilidad de esos términos es debatible. Pero es un terreno legal en evolución.
Alternativas seguras: los están expresamente autorizados para uso personal y no comercial. La API de TMDb es permisiva con una clave gratuita. Ambas son opciones sólidas si quieres mantenerte claramente dentro de lo permitido.
Orientación práctica: si vas a extraer datos, usa un ritmo de rastreo respetuoso (time.sleep(3) entre solicitudes), configura los encabezados correctos y no accedas a rutas bloqueadas por robots.txt. Para proyectos comerciales, consulta a un profesional legal o usa los datasets/API oficiales.
Hemos tratado en profundidad en el blog de Thunderbit.
Conclusión: elige la forma correcta de extraer IMDb con Python
La versión corta:
- BeautifulSoup + selectores CSS: bueno para aprender los fundamentos. Espera que se rompa cada 6–12 meses. Incluye siempre gestión de errores.
- Extracción JSON-LD: el enfoque que recomendaría para cualquier proyecto Python en curso. Sigue el estándar Schema.org, cambia mucho menos que las clases CSS y te da datos estructurados limpios sin renderizado de JavaScript.
- JSON
__NEXT_DATA__: úsalo como complemento para obtener datos más ricos en páginas individuales de títulos (duración, reparto completo, trama, pósters). - IMDb Official Datasets: la mejor opción para análisis a gran escala. Más de 26 millones de títulos, actualizados a diario, sin necesidad de scraping. Solo para uso personal/no comercial.
- : la mejor opción para quienes no programan o para cualquiera que quiera datos rápido sin mantener código. La IA se adapta a los cambios de diseño, maneja la paginación y exporta a Excel/Sheets/Airtable/Notion.
Guarda esta guía en favoritos: la actualizaré cuando cambie de nuevo la estructura de IMDb. Y si quieres saltarte el código por completo, y comprueba lo rápido que puedes pasar de una página de IMDb a una hoja de cálculo limpia. Si también trabajas con otros sitios, nuestra guía sobre cubre el flujo de trabajo más amplio.
Preguntas frecuentes
¿Es legal extraer datos de IMDb?
Los Términos de Servicio de IMDb prohíben el scraping sin consentimiento, pero la aplicabilidad de esos términos sobre datos de acceso público es jurídicamente debatible tras recientes fallos judiciales de 2024. Las opciones más seguras son los (uso personal/no comercial) o la API de TMDb (clave gratuita). Si vas a extraer datos, respeta robots.txt, usa retrasos razonables entre solicitudes y evita las rutas bloqueadas. Para uso comercial, consulta a un profesional legal.
¿Por qué mi scraper de IMDb devuelve resultados vacíos?
Casi siempre, la causa son selectores CSS obsoletos: nombres de clase como td.titleColumn y td.ratingColumn no existen desde junio de 2023. La solución es cambiar a la extracción JSON-LD (analizar la etiqueta <script type="application/ld+json">) o actualizar los selectores a las clases actuales con prefijo ipc-. Comprueba también que estás enviando un encabezado User-Agent adecuado, porque su ausencia provoca un error 403 que puede parecer un resultado vacío.
¿Cómo extraigo más de 25 resultados de IMDb?
La página Top 250 carga las 250 películas en una sola respuesta; no hace falta paginación. Para los resultados de búsqueda, usa el parámetro de URL start= (aumentando de 50 en 50) para avanzar por las páginas. Por ejemplo: start=1, start=51, start=101. Añade time.sleep(3) entre solicitudes para evitar bloqueos. Como alternativa, los datasets oficiales de IMDb en contienen más de 26 millones de títulos y no requieren paginación.
Qué es __NEXT_DATA__ y por qué debería usarlo para extraer IMDb?
__NEXT_DATA__ es un objeto JSON incrustado en una etiqueta <script id="__NEXT_DATA__"> en las páginas React/Next.js de IMDb. Contiene todos los datos estructurados que React usa para renderizar la página: títulos, valoraciones, reparto, géneros, duración y más. Como representa el modelo de datos subyacente y no el diseño visual, es más resistente a los rediseños de la interfaz que los selectores CSS. Úsalo junto con JSON-LD para lograr el enfoque de extracción más robusto.
¿Puedo extraer IMDb sin programar?
Sí. Dos opciones principales: (1) descargar los : 7 archivos TSV que cubren más de 26 millones de títulos, actualizados a diario y gratuitos para uso no comercial. (2) usar , que lee la página de IMDb, sugiere automáticamente los campos de extracción y exporta a Excel, Google Sheets o CSV en dos clics: sin código y sin selectores que mantener.
Más información