Python Scraping
Python Scraping
Introducción
Muchos proyectos de análisis de datos, big data y aprendizaje automático
requieren raspar sitios web para recopilar los datos con los que trabajará. El
lenguaje de programación Python se usa ampliamente en la comunidad de
ciencia de datos y, por lo tanto, tiene un ecosistema de módulos y
herramientas que puede usar en sus propios proyectos. En este tutorial nos
centraremos en el módulo Beautiful Soup.
Prerrequisitos
Antes de trabajar en este tutorial, debe tener un entorno de programación
puede lograr siguiendo nuestro tutorial " Cómo trabajar con datos web
mediante solicitudes y Beautiful Soup con Python 3 ". También sería útil tener
Además, dado que trabajaremos con datos eliminados de la web, debe sentirse
cómodo con la estructura y el etiquetado HTML.
https://web.archive.org/web/20170131230332/https://www.nga.gov/col
lection/an.shtm
Nota : La URL larga anterior se debe a que este sitio web ha sido archivado por
Internet Archive.
Internet Archive es una biblioteca digital sin fines de lucro que brinda acceso
gratuito a sitios de Internet y otros medios digitales. Esta organización toma
instantáneas de sitios web para preservar las historias de los sitios, y actualmente
podemos acceder a una versión anterior del sitio de la Galería Nacional que estaba
disponible cuando se escribió este tutorial por primera vez. Internet Archive es una
buena herramienta para tener en cuenta al realizar cualquier tipo de raspado de
datos históricos, incluida la comparación entre iteraciones del mismo sitio y los
datos disponibles.
Debajo del encabezado de Internet Archive, verá una página que se ve así:
Dado que haremos este proyecto para aprender sobre el raspado web con
Beautiful Soup, no necesitamos extraer demasiados datos del sitio, así que
limitemos el alcance de los datos del artista que buscamos raspar. Por lo tanto,
elija una letra (en nuestro ejemplo, elegiremos la letra Z ) y veremos una
página similar a esta:
En la página anterior, vemos que el primer artista en la lista al momento de
escribir es Zabaglia, Niccola , que es algo bueno para tener en cuenta
cuando comenzamos a extraer datos. Comenzaremos trabajando con esta
primera página, con la siguiente URL para la letra Z :
https://web.archive.org/web/20121007172955/http://www.nga.gov/coll
ection/an Z 1.htm
Es importante tener en cuenta para más adelante cuántas páginas hay en total
para la letra que está eligiendo enumerar, que puede descubrir haciendo clic
en la última página de artistas. En este caso, hay un total de 4 páginas, y el
último artista que aparece al momento de escribir es Zykmund, Václav . La
última página de artistas Z tiene la siguiente URL:
https://web.archive.org/web/20121010201041/http://www.nga.gov/coll
ection/an Z 4.htm
https://web.archive.org/web/ 20121007172955 /http://www.nga.gov/co
llection/an Z 4.htm
Es importante tener en cuenta esto porque iteraremos por estas páginas más
adelante en este tutorial.
nano nga_z_artists.py
Dentro de este archivo, podemos comenzar a importar las bibliotecas que
nga_z_artists.py
# Import libraries
import requests
from bs4 import BeautifulSoup
Copiar
Con los módulos Solicitudes y Beautiful Soup importados, podemos pasar a
trabajar para recopilar primero una página y luego analizarla.
nga_z_artists.py
import requests
from bs4 import BeautifulSoup
nga_z_artists.py
import requests
from bs4 import BeautifulSoup
page =
requests.get('https://web.archive.org/web/20121007172955/https://www.nga.gov/collection/a
nZ1.htm')
Para hacer esto, en su navegador web, haga clic derecho - o CTRL+ clic en
macOS - en el nombre del primer artista, Zabaglia, Niccola . Dentro del menú
contextual que aparece, debería ver un elemento de menú similar a Inspect
Element (Firefox) o Inspect (Chrome).
Una vez que haga clic en el elemento del menú Inspeccionar relevante , las
herramientas para desarrolladores web deberían aparecer dentro de su
navegador. Queremos buscar la clase y las etiquetas asociadas con los
nombres de los artistas en esta lista.
Primero veremos que la tabla de nombres está dentro de las <div>etiquetas
donde class="BodyText". Es importante tener en cuenta que solo buscamos
texto dentro de esta sección de la página web. También notamos que el
nombre Zabaglia, Niccola está en una etiqueta de enlace, ya que el nombre
hace referencia a una página web que describe al artista. Por lo tanto,
querremos hacer referencia a la <a>etiqueta para enlaces. El nombre de cada
artista es una referencia a un enlace.
nga_z_artists.py
import requests
from bs4 import BeautifulSoup
# Pull text from all instances of <a> tag within BodyText div
artist_name_list_items = artist_name_list.find_all('a')
Copiar
nga_z_artists.py
...
artist_name_list = soup.find(class_='BodyText')
artist_name_list_items = artist_name_list.find_all('a')
python nga_z_artists.py
Una vez que lo hagamos, recibiremos el siguiente resultado:
Output
<a href="/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?artistid=11630">
Zabaglia, Niccola
</a>
...
<a href="/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?artistid=3427">
Zao Wou-Ki
</a>
<a href="/web/20121007172955/https://www.nga.gov/collection/anZ2.htm">
Zas-Zie
</a>
<a href="/web/20121007172955/https://www.nga.gov/collection/anZ3.htm">
Zie-Zor
</a>
<a href="/web/20121007172955/https://www.nga.gov/collection/anZ4.htm">
<strong>
next
<br/>
page
</strong>
</a>
Lo que vemos en el resultado en este punto es el texto completo y las
etiquetas relacionadas con todos los nombres de los artistas dentro de
las <a>etiquetas que se encuentran en la <div class="BodyText">etiqueta en la
primera página, así como también un texto de enlace adicional en la parte
inferior. Como no queremos esta información adicional, trabajemos para
eliminarla en la siguiente sección.
Para eliminar los enlaces inferiores de la página, nuevamente haga clic derecho
e Inspeccione el DOM. Veremos que los enlaces en la parte inferior de la <div
class="BodyText">sección están contenidos en una tabla HTML <table
class="AlphaNav">:
Por lo tanto, podemos usar Beautiful Soup para encontrar la AlphaNavclase y
usar el decompose()método para eliminar una etiqueta del árbol de análisis y
luego destruirla junto con su contenido.
nga_z_artists.py
import requests
from bs4 import BeautifulSoup
page =
requests.get('https://web.archive.org/web/20121007172955/https://www.nga.gov/collection/a
nZ1.htm')
artist_name_list = soup.find(class_='BodyText')
artist_name_list_items = artist_name_list.find_all('a')
Output
<a href="/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?artistid=11630">
Zabaglia, Niccola
</a>
<a href="/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?artistid=34202">
Zaccone, Fabian
</a>
...
<a href="/web/20121007172955/http://www.nga.gov/cgi-bin/tsearch?artistid=11631">
Zanotti, Giampietro
</a>
<a href="/web/20121007172955/http://www.nga.gov/cgi-bin/tsearch?artistid=3427">
Zao Wou-Ki
</a>
En este punto, vemos que la salida ya no incluye los enlaces en la parte inferior
de la página web, y ahora solo muestra los enlaces asociados con los nombres
de los artistas.
Hasta ahora, hemos apuntado específicamente a los enlaces con los nombres
de los artistas, pero tenemos los datos de etiquetas adicionales que realmente
no queremos. Eliminemos eso en la siguiente sección.
page =
requests.get('https://web.archive.org/web/20121007172955/https://www.nga.gov/collection/a
nZ1.htm')
last_links = soup.find(class_='AlphaNav')
last_links.decompose()
artist_name_list = soup.find(class_='BodyText')
artist_name_list_items = artist_name_list.find_all('a')
Output
Zabaglia, Niccola
Zaccone, Fabian
Zadkine, Ossip
...
Zanini-Viola, Giuseppe
Zanotti, Giampietro
Zao Wou-Ki
Hemos recibido lo que es una lista de los nombres de todos los artistas
disponibles en la primera página de la letra Z .
Sin embargo, ¿qué pasa si queremos capturar también las URL asociadas con
esos artistas? Podemos extraer las URL que se encuentran dentro de
las <a>etiquetas de una página utilizando el get('href')método de Beautiful
Soup .
nga_z_artists.py
...
for artist_name in artist_name_list_items:
names = artist_name.contents[0]
links = 'https://web.archive.org' + artist_name.get('href')
print(names)
print(links)
Copiar
Cuando ejecutamos el programa anterior, recibiremos tanto los nombres de
los artistas como las URL de los enlaces que nos informan más sobre los
artistas:
Output
Zabaglia, Niccola
https://web.archive.org/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?
artistid=11630
Zaccone, Fabian
https://web.archive.org/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?
artistid=34202
...
Zanotti, Giampietro
https://web.archive.org/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?
artistid=11631
Zao Wou-Ki
https://web.archive.org/web/20121007172955/https://www.nga.gov/cgi-bin/tsearch?
artistid=3427
Aunque ahora estamos obteniendo información del sitio web, actualmente solo
se está imprimiendo en nuestra ventana de terminal. En su lugar, capturemos
estos datos para poder usarlos en otro lugar escribiéndolos en un archivo.
import csv
Copiar
f.writerow([names, links])
Copiar
Puede ver las líneas para cada una de estas tareas en el archivo a
continuación:
nga_z_artists.py
import requests
import csv
from bs4 import BeautifulSoup
page =
requests.get('https://web.archive.org/web/20121007172955/http://www.nga.gov/collection/an
Z1.htm')
last_links = soup.find(class_='AlphaNav')
last_links.decompose()
artist_name_list = soup.find(class_='BodyText')
artist_name_list_items = artist_name_list.find_all('a')
z-artist-names.csv
Name,Link
"Zabaglia,
Niccola",https://web.archive.org/web/20121007172955/http://www.nga.gov/cgi-
bin/tsearch?artistid=11630
"Zaccone,
Fabian",https://web.archive.org/web/20121007172955/http://www.nga.gov/cgi-
bin/tsearch?artistid=34202
"Zadkine, Ossip",https://web.archive.org/web/20121007172955/http://www.nga.gov/cgi-
bin/tsearch?artistid=3475w
...
O bien, puede parecerse más a una hoja de cálculo:
En cualquier caso, ahora puede usar este archivo para trabajar con los datos de
manera más significativa, ya que la información que ha recopilado ahora se
almacena en la memoria de su computadora.
Recuperando páginas relacionadas
Hemos creado un programa que va a extraer datos de la primera página de la
lista de artistas cuyos apellidos comiencen con la letra Z . Sin embargo, hay 4
páginas en total de estos artistas disponibles en el sitio web.
Para comenzar, queremos inicializar una lista para contener las páginas:
pages = []
Copiar
Además de este ciclo, tendremos un segundo ciclo que pasará por cada una de
las páginas anteriores. El código en este forbucle será similar al código que
hemos creado hasta ahora, ya que está haciendo la tarea que completamos
para la primera página de los artistas de la letra Z para cada una de las 4
páginas en total. Tenga en cuenta que debido a que hemos colocado el
programa original en el segundo forciclo, ahora tenemos el ciclo original como
un ciclo anidadofor contenido en él.
last_links = soup.find(class_='AlphaNav')
last_links.decompose()
artist_name_list = soup.find(class_='BodyText')
artist_name_list_items = artist_name_list.find_all('a')
f.writerow([names, links])
Copiar
En el código anterior, debería ver que el primer forciclo está iterando sobre las
páginas y el segundo forciclo está raspando datos de cada una de esas
páginas y luego agrega los nombres y enlaces de los artistas línea por línea a
través de cada fila de cada página.
nga_z_artists.py
import requests
import csv
from bs4 import BeautifulSoup
f = csv.writer(open('z-artist-names.csv', 'w'))
f.writerow(['Name', 'Link'])
pages = []
last_links = soup.find(class_='AlphaNav')
last_links.decompose()
artist_name_list = soup.find(class_='BodyText')
artist_name_list_items = artist_name_list.find_all('a')
f.writerow([names, links])
Copiar
Dado que este programa está haciendo un poco de trabajo, tomará un poco de
tiempo crear el archivo CSV. Una vez hecho, la salida estará completa,
mostrando los nombres de los artistas y sus enlaces asociados
desde Zabaglia, Niccola a Zykmund, Václav .
Ser considerado
Al raspar páginas web, es importante ser considerado con los servidores de los
que obtiene información.
Además, es una buena idea raspar con un encabezado que tenga su nombre y
correo electrónico para que un sitio web pueda identificarlo y hacer un
seguimiento si tienen alguna pregunta. Un ejemplo de un encabezado que
puede usar con la biblioteca de solicitudes de Python es el siguiente:
import requests
headers = {
'User-Agent': 'Your Name, example.com',
'From': '[email protected]'
}
url = 'https://example.com'
Conclusión
Este tutorial pasó por usar Python y Beautiful Soup para raspar datos de un
sitio web. Almacenamos el texto que reunimos dentro de un archivo CSV.
nuestro tutorial " Cómo rastrear una página web con Scrapy y Python 3 ".