Si últimamente has buscado "extraer IMDb con Python", probablemente te hayas dado cuenta de algo: la mayoría de los tutoriales que salen están rotos. No rotos en plan "un poco desactualizados"; más bien rotos en plan "devuelven cero resultados y una avalancha de errores NoneType".
Llevo las últimas semanas probando casi todos los tutoriales importantes que encontré sobre scraping de IMDb — GeeksforGeeks, Medium, freeCodeCamp, notebooks de Kaggle, lo que fuera. De los etiquetados para scraping de IMDb, la gran mayoría sigue usando selectores CSS (td.titleColumn, td.ratingColumn) que dejaron de existir 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 "No hay mucho que podamos hacer, aparte de arreglar cada parser". Esta guía cubre dos métodos en Python que sí funcionan hoy, cómo manejar la paginación y los errores más comunes, cuándo Python ni siquiera es la herramienta adecuada y cómo hacer tu scraper más resistente para que no acabe en el cementerio.
¿Qué significa extraer datos de 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 a mano, escribes un script que lo haga por ti. Cuando hablamos de "scrapear IMDb", nos referimos a obtener datos estructurados de películas (títulos, valoraciones, géneros, reparto, duración, número de votos) desde las páginas de IMDb usando Python.
El stack típico de Python para esto incluye tres bibliotecas: requests (para descargar la página), 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 JavaScript, pero como verás, hay alternativas más rápidas.
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 cosas aproximadamente cada 6 a 12 meses, así que si estás leyendo esto en 2027, puede que algunos selectores hayan cambiado. (También te explicaré cómo lidiar con eso.)
¿Por qué extraer IMDb con Python? Casos de uso reales
Antes de escribir una sola línea de código, ¿para qué usarías realmente 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 dataset viene 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 conoces bien los datos de IMDb.
Pero los casos de uso van mucho más allá de la academia:
| Caso de uso | Para quién es | Campos de datos necesarios |
|---|---|---|
| Motor de recomendaciones 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 de turismo cinematográfico | Organismos de turismo, empresas 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 está valorado en unos . Netflix gastó más de 17.000 millones de dólares en contenido en 2024, con impulsada por recomendaciones personalizadas. La idea es simple: los datos de IMDb influyen en decisiones reales en múltiples industrias.
Tus opciones para obtener datos de IMDb (antes de escribir código)
Esta es la parte que la mayoría de tutoriales se salta por completo. Van directos a pip install beautifulsoup4 sin plantearse si Python scraping es realmente la mejor opción para tu caso.
Este es el panorama completo:
| Camino | Ideal para | Ventajas | Desventajas |
|---|---|---|---|
| Python + BeautifulSoup | Aprender, 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 26M de títulos, actualización diaria | Formato TSV, sin reseñas/imágenes |
| Biblioteca Cinemagoer (IMDbPY) | Consultas por título programáticas | API en Python, campos ricos | 88 issues abiertos, última versión en mayo de 2023 |
| API de TMDb | Metadatos de películas + imágenes | Clave gratis, JSON, bien documentada | Otra fuente distinta (no valoraciones de IMDb) |
| Thunderbit (sin código) | Personas no técnicas, exportaciones rápidas | Scraping en 2 clics, IA sugiere campos, exporta a Excel/Sheets | Basado en créditos para scrapes grandes |
Unas cuantas 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 quienes no quieren escribir código, lee la página de IMDb, sugiere automáticamente los campos a extraer (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 el diseño, así que no hay selectores que mantener. Más adelante te cuento más.
Ahora bien, para quienes sí quieren programar en 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 tutoriales. Funciona, pero quiero ser claro: es el más frágil de los métodos que voy a 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
Qué hace cada uno:
requests— envía peticiones HTTP para obtener la páginabeautifulsoup4— analiza el HTML para poder 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 petición HTTP a IMDb
Aquí es donde muchos principiantes chocan por primera vez. IMDb bloquea las peticiones que no incluyen un encabezado User-Agent correcto: obtendrás un error 403 Forbidden. La cadena de user-agent por defecto de Python Requests (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 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 pulsa "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(primer span) - 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 vuelvan a cambiar.
Paso 4: extrae los datos de la película (título, año, valoración)
Aquí me diferencio de la mayoría de tutoriales: incluyo manejo de errores con try/except. Ninguna de las guías de la competencia que revisé hace esto, que es justo por lo que su código se rompe 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 procesar la película: {e}")
18 continue
19print(f"Extraídas {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
Funciona. Pero depende de selectores CSS que pueden romperse cualquier día, y eso nos lleva al enfoque que de verdad recomiendo.
Método 2: el truco del JSON-LD — sin analizar HTML tradicional
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 (JavaScript Object Notation for Linked Data) dentro de etiquetas <script type="application/ld+json"> en cada página. Estos datos siguen el estándar Schema.org, Google los usa para mostrar 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 para extraer datos: "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 visual. Es como la diferencia entre leer el índice de un libro o intentar identificar capítulos por el tamaño de la fuente.

Paso a paso: extraer datos de IMDb desde JSON-LD
Paso 1: obtener la página
Igual que antes: usa requests con un encabezado User-Agent correcto.
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: localizar 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"JSON-LD encontrado con tipo: {data.get('@type', 'desconocido')}")
Paso 3: analizar los datos estructurados
En la página Top 250, el JSON-LD contiene un array itemListElement con las 250 películas. Cada entrada incluye posición, nombre, URL, aggregateRating, datePublished, género, descripción, director y arrays 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: exportar 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. Limpio, estructurado y sin malabares con selectores CSS. Y como estos datos siguen el estándar Schema.org, del que Google depende para los resultados de búsqueda, es mucho menos probable que cambien que la capa visual.
Extra: __NEXT_DATA__ para páginas de película individuales
Para obtener datos más ricos de las páginas de cada título (duración, reparto completo, sinopsis, imágenes del póster), IMDb también incrusta un objeto JSON __NEXT_DATA__. Es el dato que React usa para hidratar la página; no puede eliminarse sin romper el sitio.
1# En una página individual 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 listado o ranking, 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 arreglarlo)
Este es el problema más reportado en todos los foros de scraping de IMDb que revisé. Los usuarios escriben: "Parte del código se rompió por cambios en la interfaz" y "¡No funciona en 2024!" — y la respuesta suele ser silencio o "prueba con Selenium".
La causa raíz es la migración continua de IMDb a un frontend basado en React/Next.js. Esta es la cronología de los grandes cambios que rompieron scrapers:
| Fecha | Qué cambió | Qué se rompió |
|---|---|---|---|
| Nov 2022 | Rediseño de las páginas de nombre | Scrapers antiguos de páginas de nombre |
| Jun 2023 | Rediseño de la página Top 250 | Todos los selectores td.titleColumn / td.ratingColumn |
| Abr 2023 | Rediseño de subpáginas de títulos | Scrapers de biografía, premios, noticias |
| Oct 2023 | Rediseño de búsqueda avanzada | Scrapers basados en búsqueda |
| Jun 2025 | Rediseño de páginas /reference | Biblioteca Cinemagoer (la mayoría de parsers) |
Eso equivale, más o menos, a un gran cambio incompatible cada 6 a 12 meses. Si tu scraper depende de nombres de clase CSS, estás corriendo en una cinta sin fin.
Errores comunes y cómo solucionarlos
Resultados vacíos / errores NoneType
Es el error más común. Verás AttributeError: 'NoneType' object has no attribute 'text'. Esto significa que BeautifulSoup no encontró el elemento que buscabas, normalmente porque cambió el nombre de la clase CSS o porque el contenido lo renderiza JavaScript.
Solución: cambia a la extracción JSON-LD (Método 2 arriba). Los datos están en la respuesta HTML inicial, sin necesidad de JavaScript.
403 Forbidden
IMDb usa para detectar y bloquear bots. El desencadenante número uno es un encabezado User-Agent ausente o obviamente falso. Esto está documentado en proyectos open source y en , donde un empleado de IMDb reconoció el problema.
Solución: incluye siempre una cadena realista de User-Agent de navegador y el encabezado Accept-Language: en-US. Usa requests.Session() para reutilizar conexiones.
Solo devuelve 25 resultados
Las páginas de búsqueda y las listas de "Más populares" usan carga diferida: inicialmente solo renderizan unos 25 resultados y cargan más mediante AJAX al hacer scroll.
Solución: usa la paginación por parámetro URL (que cubro 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 cualquiera de estos, está roto.
Solución: prioriza atributos data-testid (como h1[data-testid="hero-title-block__title"]) frente a nombres de clase autogenerados. Mejor aún, usa JSON-LD.
Marco de decisión: arreglos a corto vs. largo plazo
- Arreglo rápido: añade bloques
try/exceptalrededor de cada selector, valida los códigos de estado HTTP y registra errores en lugar de hacer que el script se caiga - 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 vuelve a leer la estructura de la página con IA cada vez — sin selectores que mantener, la IA se adapta automáticamente a los cambios de diseño
Más allá del muro de 25 resultados: scraping de paginación y grandes datasets de IMDb
Cada tutorial de la competencia que revisé extrae exactamente una página. Nadie cubre la paginación. Pero si necesitas más que una sola lista, te vas a topar 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 única respuesta renderizada en el servidor. Tanto JSON-LD como __NEXT_DATA__ contienen el conjunto completo de datos. No hace falta paginación.
Cómo funciona la paginación de búsqueda en 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 para recorrer los resultados:
1import time
2all_movies = []
3for start in range(1, 1001, 50): # Recorre el 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"Error en start={start}: {response.status_code}")
8 break
9 soup = BeautifulSoup(response.text, "lxml")
10 # Extrae las películas usando tu método preferido
11 # ...
12 print(f"Página extraída desde {start}")
13 time.sleep(3) # Sé prudente: 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 de 2 a 5 segundos es una buena práctica.
Cuándo saltarse el scraping por completo: los datasets oficiales 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# Unir 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 resuelve la paginación por ti
Para quienes necesitan datos de IMDb paginados pero no quieren escribir lógica de paginación, admite de forma nativa paginación por clic y scroll infinito. Tú le dices que extraiga; él se encarga del resto, incluido desplazarse por contenido con carga diferida.
Extraer IMDb con Python: código completo y funcional listo para copiar y pegar
Aquí tienes dos scripts autocontenidos que puedes ejecutar ahora mismo.
Script A: método 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 omite la película por error: {e}")
28df = pd.DataFrame(movies)
29df.to_csv("imdb_top250_bs4.csv", index=False)
30print(f"Guardadas {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"Guardadas {len(df)} películas")
42print(df.head())
Ambos scripts incluyen manejo 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 programar en Python. Tal vez seas analista de operaciones y solo necesites el top de películas de esta semana en una hoja de cálculo. Tal vez seas estratega de contenidos y quieras comparar tendencias de géneros entre años. En esos casos, escribir un scraper es demasiado.
Así puedes obtener los mismos datos con :
Antes de empezar:
- Dificultad: Principiante
- Tiempo necesario: ~2 minutos
- Lo que necesitas: navegador Chrome, (el plan gratis funciona)
Paso 1: abre la página de IMDb que quieras extraer. Abre el Top 250 de IMDb (o cualquier otra lista/página de búsqueda) 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 vista previa de tabla 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, lo gestiona 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 no es solo la comodidad: es que la IA de Thunderbit relee la estructura de la página cada vez. Cuando IMDb cambia el diseño —y lo hará—, la IA se adapta. Sin selectores que actualizar, sin código que reparar. Para cualquiera que haya sufrido un scraper roto a las 2 de la mañana antes de una entrega, eso vale muchísimo.
Thunderbit también admite scraping de subpáginas: puedes entrar en la ficha 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 IMDb? Lo que debes saber
Los usuarios lo preguntan explícitamente en los foros: "¿Algo así es legal?… 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 de títulos individuales (/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 datos extraídos.
Qué significa esto en la práctica: resoluciones judiciales recientes de 2024 (Meta v. Bright Data, X Corp v. Bright Data) concluyeron que los Términos de Servicio podrían no vincular a usuarios que nunca los aceptaron; si extraes datos públicos sin iniciar sesión, la exigibilidad de esos términos es discutible. Pero es un área 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.
Recomendación práctica: si decides scrapear, usa una velocidad de rastreo respetuosa (time.sleep(3) entre solicitudes), configura encabezados correctos y no accedas a rutas bloqueadas por robots.txt. Para proyectos comerciales, consulta con un profesional legal o usa los datasets/API oficiales.
Hemos cubierto las en detalle en el blog de Thunderbit.
Conclusión: elige la forma correcta de extraer IMDb con Python
La versión corta:
- BeautifulSoup + selectores CSS: útil para aprender los fundamentos. Espera que se rompa cada 6 a 12 meses. Incluye siempre manejo 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 renderizar JavaScript.
- JSON
__NEXT_DATA__: úsalo como complemento para obtener datos más ricos en páginas individuales de títulos (duración, reparto completo, sinopsis, imágenes del póster). - IMDb Official Datasets: la mejor opción para análisis a gran escala. Más de 26 millones de títulos, actualización diaria, 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 cambios de diseño, gestiona la paginación y exporta a Excel/Sheets/Airtable/Notion.
Guarda esta guía en favoritos: la actualizaré cuando cambie la estructura de IMDb otra vez. 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 general.
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 discutible tras resoluciones judiciales recientes de 2024. Las opciones más seguras son los (uso personal/no comercial) o la API de TMDb (clave gratis). Si decides scrapear, respeta robots.txt, usa pausas 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 desactualizados: clases como td.titleColumn y td.ratingColumn no existen desde junio de 2023. La solución es cambiar a la extracción JSON-LD (analizando la etiqueta <script type="application/ld+json">) o actualizar tus selectores a las clases actuales con prefijo ipc-. Comprueba también que estés enviando un encabezado User-Agent correcto, porque si falta puede provocar un error 403 que se manifiesta como resultados vacíos.
¿Cómo extraigo más de 25 resultados de IMDb?
La página Top 250 carga las 250 películas en una sola respuesta, así que no necesita paginación. Para resultados de búsqueda, usa el parámetro de URL start= (incrementando de 50 en 50) para recorrer las páginas. Por ejemplo: start=1, start=51, start=101. Añade un 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 sin necesidad de 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 rediseños de interfaz que los selectores CSS. Úsalo junto con JSON-LD para obtener 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 diariamente 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
