por Ahad Sheriff
Un proyecto simple para aprender los fundamentos de la extracción de datos web
Antes de empezar, asegurémonos de entender qué es el raspado web:
El raspado web es el proceso de extracción de datos de sitios web para presentarlos en un formato que los usuarios puedan entender fácilmente.
En este tutorial, quiero demostrar lo fácil que es crear un rastreador de URL simple en Python que pueda usar para mapear sitios web. Si bien este programa es relativamente simple, puede proporcionar una gran introducción a los fundamentos de la extracción de datos web y la automatización. Nos centraremos en extraer recursivamente enlaces de páginas web, pero las mismas ideas se pueden aplicar a una miríada de otras soluciones.
Nuestro programa funcionará así:
- Visitar una página web
- Raspar todas las URL únicas que se encuentran en la página web y agregarlas a una cola
- Procesar recursivamente las URL una por una hasta agotar la cola
- Imprimir resultados
Lo primero es lo primero
Lo primero importa todas las bibliotecas necesarias. Utilizaremos BeautifulSoup, requests y urllib para la extracción de datos web.
from bs4 import BeautifulSoupimport requestsimport requests.exceptionsfrom urllib.parse import urlsplitfrom urllib.parse import urlparsefrom collections import deque
A continuación, necesitamos seleccionar una URL desde la que comenzar a rastrear. Si bien puedes elegir cualquier página web con enlaces HTML, te recomiendo usar ScrapeThisSite. Es una caja de arena segura que puedes gatear sin meterte en problemas.
url = "https://scrapethissite.com"
A continuación, vamos a necesitar crear un nuevo objeto deque para que podamos agregar fácilmente enlaces recién encontrados y eliminarlos una vez que hayamos terminado de procesarlos. Rellene previamente el deque con su variable url
:
# a queue of urls to be crawled nextnew_urls = deque()
Luego podemos usar un conjunto para almacenar URL únicas una vez que se hayan procesado:
# a set of urls that we have already processed processed_urls = set()
También queremos hacer un seguimiento de las URL locales (el mismo dominio que el destino), extranjeras (dominio diferente que el destino) y rotas:
# a set of domains inside the target websitelocal_urls = set()
# a set of domains outside the target websiteforeign_urls = set()
# a set of broken urlsbroken_urls = set()
Tiempo para rastrear
Con todo eso en su lugar, ahora podemos comenzar a escribir el código real para rastrear el sitio web.
Queremos ver cada URL de la cola, ver si hay alguna URL adicional dentro de esa página y agregar cada una al final de la cola hasta que no quede ninguna. Tan pronto como terminemos de raspar una URL, la eliminaremos de la cola y la agregaremos al conjunto processed_urls
para su uso posterior.
# process urls one by one until we exhaust the queuewhile len(new_urls): # move url from the queue to processed url set url = new_urls.popleft() processed_urls.add(url) # print the current url print("Processing %s" % url)
A continuación, agregue una excepción para capturar cualquier página web rota y agregarla al conjunto broken_urls
para su uso posterior:
try: response = requests.get(url)
except(requests.exceptions.MissingSchema, requests.exceptions.ConnectionError, requests.exceptions.InvalidURL, requests.exceptions.InvalidSchema): # add broken urls to it's own set, then continue broken_urls.add(url) continue
Luego necesitamos obtener la URL base de la página web para poder diferenciar fácilmente las direcciones locales y extranjeras:
# extract base url to resolve relative linksparts = urlsplit(url)base = "{0.netloc}".format(parts)strip_base = base.replace("www.", "")base_url = "{0.scheme}://{0.netloc}".format(parts)path = url if '/' in parts.path else url
Inicializar BeautifulSoup para procesar el documento HTML:
soup = BeautifulSoup(response.text, "lxml")
Ahora raspe la página web para todos los enlaces y agréguelos a su conjunto correspondiente:
for link in soup.find_all('a'): # extract link url from the anchor anchor = link.attrs if "href" in link.attrs else ''
if anchor.startswith('/'): local_link = base_url + anchor local_urls.add(local_link) elif strip_base in anchor: local_urls.add(anchor) elif not anchor.startswith('http'): local_link = path + anchor local_urls.add(local_link) else: foreign_urls.add(anchor)
Dado que quiero limitar mi rastreador solo a direcciones locales, agrego lo siguiente para agregar nuevas URL a nuestra cola:
for i in local_urls: if not i in new_urls and not i in processed_urls: new_urls.append(i)
Si desea rastrear todas las URL, use:
if not link in new_urls and not link in processed_urls: new_urls.append(link)
Aviso: De la forma en que el programa funciona actualmente, rastrear URL extranjeras llevará mucho tiempo. Posiblemente podría meterse en problemas por raspar sitios web sin permiso. ¡Úselo bajo su propio riesgo!
Aquí está todo mi código:
Y eso debería ser todo. ¡Acabas de crear una herramienta sencilla para rastrear un sitio web y mapear todas las URL encontradas!
En Conclusión
Siéntase libre de construir y mejorar este código. Por ejemplo, puede modificar el programa para buscar direcciones de correo electrónico o números de teléfono en páginas web a medida que las rastrea. Incluso podría ampliar la funcionalidad agregando argumentos de línea de comandos para proporcionar la opción de definir archivos de salida, limitar las búsquedas a la profundidad y mucho más. Obtenga información sobre cómo crear interfaces de línea de comandos para aceptar argumentos aquí.