En el artículo de hoy vamos a raspar un sitio web con Python y extraer datos de él con Beautifulsoup.
El sitio web que vamos a scrapear es un simple sitio de intercambio de imágenes HTML/CSS para que podamos concentrarnos en entender el concepto central del web scraping en lugar de preocuparnos por la estructura del sitio web.
Scraping de un sitio web usando python
Ahora, vamos a comenzar nuestra misión de raspar el sitio web dado con Python.
Configuración del entorno virtual
Usar un entorno virtual y trabajar dentro de él es una de las mejores prácticas mientras se trabaja en proyectos de Python.
Sigue los siguientes códigos si estás en un dispositivo Windows.
# Installingpip install virtualenv # install Virtual Environment python -m venv env # create Virtual Environment env/Scripts/Activate.ps1 # activate Virtual Environment
Sigue los siguientes códigos si estás en un dispositivo Linux. Puedes utilizar el gestor de paquetes compatible (apt/yum/pacman..) con tu distro actual para instalar Virtual Environment.
sudo apt install virtualenv # install Virtual Environment virtualenv env # create Virtual Environment source env/bin/activate # activate Virtual Environment
Dependencias y requisitos de la instalación
Después de activar la env virtual para nuestro proyecto de scraping, vamos a instalar todos los requisitos.
pip install requests # Python Requests pip install bs4 # BeautifulSoup4 pip install htmlparser # HTLM5 Parser
# Or Install at Oncepip install requests bs4 htmlparser
Iniciando el web scraping
Crea un nuevo nombre de archivo con Scrape.py
o cualquier nombre que quieras. Importar Beautifulsoup y las peticiones de Python en ese archivo.
from bs4 import BeautifulSoup
import requests
Ahora, ¡es hora de algunas variables! Vamos a escribir nuestra primera variable como site_url
en nuestra siguiente línea.
site_url = 'https://img.webmatrices.com/'
Finalmente, si tienes algún problema con este sitio te he dado la fuente HTML en el repo de GitHub.
Extrayendo la fuente HTML
Necesitamos la fuente HTML para raspar el sitio porque la fuente HTML
es la fuente real de datos.
Para extraer o descargar la fuente HTML de cualquier sitio web, utilizamos Python Requests. Así, el trabajo se hará con un requests.get
y traduciéndolo a texto/cadena.
response = requests.get(site_url)
source = response.text
Aquí requests.get
envía/recibe una respuesta del servidor. Y con response.text
se extrae todo el Fuente HTML
de la web.
Parar HTML con Beautifulsoup
Ahora, viene el uso de HTMLParser
. Utilizaremos la librería BeautifulSoup y HTMLParser para parsear HTML.
soup = BeautifulSoup(source, ‘html.parser’)
Aquí, BeautifulSoup
cocina y analiza la fuente HTML de la página web utilizando HTMLParser. La sopa
parseada está bien gestionada y bien almacenada de tal manera que se puede extraer cualquier elemento HTML simplemente con el comando find
y find_all
.
Scraping data begins
Por lo tanto, tenemos que entender cómo el trozo de HTML se representa en la página web. Para entender la página web, necesitamos entender los requisitos de los datos.
Requisitos de datos: Vamos a extraer las descripciones, las fuentes de las imágenes y los alt de todas las imágenes.Después de conocer los requisitos, tenemos que dividir el trozo de HTML necesario de los trozos de HTML renderizados.
site-source-required.html<div class="gallery"> <a target="_blank" href="./site-source-code_files/Bishwas_Bhandari.jpg"> <img src="./site-source-code_files/Bishwas_Bhandari.jpg" alt="Subscribe to Developer Bishwas Bhandari" width="600" height="400" /> </a> <div class="desc">Subscribe to Developer Bishwas Bhandari</div> </div>
Ahora, vamos a encontrar todas las divisiones con nombre de clase de la galería (es decir, <div class="gallery">
), porque esos elementos de división contienen los datos necesarios en ellos.
# Extracting divs with gallery class-namegallery_elements = soup.find_all('div', class_ = 'gallery') # or .find_all('div', {'class': 'gallery'})
soup.find_all('div', class_ = 'gallery')
devuelve todos los elementos como una lista en la variable gallery_elements
.
Ahora, haremos un bucle a través de gallery_elements
para acceder a cada elemento dentro de ella.
# Getting index and each gallery elementfor index, gallery_element in enumerate(gallery_elements):
Después de este bucle, encontraremos la etiqueta img (es decir, img
) dentro de cada elemento de la galería.
image = gallery_element.find('img')
Así que, tenemos la etiqueta img, ahora vamos a obtener los atributos dentro de ella. En general, para obtener un atributo de un elemento-HTML soplado,
HTML Element<tag attribute_name='my-attribute'>Inside Tag.. </tag>
Souped HTML elementsouped_HTML_element = soup.find('tag', class_='some-class') arrtibute = souped_HTML_element['arrtibute_name']
Entonces, para obtener la fuente/ruta de una imagen tenemos que hacer,
image_source = image['src'] Y lo mismo para el alt de la imagen,# [‘alt’] gets the alt attribute of img-tagimage_alt = image['alt']
Algo similar ocurre con la descripción
discription = gallery_element.find('div', class_="desc")
Por último, realizamos un bucle a través de la gallery_elements
y lo iteramos, pero todavía tenemos que recoger datos limpios dentro del bucle.
for index, gallery_element in enumerate(gallery_elements): image = gallery_element.find('img') image_source = image['src'] image_alt = image['alt'] # for description description = gallery_element.find('div', class_="desc") # use .text to get text from the description
Para recoger los datos limpios, vamos a crear una variable de diccionario vacía antes de que comience el bucle, gallery_data = {}
.
gallery_data = {} for index, gallery_element in enumerate(gallery_elements): ...
Actualizar los datos en gallery_update
dentro del bucle.
... gallery_data.update({ index: { 'source': image_source, 'alt': image_alt, 'description': description.text } })
Finalmente la impresión de gallery_data
da,
// Result{0: {'source': '/media/Bishwas_Bhandari.jpg', 'alt': 'Subscribe to Developer Bishwas Bhandari', 'discription': 'Subscribe to Developer Bishwas Bhandari'}, 1: {'source': '/media/Existence_of_1d_object_and_its_motion_with1.gif', 'alt': 'Existance of 2d object', 'discription': 'Existance of 2d object'}, 2: {'source': '/media/7495.jpg', 'alt': 'Developer Illustration - Programming Image', 'discription': 'Developer Illustration - Programming Image'}, 3: {'source': '/media/linkedin_hashtag_generator.png', 'alt': 'linkedin hashtag generator', 'discription': 'linkedin hashtag generator'}, 4: {'source': '/media/LinkedIn_Hashtag_Generator_icon.png', 'alt': 'LinkedIn Hashtag Generator Icon', 'discription': 'LinkedIn Hashtag Generator Icon'}, 5: {'source': '/media/coder2.gif', 'alt': 'programmer coding gif', 'discription': 'programmer coding gif'}, 6: {'source': '/media/suprised_with_big_eyes.gif', 'alt': 'Suprised with BIG eyes', 'discription': 'Suprised with BIG eyes'}, 7: {'source': '/media/laughing_gif_meme.gif', 'alt': 'Laughing Gif Meme', 'discription': 'Laughing Gif Meme'}, 8: {'source': '/media/lemme_see_lemme_see_gif_meme.gif', 'alt': 'Lemme see gif meme', 'discription': 'Lemme see gif meme'}, 9: {'source': '/media/sheldon_meme_gif.gif', 'alt': "It's funny because it's true - sheldon meme", 'discription': "It's funny because it's true - sheldon meme"}, 10: {'source': '/media/wow_meme_gif_template.gif', 'alt': 'Wow meme gif template', 'discription': 'Wow meme gif template'}, 11: {'source': '/media/tej_magar_clone.jpg', 'alt': "tej magar clone'", 'discription': "tej magar clone'"}, 12: {'source': '/media/dekha_apne_laparwahi_ka_natija_gif.gif', 'alt': 'dekha apne laparwahi ka natija gif', 'discription': 'dekha apne laparwahi ka natija gif'}, 13: {'source': '/media/Affiliate_marketing_flarum_extension_free.png', 'alt': 'Affiliate marketing flarum extension free', 'discription': 'Affiliate marketing flarum extension free'}, 14: {'source': '/media/linux-physics-chemistry.jpg', 'alt': 'Linux wallpaper for mobile, linux: physics, chemist', 'discription': 'Linux wallpaper for mobile, linux: physics, chemist'}}
¿Cómo limpiar datos raspados en Python?
Pero bueno, esos datos no son tan fáciles de leer y entender, así que usaremos el formato json con la ayuda de una librería incorporada en python llamada json
Importar la biblioteca json
Para poder utilizar la biblioteca json, debemos importarla. así que …
import json at the top of your codeimport json
Volcar el diccionario en formato json
Volcar o limpiar el diccionario de python a formato json es una práctica muy inteligente. Y dar indent=4
es la más inteligente.
gallery_data = json.dumps(gallery_data, indent=4)
Después de imprimir estos datos, obtendremos…
{ "0": { "source": "/media/Bishwas_Bhandari.jpg", "alt": "Subscribe to Developer Bishwas Bhandari", "description": "Subscribe to Developer Bishwas Bhandari" }, "1": { "source": "/media/Existence_of_1d_object_and_its_motion_with1.gif", "alt": "Existance of 2d object", "description": "Existance of 2d object" }, "2": { "source": "/media/7495.jpg", "alt": "Developer Illustration - Programming Image", "description": "Developer Illustration - Programming Image" }, ... "14": { "source": "/media/linux-physics-chemistry.jpg", "alt": "Linux wallpaper for mobile, linux: physics, chemist", "description": "Linux wallpaper for mobile, linux: physics, chemist" } }
Tarea para ti
Como el source
tiene el valor similar a /media/image.png
, que no contiene la ruta completa-actual de la imagen. Por qué no lo haces algo similar a https://img.webmatrices.com/media/image.png
.
Además, echa un vistazo a código final (repo de GitHub).
Feliz codificación.