En mi , mis intereses se encuentran en el aprendizaje automático (ML) y la inteligencia artificial (IA), y el lenguaje que elegí dominar es Python. viaje de programación autodidacta Mis habilidades en Python son básicas, así que si estás aquí sin muchas habilidades en codificación, espero que esta guía te ayude a obtener más conocimiento y comprensión. El proyecto perfecto para principiantes Para obtener datos para proyectos de ML, IA o ciencia de datos, a menudo dependerá de bases de datos, API o conjuntos de datos CSV listos para usar. Pero, ¿qué sucede si no puede encontrar un conjunto de datos que desea usar y analizar? Ahí es donde entra en juego un web scraper. Trabajar en proyectos es crucial para solidificar el conocimiento que obtienes. Cuando comencé este proyecto, estaba un poco abrumado porque realmente no sabía nada. Cumplir con eso, encontrar respuestas a mis preguntas sobre Stack Overflow y muchas pruebas y errores me ayudaron a comprender realmente cómo funciona la programación: cómo funcionan las páginas web, cómo usar bucles y cómo crear funciones y mantener los datos limpios. Hace que la construcción de un raspador web sea el proyecto perfecto para principiantes para cualquiera que comience en Python. lo que cubriremos Esta guía lo guiará a través de la comprensión de las páginas web HTML, la creación de un web scraper con Python y la creación de un DataFrame con pandas. Cubrirá la calidad de los datos, la limpieza de datos y la conversión de tipos de datos, completamente paso a paso y con instrucciones, código y explicaciones sobre cómo funciona cada parte. ¡Espero que codifiques y disfrutes! Descargo de responsabilidad Los sitios web pueden restringir o prohibir el raspado de datos de su sitio web. Los usuarios pueden estar sujetos a ramificaciones legales dependiendo de dónde y cómo intente obtener información. Los sitios web generalmente describen esto en sus términos de uso y en su archivo robots.txt que se encuentra en su sitio, que generalmente se parece a esto: . Así que raspe de manera responsable y respete el archivo robots.txt. www.example.com/robots.txt ¿Qué es Web Scraping? consiste en recopilar datos disponibles en sitios web. Esto se puede hacer manualmente por un ser humano o mediante el uso de un bot. El web scraping Un es un programa que creas que te ayuda a extraer los datos que necesitas mucho más rápido de lo que pueden hacerlo la mano y los ojos de un ser humano. bot ¿Qué vamos a raspar? Es esencial identificar el objetivo de su raspado desde el principio. No queremos raspar ningún dato que en realidad no necesitemos. Para este proyecto, recopilaremos datos de , específicamente las 50 mejores películas de esta página. Aquí está la información que recopilaremos de cada lista de películas: las "1000 mejores" películas de IMDb El título El año en que fue lanzado cuanto dura la pelicula Clasificación de IMDb de la película El Metascore de la película cuantos votos obtuvo la pelicula Las ganancias brutas de la película en EE. UU. ¿Cómo funcionan los raspadores web? Los rastreadores web recopilan datos del sitio web de la misma manera que lo haría un ser humano: van a una página web del sitio web, obtienen los datos relevantes y pasan a la siguiente página web, solo que mucho más rápido. Cada sitio web tiene una estructura diferente. Estas son algunas cosas importantes a tener en cuenta al construir un raspador web: ¿Cuál es la estructura de la página web que contiene los datos que está buscando? ¿Cómo llegamos a esas páginas web? ¿Necesitará recopilar más datos de la página siguiente? la dirección URL Para comenzar, veamos la . URL de la página que queremos raspar Esto es lo que vemos en la URL: Notamos algunas cosas sobre la URL: actúa como un separador: indica el final de la ruta del recurso URL y el inicio de los parámetros ? especifica de qué tratará la página groups=top_1000 nos lleva a la página siguiente o anterior. La referencia es la página en la que estamos actualmente. y hay dos valores posibles: traducidos para y &ref_adv_prv adv_nxt adv_prv avanzar a la página siguiente avanzar a la página anterior. Cuando navegue de un lado a otro por las páginas, notará que solo cambian los parámetros. Tenga en cuenta esta estructura, ya que es útil conocerla mientras construimos el raspador. el html HTML significa lenguaje de y la mayoría de las páginas web se escriben con él. Esencialmente, HTML es en que dos computadoras se comunican entre sí a través de Internet, y los sitios web son que dicen. marcado de hipertexto, la forma lo Cuando accede a una URL, su computadora envía una solicitud al servidor que aloja el sitio. Cualquier tecnología puede estar ejecutándose en ese servidor (JavaScript, Ruby, Java, etc.) para procesar su solicitud. Eventualmente, el servidor devuelve una respuesta a su navegador; a menudo, esa respuesta tendrá la forma de una página HTML para que la muestre su navegador. HTML describe la estructura de una página web semánticamente y originalmente incluía pistas para la apariencia del documento. inspeccionar html Los usuarios de Chrome, Firefox y Safari pueden examinar la estructura HTML de cualquier página haciendo clic con el botón derecho del mouse y presionando la opción Inspeccionar. Aparecerá un menú en la parte inferior o en el lado derecho de su página con una larga lista de todas las etiquetas HTML que contienen la información que se muestra en la ventana de su navegador. Si estás en Safari (foto de arriba), querrás presionar el botón a la izquierda de la barra de búsqueda, que parece un objetivo. Si está en Chrome o Firefox, hay un pequeño cuadro con un ícono de flecha en la parte superior izquierda que usará para inspeccionar. Una vez que haya hecho clic, si mueve el cursor sobre cualquier elemento de la página, notará que se resaltará junto con las etiquetas HTML en el menú al que están asociadas, como se ve arriba. Saber cómo leer la estructura básica de la página HTML de una página es importante para que podamos recurrir a Python para ayudarnos a extraer el HTML de la página. Instrumentos Las herramientas que vamos a utilizar son: (opcional) es un entorno de programación de computadora simple e interactivo que se utiliza a través de su navegador web. Recomiendo usar esto solo para fines de código si aún no tiene un IDE. Si usa Repl, asegúrese de estar usando el entorno de Python. Reemplazo nos permitirán enviar solicitudes HTTP para obtener archivos HTML Las solicitudes nos ayudará a analizar los archivos HTML HermosaSopa nos ayudará a ensamblar los datos en un DataFrame para limpiarlos y analizarlos pandas agregará soporte para funciones matemáticas y herramientas para trabajar con matrices NumPy Ahora, vamos a codificar Puede seguir a continuación dentro de su entorno Repl o IDE, o puede ir directamente al . ¡Que te diviertas! código completo aquí Herramientas de importación Primero, importaremos las herramientas que necesitaremos para que podamos usarlas para ayudarnos a construir el raspador y obtener los datos que necesitamos. peliculas en ingles Es muy probable que cuando ejecutemos nuestro código para raspar algunas de estas películas, obtengamos los nombres de las películas traducidos al idioma principal del país en el que se originó la película. Usa este código para asegurarte de obtener títulos traducidos al inglés de todas las películas que raspamos: Solicitar contenido de la URL Obtener el contenido de la página que estamos viendo solicitando la URL: Desglose de las solicitudes de URL: es la variable que creamos y le asignamos la URL url es la variable que creamos para almacenar nuestra acción request.get results es el método que usamos para captar el contenido de la URL. requests.get(url, headers=headers) los parte le dice a nuestro raspador que nos traiga inglés, basado en nuestra línea de código anterior. headers Usando BeautifulSoup Haga que el contenido que capturamos sea fácil de leer usando BeautifulSoup: Rompiendo BeautifulSoup abajo: es la variable que creamos para asignar el método BeatifulSoup, que especifica un formato deseado de resultados utilizando el analizador HTML; esto permite que Python lea los componentes de la página en lugar de tratarlos como una cadena larga soup imprimirá lo que hemos agarrado en un formato de árbol más estructurado, lo que facilita la lectura print(soup.prettify()) Los resultados de la impresión se verán más ordenados, así: Inicialice su almacenamiento Cuando escribimos código para extraer nuestros datos, necesitamos un lugar para almacenar esos datos. Cree variables para cada tipo de datos que extraerá y asígnele una lista vacía, indicada por corchetes . Recuerde la lista de información que queríamos obtener de cada película anterior: [] Tu código ahora debería verse así. Tenga en cuenta que podemos eliminar nuestra función hasta que necesitemos usarla de nuevo. print Encuentre el contenedor div correcto Es hora de revisar el código HTML en nuestra página web. Vaya a la página web que estamos raspando, inspecciónela y desplace el cursor sobre una sola película en su totalidad, como se muestra a continuación: Necesitamos descubrir qué distingue a cada uno de estos de otros contenedores div que vemos. Notarás la lista de elementos a la derecha con un atributo que tiene dos valores: y . div class lister-item mode-advanced Si hace clic en cada uno de ellos, notará que resaltará cada contenedor de película a la izquierda de la página, como arriba. Si hacemos una búsqueda rápida dentro de inspeccionar (presionamos Ctrl+F y escribimos ), veremos 50 coincidencias que representan las 50 películas que se muestran en una sola página. Ahora sabemos que toda la información que buscamos se encuentra dentro de este etiqueta. lister-item mode-advanced div Encuentra todos divisiones lister-item mode-advanced Nuestro próximo paso es decirle a nuestro raspador que encuentre todos estos divs avanzados en modo lister-item: Rotura find_all abajo: es la variable que usaremos para almacenar todos los contenedores div con una clase de movie_div lister-item mode-advanced la El extrae todos los contenedores div que tienen un atributo de clase de modo de elemento de listado avanzado de lo que hemos almacenado en nuestra sopa de variables. find_all() método Prepárate para extraer cada elemento Si nos fijamos en la primera película de nuestra lista: ¡Nos faltan las ganancias brutas! Si miras la segunda película, la han incluido allí. Algo que siempre debe considerar al construir un web scraper es la idea de que no toda la información que busca estará disponible para que la recopile. En estos casos, debemos asegurarnos de que nuestro raspador web no deje de funcionar o se rompa cuando llegue a los datos faltantes y construir alrededor de la idea de que simplemente no sabemos si eso sucederá o no. Entrar en cada división lister-item mode-advanced Cuando tomamos cada uno de los elementos que necesitamos en un solo contenedor, necesitamos el raspador para pasar al siguiente contenedor y toma esos elementos de la película también. Y luego debe pasar al siguiente y así sucesivamente, 50 veces para cada página. Para que esto se ejecute, necesitaremos envolver nuestro raspador en un . lister-item mode-advanced div lister-item mode-advanced div bucle for Desglosando el bucle for: A círculo se utiliza para iterar sobre una secuencia. Nuestra secuencia es cada contenedor en el que almacenamos for lister-item mode-advanced div movie_div es el nombre de la variable que entra en cada div. Puedes nombrar esto como quieras ( , , , ), y no cambiará la función del ciclo. container x loop banana cheese Se puede leer así: Extraer el título de la película. Comenzando con el nombre de la película, ubiquemos su línea HTML correspondiente usando inspeccionar y haciendo clic en el título. Vemos que el nombre está contenido dentro de una etiqueta de anclaje, . Esta etiqueta está anidada dentro de una etiqueta de encabezado, . los la etiqueta está anidada dentro de un etiqueta. Este es el tercero de los Está anidado en el contenedor de la primera película. <a> <h3> <h3> <div> <div> div Desglosando los títulos: es la variable que usaremos para almacenar los datos del título que encontremos name es lo que usamos en nuestro bucle: se usa para iterar cada vez. container for y es una notación de atributo y le dice al raspador que acceda a cada una de esas etiquetas. h3 .a le dice al raspador que tome el texto anidado en la etiqueta text <a> le dice al raspador que tome lo que encontramos y almacenó en el nombre y lo agregue a nuestra lista vacía llamada títulos, que creamos al principio titles.append(name) Extraer año de lanzamiento Localicemos el año de la película y su línea HTML correspondiente usando inspeccionar y haciendo clic en el año. Vemos que estos datos se almacenan dentro del etiqueta debajo de la etiqueta que contiene el título de la película. La notación de puntos, que usamos para encontrar los datos del título ( ), funcionó porque fue el primero etiqueta después de la etiqueta. Desde el la etiqueta que queremos es la segunda etiqueta, tenemos que usar un método diferente. <span> <a> .h3.a <a> h3 <span> <span> En cambio, podemos decirle a nuestro raspador que busque por la marca distintiva del segundo . Usaremos el , que es similar a excepto que solo devuelve el primer partido. <span> find() método find_all() Desglosando los años: es la variable que usaremos para almacenar los datos del año que encontremos year es lo que usamos en nuestro bucle for: se usa para iterar cada vez. container es una notación de atributo, que le dice al raspador que acceda a esa etiqueta. h3 es un método que usaremos para acceder a este particular etiqueta find() <span> ( ) es el distintivo etiqueta que queremos 'span', class_ = 'lister-item-year' <span> le dice al raspador que tome lo que encontramos y almacenamos en el año y lo agregue a nuestra lista vacía llamada años (que creamos al principio) years.append(year) Extraer la duración de la película Ubique la duración de la película y su línea HTML correspondiente usando inspeccionar y haciendo clic en el total de minutos. Los datos que necesitamos se pueden encontrar en un etiqueta con una clase de tiempo de ejecución. Como hicimos con el año, podemos hacer algo similar: <span> Desglosando el tiempo: es la variable que usaremos para almacenar los datos de tiempo que encontremos runtime es lo que usamos en nuestro bucle for: se usa para iterar cada vez. container es un método que usaremos para acceder a este particular etiqueta find() <span> ( ) es el distintivo etiqueta que queremos 'span', class_ = 'runtime' <span> dice que si hay datos allí, agárralos, pero si faltan datos, entonces coloca un guión allí. if container.p.find('span', class_='runtime') else '-' le dice al raspador que tome ese texto en el etiqueta text <span> le dice al raspador que tome lo que encontramos y almacenó en tiempo de ejecución y lo agregue a nuestra lista vacía llamada tiempo (que creamos al principio) time.append(runtime) Extraer calificaciones de IMDb Encuentre la calificación de IMDb de la película y su línea HTML correspondiente usando inspeccionar y haciendo clic en la calificación de IMDb. Ahora, nos centraremos en extraer la calificación de IMDb. Los datos que necesitamos se pueden encontrar en un etiqueta. Como no veo ninguna otra etiquetas, podemos usar la notación de atributos (notación de puntos) para capturar estos datos. <strong> <strong> Desglosando las calificaciones de IMDb: es la variable que usaremos para almacenar los datos de calificaciones de IMDB que encuentre imdb es lo que usamos en nuestro bucle: se usa para iterar cada vez. container for es una notación de atributo que le dice al raspador que acceda a esa etiqueta. strong le dice al raspador que tome ese texto text los el texto que encontramos en un flotante, que es un decimal float() convierte le dice al raspador que tome lo que encontramos y almacenamos en y para agregarlo a nuestra lista vacía llamada (que creamos al principio). imdb_ratings.append(imdb) imdb imdb_ratings Extraer metapuntuación Encuentre la calificación Metascore de la película y su línea HTML correspondiente usando inspeccionar y haciendo clic en el número Metascore. Los datos que necesitamos se pueden encontrar en un etiqueta que tiene una clase que dice . <span> metascore favorable Antes de decidirnos por eso, debes notar que, por supuesto, un 96 para “Parasite” muestra una calificación favorable, pero ¿los demás son favorables? Si resalta el Metascore de la próxima película, verá que "JoJo Rabbit" tiene una clase que dice . Dado que estas etiquetas son diferentes, sería seguro decirle al raspador que use solo la clase al raspar: metascore mixed metascore Desglosando Metascores: es la variable que usaremos para almacenar los datos de clasificación Metascore que encuentra m_score es lo que usamos en nuestro bucle: se usa para iterar cada vez. container for es un método que usaremos para acceder a este particular etiqueta find() <span> ( ) es el distintivo etiqueta que queremos. 'span', class_ = 'metascore' <span> le dice al raspador que tome ese texto text dice que si hay datos allí, agárralos, pero si faltan, entonces coloca un guión allí if container.find('span', class_='metascore') else '-' los convierte el texto que encontramos en un número entero int() método le dice al raspador que tome lo que encontramos y almacenamos en y para agregarlo a nuestra lista vacía llamada (que creamos al principio) metascores.append(m_score) m_score metascores Extraer votos y ganancias brutas Finalmente llegamos a los dos elementos finales que necesitamos extraer, pero dejamos lo más difícil para el final. Aquí es donde las cosas se ponen un poco complicadas. Como se mencionó anteriormente, debería haber notado que cuando miramos la primera película en esta lista, no vemos un número de ganancias brutas. Cuando miramos la segunda película de la lista, podemos ver ambas. Echemos un vistazo al código HTML de la segunda película y partamos de ahí. Tanto los votos como el bruto se destacan a la derecha. Después de ver los votos y los contenedores brutos de la película n.° 2, ¿qué notas? Como puede ver, ambos están en una etiqueta que tiene un atributo que equivale y un atributo que contiene los valores del número distintivo que necesitamos para cada uno. <span> name nv data-value ¿Cómo podemos obtener los datos del segundo si los parámetros de búsqueda del primero son los mismos? ¿Cómo le decimos a nuestro raspador que se salte el primero y raspe el segundo? Esto requirió mucha flexión del cerebro, toneladas de café y un par de noches para descubrirlo. Así es como lo hice: Desglose de votos y bruto: es una variable completamente nueva que usaremos para mantener tanto los votos como el bruto etiquetas nv <span> es lo que usamos en nuestro bucle para iterar cada vez container for es el método que usaremos para capturar ambos etiquetas find_all() <span> ( ) es cómo podemos obtener atributos de esa etiqueta específica. 'span', attrs = 'name' : 'nv' es la variable que usaremos para almacenar los votos que encontremos en el etiqueta vote nv le dice al raspador que entre en el etiquete y tome los primeros datos en la lista, que son los votos porque los votos son lo primero en nuestro código HTML (las computadoras cuentan en binario, comienzan a contar en 0, no en 1). nv[0] nv le dice al raspador que tome ese texto text le dice al raspador que tome lo que encontramos y almacenamos en y para agregarlo a nuestra lista vacía llamada (que creamos al principio) votes.append(vote) vote votes es la variable que usaremos para almacenar el bruto que encontramos en el etiqueta grosses nv le dice al raspador que entre en el etiquete y obtenga los segundos datos de la lista, lo cual es bruto porque el bruto ocupa el segundo lugar en nuestro código HTML nv[1] nv dice si la longitud de es mayor que uno, luego encuentre el segundo dato que está almacenado. Pero si los datos que están almacenados en no es mayor que uno, es decir, si falta el bruto, entonces coloque un guión allí. nv[1].text if len(nv) > 1 else '-' nv nv le dice al raspador que tome lo que encontramos y almacenamos en y para agregarlo a nuestra lista vacía llamada (que creamos al principio) us_gross.append(grosses) grosses us_grosses Su código ahora debería verse así: Veamos lo que tenemos hasta ahora Ahora que le hemos dicho a nuestro raspador qué elementos raspar, usemos la función de impresión para imprimir cada lista a la que enviamos nuestros datos raspados: Nuestras listas se ven así ['Parasite', 'Jojo Rabbit', ' ', 'Knives Out', 'Uncut Gems', 'Once Upon a Time... in Hollywood', 'Joker', 'The Gentlemen', 'Ford v Ferrari', 'Little Women', 'The Irishman', 'The Lighthouse', 'Toy Story ', 'Marriage Story', 'Avengers: Endgame', 'The Godfather', 'Blade Runner ', 'The Shawshank Redemption', 'The Dark Knight', 'Inglourious Basterds', 'Call Me by Your Name', 'The Two Popes', 'Pulp Fiction', 'Inception', 'Interstellar', 'Green Book', 'Blade Runner', 'The Wolf of Wall Street', 'Gone Girl', 'The Shining', 'The Matrix', 'Titanic', 'The Silence of the Lambs', 'Three Billboards Outside Ebbing, Missouri', , 'The Peanut Butter Falcon', 'The Handmaiden', 'Memories of Murder', 'The Lord of the Rings: The Fellowship of the Ring', 'Gladiator', 'The Martian', 'Bohemian Rhapsody', 'Watchmen', 'Forrest Gump', 'Thor: Ragnarok', 'Casino Royale', 'The Breakfast Club', 'The Godfather: Part II', 'Django Unchained', 'Baby Driver'] ['( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '(I) ( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )', '( )'] [' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min', ' min'] [ , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ] [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '] [' , ', ' , ', ' , ', ' , ', ' , ', ' , ', ' , ', ' , ', ' , ', ' , ', ' , ', ' , ', ' , ', ' , ', ' , ', ' , , ', ' , ', ' , , ', ' , , ', ' , , ', ' , ', ' , ', ' , , ', ' , , ', ' , , ', ' , ', ' , ', ' , , ', ' , ', ' , ', ' , , ', ' , ', ' , , ', ' , ', ' , ', ' , ', ' , ', ' , ', ' , , ', ' , , ', ' , ', ' , ', ' , ', ' , , ', ' , ', ' , ', ' , ', ' , , ', ' , , ', ' , '] ['-', '$ M', '-', '-', '-', '$ M', '$ M', '-', '-', '-', '-', '$ M', '$ M', '-', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '-', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M', '$ M'] 1917 4 2049 "Harry Potter and the Sorcerer's Stone" 2019 2019 2019 2019 2019 2019 2019 2019 2019 2019 2019 2019 2019 2019 2019 1972 2017 1994 2008 2009 2017 2019 1994 2010 2014 2018 1982 2013 2014 1980 1999 1997 1991 2017 2001 2019 2016 2003 2001 2000 2015 2018 2009 1994 2017 2006 1985 1974 2012 2017 132 108 119 131 135 161 122 113 152 135 209 109 100 137 181 175 164 142 152 153 132 125 154 148 169 130 117 180 149 146 136 194 118 115 152 97 145 132 178 155 144 134 162 142 130 144 97 202 165 113 8.6 8.0 8.5 8.0 7.6 7.7 8.6 8.1 8.2 8.0 8.0 7.7 7.8 8.0 8.5 9.2 8.0 9.3 9.0 8.3 7.9 7.6 8.9 8.8 8.6 8.2 8.1 8.2 8.1 8.4 8.7 7.8 8.6 8.2 7.6 7.7 8.1 8.1 8.8 8.5 8.0 8.0 7.6 8.8 7.9 8.0 7.9 9.0 8.4 7.6 96 58 78 82 90 83 59 51 81 91 94 83 84 93 78 100 81 80 84 69 93 75 94 74 74 69 84 75 79 66 73 75 85 88 64 70 84 82 92 67 80 49 56 82 74 80 62 90 81 86 282 699 142 517 199 638 195 728 108 330 396 071 695 224 42 015 152 661 65 234 249 950 77 453 160 180 179 887 673 115 1 511 929 414 992 2 194 397 2 176 865 1 184 882 178 688 76 291 1 724 518 1 925 684 1 378 968 293 695 656 442 1 092 063 799 696 835 496 1 580 250 994 453 1 191 182 383 958 595 613 34 091 92 492 115 125 1 572 354 1 267 310 715 623 410 199 479 811 1 693 344 535 065 555 756 330 308 1 059 089 1 271 569 398 553 0.35 135.37 192.73 0.43 433.03 858.37 134.97 92.05 28.34 534.86 120.54 18.10 107.93 292.58 188.02 85.08 32.87 116.90 167.77 44.02 171.48 659.33 130.74 54.51 317.58 13.12 2.01 0.01 315.54 187.71 228.43 216.43 107.51 330.25 315.06 167.45 45.88 57.30 162.81 107.83 Hasta aquí todo bien, pero aún no hemos llegado a ese punto. Necesitamos limpiar un poco nuestros datos. Parece que tenemos algunos elementos no deseados en nuestros datos: signos de dólar, Ms, mins, comas, paréntesis y espacios en blanco adicionales en Metascores. Construyendo un marco de datos con pandas El siguiente orden del día es construir un DataFrame con pandas para almacenar los datos que tenemos muy bien en una tabla para entender realmente lo que está pasando. Así es como lo hacemos: Desglosando nuestro marco de datos: es lo que llamaremos nuestro DataFrame movies es como inicializamos la creación de un DataFrame con pandas pd.DataFrame Las teclas de la izquierda son los nombres de las columnas. Los valores a la derecha son nuestras listas de datos que hemos recopilado Ver nuestro marco de datos Podemos ver cómo se ve todo simplemente usando la función de impresión en nuestro DataFrame, al que llamamos películas, en la parte inferior de nuestro programa: Nuestro marco de datos de pandas se ve así Calidad de datos Antes de embarcarse en proyectos como este, debe saber cuáles son sus criterios de calidad de datos, es decir, qué reglas o restricciones deben seguir sus datos. Aquí hay unos ejemplos: los valores en sus columnas deben ser de un tipo de datos particular: numérico, booleano, fecha, etc. Restricciones de tipo de datos: : Ciertas columnas no pueden estar vacías Restricciones obligatorias campos de texto que deben tener un patrón determinado, como números de teléfono Patrones de expresiones regulares: ¿Qué es la limpieza de datos? es el proceso de detectar y corregir o eliminar registros corruptos o inexactos de su conjunto de datos. La limpieza de datos Al realizar análisis de datos, también es importante asegurarse de que estamos utilizando los tipos de datos correctos. Comprobación de tipos de datos Podemos verificar cómo se ven nuestros tipos de datos ejecutando esta función de impresión en la parte inferior de nuestro programa: Nuestros resultados de tipos de datos Analicemos esto: Nuestro tipo de datos de películas es un objeto, que es lo mismo que una cadena, lo cual sería correcto considerando que son títulos de películas. Nuestro puntaje de IMDb también es correcto porque tenemos números de coma flotante en esta columna (números decimales). Pero nuestro , , , y muestran que son objetos cuando deberían ser tipos de datos enteros, y nuestro es un objeto en lugar de un tipo de datos. ¿Cómo pasó esto? year timeMin metascore votes us_grossMillions float Inicialmente, cuando le decíamos a nuestro raspador que tomara estos valores de cada contenedor HTML, le decíamos que tomara valores específicos de una cadena. Una cadena representa texto en lugar de números: se compone de un conjunto de caracteres que pueden contener números. también Por ejemplo, la palabra y el son ambas cadenas. Si tuviéramos que deshacernos de todo excepto del desde el cadena, sigue siendo una cadena, pero ahora es una que solo dice . cheese phrase I ate 10 blocks of cheese 10 I ate 10 blocks of cheese 10 Limpieza de datos con pandas Ahora que tenemos una idea clara de cómo se ven nuestros datos en este momento, es hora de comenzar a limpiarlos. Esta puede ser una tarea tediosa, pero es muy importante. Datos del año de limpieza Para eliminar los paréntesis de los datos de nuestro año y convertir el objeto en un tipo de datos entero, haremos lo siguiente: Desglose de los datos del año de limpieza: le dice a los pandas que vayan a la columna año en nuestro movies['year'] DataFrame este método: dice que extraiga todos los dígitos en la cadena .str.extract('(\d+') ('(\d+') los convierte el resultado a un número entero .astype(int) método Ahora, si corremos en la parte inferior de nuestro programa para ver cómo se ven los datos de nuestro año, este es el resultado: print(movies['year']) Debería ver su lista de años sin paréntesis. Y el tipo de datos que se muestra ahora es un número entero. Los datos de nuestro año se limpian oficialmente. Datos de tiempo de limpieza Haremos exactamente lo que hicimos limpiando los datos de nuestro año anterior a nuestros datos de tiempo tomando solo los dígitos y convirtiendo nuestro tipo de datos a un número entero. Limpieza de datos Metascore La única limpieza que necesitamos hacer aquí es convertir nuestro tipo de datos de objeto en un número entero: Votos de limpieza Con los votos, debemos eliminar las comas y convertirlo en un tipo de datos entero: Desglosando los votos de limpieza: son nuestros datos de votos en nuestras películas . Estamos asignando nuestros nuevos datos limpios a nuestros votos. . movies['votes'] DataFrame DataFrame agarra la cuerda y usa el para reemplazar las comas con una comilla vacía (nada) .str.replace(' , ' , '') replace método los convierte el resultado en un número entero .astype(int) método Limpieza de datos brutos Los datos brutos implican algunos obstáculos para saltar. Lo que debemos hacer es eliminar el signo de dólar y la M de los datos y convertirlos en un número de coma flotante. Aquí está cómo hacerlo: Desglosando la limpieza bruta: Código de limpieza superior: son nuestros datos brutos en nuestras películas . Asignaremos nuestros nuevos datos limpios a nuestro columna. movies['us_grossMillions'] DataFrame us_grossMillions le dice a los pandas que vayan al en nuestro movies['us_grossMillions'] column us_grossMillions DataFrame los llama a la función especificada para cada elemento de un iterable .map() función es una función anónima en Python (una sin nombre). Las funciones normales se definen usando el palabra clave. lambda x: x def son los argumentos de nuestra función. Esto le dice a nuestra función que elimine el desde el lado izquierdo y pelar el desde el lado derecho. lstrip('$').rstrip('M') $ M Código de conversión inferior: está despojado de los elementos que no necesitamos, y ahora le asignaremos los datos del código de conversión para terminarlo movies['us_grossMillions'] es un que podemos usar para cambiar esta columna a un flotante. La razón por la que usamos esto es porque tenemos muchos guiones en esta columna y no podemos simplemente convertirlo en un flotante usando .astype(float) — esto detectaría un error. pd.to_numeric método transformará los valores no numéricos, nuestros guiones, en NaN (no-un-número) valores porque tenemos guiones en lugar de los datos que faltan errors='coerce' Revise el código limpio y convertido Veamos cómo lo hicimos. Ejecute la función de impresión para ver nuestros datos y los tipos de datos que tenemos: El resultado de nuestros datos limpios El resultado de nuestros tipos de datos ¡Se ve bien! Código final terminado Aquí está el código final de su raspador web de una sola página: Guardar sus datos en un CSV ¿Cuál es el uso de nuestros datos raspados si no podemos guardarlos para ningún proyecto o análisis futuro? A continuación se muestra el código que puede agregar al final de su programa para guardar sus datos en un archivo CSV: Desglosando el archivo CSV: movies.to_csv('movies.csv') Para que este código se ejecute correctamente, deberá crear un archivo vacío y nombrarlo como desee, asegurándose de que tenga el extensión. nombré a la mía , como puede ver arriba, pero siéntase libre de nombrarlo como quiera. Solo asegúrese de cambiar el código anterior para que coincida. .csv movies.csv Si está en Repl, puede crear un archivo CSV vacío pasando el mouse cerca de Archivos y haciendo clic en la opción "Agregar archivo". Nómbrelo y guárdelo con un extensión. Luego, agregue el código al final de su programa: .csv movies.to_csv('the_name_of_your_csv_here.csv') Todos sus datos deben completarse en su CSV. Una vez que lo descargue en su computadora/lo abra, su archivo se verá así: Conclusión Hemos recorrido un largo camino desde solicitar el contenido HTML de nuestra página web hasta limpiar todo nuestro DataFrame. Ahora debería saber cómo raspar páginas web con la misma estructura HTML y URL que le mostré anteriormente. Este es un resumen de lo que hemos logrado: Próximos pasos ¡Espero que te hayas divertido haciendo esto! Si desea aprovechar lo que ha aprendido, aquí hay algunas ideas para probar: Obtenga los datos de la película para las 1,000 películas en esa lista Raspe otros datos sobre cada película, por ejemplo, género, director, protagonista o el resumen de la película. Encuentre un sitio web diferente para raspar que le interese En mi próximo artículo, explicaré cómo recorrer todas las páginas de esta lista de IMDb para obtener todas las 1000 películas, lo que implicará algunas modificaciones en el código final que tenemos aquí. ¡Feliz codificación! Publicado anteriormente en https://medium.com/better-programming/the-only-step-by-step-guide-youll-need-to-build-a-web-scraper-with-python-e79066bd895a