Tabla de Contenidos
Extracción de imágenes y enlaces con el módulo bs4
Módulo perteneciente al curso Python avanzado para proyectos de seguridad
De la misma forma que en la sección anterior hemos extraído las enlaces, documentos e imágenes con el módulo de lxml, también podemos hacerlo directamente con BeautifulSoup.
En este ejemplo realizamos la petición a la url pasada por parámetro con el módulo requests. Posteriormente construimos el objeto BeautifulSoup a partir del cual vamos a extraer aquellas etiquetas que sean <img>. Si la url es correcta, se descarga la imagen de nuevo utilizando el módulo requests.
Para el caso de extraer imágenes a partir de una url podemos hacer uso del método bs.find_all("img").
Esto nos devolverá el listado de etiquetas img encontradas en el código html obtenido.
Puede encontrar el siguiente código en el fichero obtener_images_bs4.py:
#!/usr/bin/env python3 import os import requests from bs4 import BeautifulSoup class Scraping: def scrapingImages(self,url): print("Obtener imágenes de la url con bs4:"+ url) try: response = requests.get(url) bs = BeautifulSoup(response.text, 'lxml') images = bs.find_all("img") print('Imágenes encontradas %s' % len(images)) #crear directorio para guardar las imagenes os.system("mkdir imagenes") for tagImage in images: if tagImage['src'].startswith("http") == False: download = url + tagImage['src'] else: download = tagImage['src'] print(download) # descargar las imagenes en el directorio creado r = requests.get(download) f = open('imagenes/%s' % download.split('/')[-1], 'wb') f.write(r.content) f.close() except Exception as e: print("Error de conexión en: " + url) pass if __name__ == "__main__": target = "https://www.python.org" scraping = Scraping() scraping.scrapingImages(target)
Desde nuestro programa principal main llamaríamos al método scrapingImages de la clase Scraping pasándole por parámetro la url o target a analizar.
Como podemos ver en la salida nos devuelve aquellas imágenes que se encuentran en la página principal que estamos analizando.
Extraer enlaces a partir de una url con BeautifulSoup
Considere una situación en la que desea obtener todos los hipervínculos de la página web.
En el siguiente ejemplo extraemos todos los enlaces de una determinada URL. La idea es hacer la petición con requests y con BeautifulSoup parsear los datos que devuelve la petición.
Puede encontrar el siguiente código en el fichero extract_links_from_url.py:
#!/usr/bin/env python3 from bs4 import BeautifulSoup import requests url = input("Ingrese a un sitio web para extraer los links: ") headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'} response = requests.get("http://" +url, headers = headers) data = response.text soup = BeautifulSoup(data,'lxml') for link in soup.find_all('a'): link = link.get('href') if(link.startswith("http")): print(link) else: print(url+link)
En el código anterior la declaración from bs4 import BeautifulSoup permite importar la biblioteca BeautifulSoup. La variable url almacena la URL del sitio web y usamos el módulo requests para realizar la petición http.
La instrucción data = response.text asigna la página web a una variable data. En la instrucción soup = BeautifulSoup(data,'lxml'), se crea un objeto soup. La siguiente instrucción soup.find_all('a') guarda todos los hipervínculos.
Para su ejecución, bastaría con introducir un sitio web y extraerá todos los enlaces utilizando el método find_all() del módulo BeautifulSoup.
También podríamos utilizar el módulo urllib.requests para realizar la petición en lugar del módulo requests.
En el siguiente ejemplo estamos extrayendo los enlaces realizando la petición con urllib.requests.
Puede encontrar el siguiente código en el fichero links_pyvideo.py:
#!/usr/bin/env python3 import urllib.request from bs4 import BeautifulSoup def get_video_links(archive_url): # crear objeto respuesta response = urllib.request.urlopen(archive_url) # crear objeto beautiful-soup soup = BeautifulSoup(response.read(),'lxml') links = [] for link in soup.find_all('a'): file_link = link.get('href') links.append(file_link) return links links = get_video_links('https://pyvideo.org') print(links)
<p>Como podemos ver en la salida nos devuelve aquellos enlaces que se encuentran en la página principal que estamos analizando.</p>
['https://github.com/pyvideo/pyvideo/wiki/How-to-Contribute-Media', '/pages/thank-you-contributors.html', 'https://pyvideo.org/index.html', 'https://pyvideo.org/events.html', 'https://pyvideo.org/tags.html', 'https://pyvideo.org/speakers.html', 'https://pyvideo.org/pages/about.html', 'https://pyvideo.org/pages/thank-you-contributors.html', 'https://pyvideo.org/pages/thanks-will-and-sheila.html', 'https://pyvideo.org/', '/pycon-us-2020/1-1-1-or-record-deduplication-with-python.html', '/pycon-us-2020/1-1-1-or-record-deduplication-with-python.html', '/events/pycon-us-2020.html', '/speaker/flavio-juvenal-da-silva-junior.html', '/pycon-us-2020/9-years-of-pyladies-lessons-learned-and-what-comes-next.html', '/pycon-us-2020/9-years-of-pyladies-lessons-learned-and-what-comes-next.html', '/events/pycon-us-2020.html', '/speaker/lorena-mesa.html', '/speaker/elaine-wong.html', '/speaker/mariatta.html', '/pycon-us-2020/a-s-guide-to-unicode.html', '/pycon-us-2020/a-s-guide-to-unicode.html', '/events/pycon-us-2020.html', '/speaker/james-bennett.html', '/pycon-us-2020/asyncio-music.html', '/pycon-us-2020/asyncio-music.html', '/events/pycon-us-2020.html', '/speaker/lukasz-langa.html', '/pycon-us-2020/automate-the-boring-stuff-with-slackbot.html', '/pycon-us-2020/automate-the-boring-stuff-with-slackbot.html', '/events/pycon-us-2020.html', '/speaker/takanori-suzuki.html', '/pycon-us-2020/beautiful-python-refactoring.html', '/pycon-us-2020/beautiful-python-refactoring.html', '/events/pycon-us-2020.html', '/speaker/conor-hoekstra.html', 'https://pyvideo.org/events/pycon-us-2020.html', 'https://pyvideo.org/events/pyninsula-2020.html', 'https://pyvideo.org/events/minsk-python-meetup.html', 'https://pyvideo.org/events/pyjamas-conf-2019.html', 'https://pyvideo.org/events/pydata-warsaw-2019.html', '/events.html', 'https://pyvideo.org/speaker/russell-keith-magee.html', 'https://pyvideo.org/speaker/james-powell.html', 'https://pyvideo.org/speaker/brandon-rhodes.html', 'https://pyvideo.org/speaker/dustin-ingram.html', 'https://pyvideo.org/speaker/andrew-godwin.html', '/speakers.html', 'https://pyvideo.org/tag/lightning-talks/', 'https://pyvideo.org/tag/talk/', 'https://pyvideo.org/tag/tutorial/', 'https://pyvideo.org/tag/django/', 'https://pyvideo.org/tag/python/', 'https://pyvideo.org/tag/keynote/', 'https://pyvideo.org/tag/machine-learning/', 'https://pyvideo.org/tag/belarus/', 'https://pyvideo.org/tag/minsk/', 'https://pyvideo.org/tag/data-science/', '/tags.html', 'https://pyvideo.org/languages.html#eng', 'https://pyvideo.org/languages.html#spa', 'https://pyvideo.org/languages.html#rus', 'https://pyvideo.org/languages.html#por', 'https://pyvideo.org/languages.html#jpn', 'https://pyvideo.org/languages.html#fra', 'https://pyvideo.org/languages.html#kor', 'https://pyvideo.org/languages.html#ita', 'https://pyvideo.org/languages.html#deu', 'https://pyvideo.org/languages.html#zho', '/languages.html', 'https://github.com/pyvideo/pyvideo/blob/master/LICENSE', 'https://github.com/pyvideo/data/blob/master/LICENSE']
Actividad práctica: Completar el código que permite la extracción de enlaces con el módulo beautifulSoup
Completar el código que permite la extracción de enlaces con el módulo beautifulSoup
#!/usr/bin/env python3 import os import xxx from bs4 import xxx class Scraping: def scrapingLinks(self,xxx): print("Obtener links de la url:"+ xxx) try: response = requests.xxx(url) bs = xxx(xxx.text, 'lxml') links = bs.xxx("a") print('Links encontrados %s' % len(xxx)) for xxx in links: if xxx['href'].startswith("http") == False: print(xxx+xxx['href']) else: print(xxx['href']) except Exception as e: print("Error de conexión en: " + xxx) pass if __name__ == "__main__": target = "https://www.python.org" scraping = Scraping() scraping.xxx(xxx)
Desde nuestro programa principal main llamaríamos al método scrapingLinks de la clase Scraping pasándole por parámetro la url o target a analizar.
Como podemos ver en la salida, nos devuelve aquellos link que se encuentran en la página principal que estamos analizando.
Obtener links de la url:https://www.python.org Links encontrados 206 https://www.python.org#content https://www.python.org#python-network https://www.python.org/ https://www.python.org/psf-landing/ https://docs.python.org https://pypi.org/ https://www.python.org/jobs/ https://www.python.org/community/ https://www.python.org#top https://www.python.org/ https://psfmember.org/civicrm/contribute/transact?reset=1&id=2 https://www.python.org#site-map https://www.python.org# https://www.python.orgjavascript:; https://www.python.orgjavascript:; https://www.python.orgjavascript:; https://www.python.org# https://www.facebook.com/pythonlang?fref=ts https://twitter.com/ThePSF
Solución
#!/usr/bin/env python3 import os import requests from bs4 import BeautifulSoup class Scraping: def scrapingLinks(self,url): print("Obtener links de la url:"+ url) try: response = requests.get(url) bs = BeautifulSoup(response.text, 'lxml') links = bs.find_all("a") print('Links encontrados %s' % len(links)) for link in links: if link['href'].startswith("http") == False: print(url+link['href']) else: print(link['href']) except Exception as e: print("Error de conexión en: " + url) pass if __name__ == "__main__": target = "https://www.python.org" scraping = Scraping() scraping.scrapingLinks(target)
Implementar un crawler de enlaces a partir de una URL
El siguiente ejemplo permite implementar un crawler de enlaces a partir de una url.
Puede encontrar el siguiente código en el fichero obtener_links_spyder.py:
#!/usr/bin/env python3 import requests import sys from bs4 import BeautifulSoup # Creamos las listas 2 niveles urls_nivel1 = [] urls_nivel2 = [] # Recibimos los argumentos target_url = sys.argv[1] # Realizamos una conexión al argumento pasado y además, leemos todo el contenido del código fuente que existe en la página url = requests.get(target_url).content # Usamos nuestra librería de bs4 para posteriormente recatar lo que deseamos soup = BeautifulSoup(url,'lxml') # Mediante el for y el método de bs4 llamado find_all, recolectamos todas las etiquetas donde existe a href for line in soup.find_all('a'): new_line = line.get('href') try: # Si existe en alguna línea del código fuente el http, lo almacenamos en nuestra lista llamada urls if new_line[:4] == "http": if target_url in new_line: urls_nivel1.append(str(new_line)) # Si no existe, intentamos combinar nuestro argumento(url de la página) + lo que encontramos elif new_line[:1] == "/": try: comb_line = target_url+new_line urls_nivel1.append(str(comb_line)) except: pass # Recorremos lo que hemos guardado anteriormente en nuestra lista(urls). print(urls_nivel1) for get_this in urls_nivel1: # Como dentro de urls están todos los enlaces, realizamos una conexión a dicha url y leemos el código fuente url = requests.get(get_this).content # Usamos nuestra librería de bs4 para posteriormente obtener nuevos enlaces soup = BeautifulSoup(url,'lxml') for line in soup.find_all('a'): new_line = line.get('href') try: if new_line[:4] == "http": if target_url in new_line: urls_nivel2.append(str(newline)) elif new_line[:1] == "/": comb_line = target_url+new_line urls_nivel2.append(str(comb_line)) except: pass except: pass print(urls_nivel2)
Ejemplo de ejecución:
$ python obtener_links_spyder.txt http://python.org [] ['http://python.org/'] ['http://python.org/', 'http://python.org/jobs/'] ['http://python.org/', 'http://python.org/jobs/', 'http://python.org/community-landing/'] ['http://python.org/', 'http://python.org/jobs/', 'http://python.org/community-landing/', 'http://python.org/', 'http://python.org/community/irc/']
FAQ
¿Qué es BeautifulSoup?
Beautiful Soup es una librería Python que permite extraer información de contenido en formato HTML o XML. Para usarla, es necesario especificar un parser, que es responsable de transformar un documento HTML o XML en un árbol complejo de objetos Python. Esto permite, por ejemplo, que podamos interactuar con los elementos de una página web como si estuviésemos utilizando las herramientas del desarrollador de un navegador.
