Introducción a Web Scraping

En este notebook veremos algunos ejemplos sencillos de web scraping y al mismo tiempo aprenderemos un poco de HTML. La razón por la cual veremos HTML es porque al scrapear es útil identificar la estructura general de una página web y saber donde es posible que se encuentre la información que buscamos. El saber un poco de HTML nos facilitará el extraer la información.

Pero ¿Qué es Web Scraping?

En palabras llanas es una técnica que se apoya en el uso de la programación para extraer información de páginas web y tratar de estructurarla de tal forma que sea útil para trabajar con ella.

¿Y qué es HTML?

HTML son las siglas de HyperText Markup Language y es el lenguaje está1ndar en que se hacen las páginas de internet. Prácticamente todas las páginas que vemos en internet son en su mayoría cientos e incluso miles de líneas de este lenguaje.

En HTML todo está1 encerrado por lo que se conoce como etiquetas que se pueden entender como instrucciones para los navegadores que les indican la forma y estilo del texto encerrado entre éstas. La estructura general de una página escrita en HTML es la siguiente:

<html>
          <head>
              <title>.........</title>
              .
              .
              .
          </head>
          <body>
              <h1>.....</h1>
              .
              .
              .
              <p>.....</p>
              .
              .
              .
          </body>
</html>

Todo lo que está entre <> son las etiquetas. Como podemos ver todas tienen una pareja <..></...>, <...> indica el inicio de una etiqueta y </...> el final de ésta. Las principales etiquetas son estas:

<title>Indica el título de la página (el que vemos en la pestaña del navegador)</title>

<body>En esta etiqueta se encuentra todo el contenido de la página</body>

<h1,h2,h3...h6**>Indican los títulos que hay dentro del texto</h1...>

<p>Indican parrafos</p>

<a ...>Indican links</a>

<td ...>Indican texto dentro de una tabla</td>

<strong>Indica texto en negritas</strong>

<img ...>Indica una imagen</img>

Algunas etiquetas incluyen lo que se conoce como clases y atributos que modifican las características de la etiqueta. Son fácil identificarlos ya que se escriben después de la etiqueta y siempre llevan un signo = .

Para estos ejemplos introductorios usaremos una p\u00e1gina relativamene sencilla de scrapear. Empezaremos cargando la p\u00e1gina que utilizaremos en este notebook.


In [20]:
from IPython.display import HTML
p = """https://raw.githubusercontent.com/beangoben/lerningMachin/master/PaginaWeb/D%C3%ADa%20de%20muertos.html"""
pa = HTML(p);pa


Out[20]:

Día de muertos

Una de las tradiciones más representativas del pueblo mexicano es el Día de Muertos. Los origenes de esta celebración se remontan varios siglos atrás , antes de la época de la Colonia. Civilizaciones como los olmecas , mayas y aztecas compartían algo en común, la creencia de una vida después de la muerte.

Para nuestros antepasados la muerte era sólo una parte de un ciclo de la vida. Al morir la persona emprendía un viaje al Mictlán, el mundo de los muertos, lugar de su eterno reposo.

Al llegar los españoles a México, las creencias prehispánicas se fusionaron con la religión católica dando como resultado lo que hoy conocemos como el Día de Muertos y que se celebra cada 2 de Noviembre.

Elementos escenciales de un altar de muertos

Elemento Significado
Flor de Cempasúchil Quiere decir flor de más de 20 pétalos en la lengua náhuatl. Sus pétalos se usan para marcar en el suelo el camino que deben seguir las almas de los difuntos.
Velas Se usan para orientar a las almas e iluminar su camino
Sal Símbolo de purificación
Copal Atrae las almas de los difuntos hacia el altar
Comida Se ponen los platillos favoritos del difunto a quien se ofrece el altar
Agua Se coloca un vaso con agua para calmar la sed del difunto después de su largo viaje
Arco de flores Simboliza la entrada al mundo de los muertos

Para aprender más acerca de esta tradición puedes visitar las siguientes páginas http://www.uv.mx/cienciahombre/revistae/vol25num1/articulos/altar/ http://www.mexicodesconocido.com.mx/haz-tu-propia-ofrenda-de-dia-de-muertos.html * http://aristeguinoticias.com/2810/lomasdestacado/como-hacer-una-ofrenda-o-altar-de-muertos/

Con el código anterior cargamos la página de la cual extraeremos la información.

Primer Ejemplo

Para este primer ejemplo lo que haremos es obtener el título de la página web (el que aparece en la pestaña del navegador). Es importante recalcar que antes de cualquier cosa debemos importar las librerías que necesitaremos.


In [8]:
import urllib.request
import bs4
import re

Con las instrucciones anteriores hemos cargado las librerías que usaremos para el scrapping. Urllib.request nos permite acceder a las páginas (Si usas Python 2 debes cambiar urllib.request por urllib2), Beautiful Soup (bs4) nos permite parsear la página, re es la librería de Python de expresiones regulares.

Para aprender más acerca del uso de estas librerías podemos vistar las siguientes p\u00e1ginas:

Beautiful Soup

urllib.request

re

Después de que importamos la librerías podemos empezar a trabajar con la página. Lo primero que debemos hacer con una página es abrirla, para eso crearemos una función para facilitar la tarea.


In [9]:
def crearSopa(url):
      pageUrl = urllib.request.urlopen(url)
      pageHtml = pageUrl.read()
      pageUrl.close()
      return bs4.BeautifulSoup(pageHtml)

Con la función anterior abriremos la página, después la leeremos crearemos la sopa y cerraremos la página. A continuación le indicaremos al programa con que página debe hacer todo lo anterior.


In [10]:
sopa = crearSopa("https://raw.githubusercontent.com/beangoben/lerningMachin/master/PaginaWeb/D%C3%ADa%20de%20muertos.html")

Con la instrucción anterior hemos guardado todo el archivo HTML en la variable soup. Para comprobarlo veamos que tiene soup al imprimir esta variable.


In [11]:
print(sopa)


<html><body><h1 id="dia-de-muertos">Día de muertos</h1>
<p><img alt="alt text" src="http://www.reportajes.org/wp-content/uploads/2010/11/d%C3%ADa-de-muertos.jpg"/></p>
<p>Una de las tradiciones más representativas del pueblo mexicano es el Día de Muertos. Los origenes de esta celebración se remontan varios siglos atrás , antes de la época de la Colonia. Civilizaciones como los <strong>olmecas</strong> , <strong>mayas</strong> y <strong>aztecas</strong> compartían algo en común, la creencia de una <strong>vida</strong> después de la muerte.</p>
<p>Para nuestros antepasados la <strong>muerte</strong> era sólo una parte de un <strong>ciclo</strong> de la vida. Al morir la persona emprendía un viaje al Mictlán, el mundo de los muertos, lugar de su eterno reposo.</p>
<p>Al llegar los españoles a México, las creencias prehispánicas se fusionaron con la religión católica dando como resultado lo que hoy conocemos como el Día de Muertos y que se celebra cada <strong>2</strong> de <strong>Noviembre</strong>.</p>
<h3 id="elementos-escenciales-de-un-altar-de-muertos"><em>Elementos escenciales de un altar de muertos</em></h3>
<table>
<thead>
<tr>
<th align="center">Elemento</th>
<th>Significado</th>
</tr>
</thead>
<tbody>
<tr>
<td align="center">Flor de Cempasúchil</td>
<td>Quiere decir flor de más de 20 pétalos en la lengua náhuatl. Sus pétalos se usan para marcar en el suelo el camino que deben seguir las almas de los difuntos.</td>
</tr>
<tr>
<td align="center">Velas</td>
<td>Se usan para orientar a las almas e iluminar su camino</td>
</tr>
<tr>
<td align="center">Sal</td>
<td>Símbolo de purificación</td>
</tr>
<tr>
<td align="center">Copal</td>
<td>Atrae las almas de los difuntos hacia el altar</td>
</tr>
<tr>
<td align="center">Comida</td>
<td>Se ponen los platillos favoritos del difunto a quien se ofrece el altar</td>
</tr>
<tr>
<td align="center">Agua</td>
<td>Se coloca un vaso con agua para calmar la sed del difunto después de su largo viaje</td>
</tr>
<tr>
<td align="center">Arco de flores</td>
<td>Simboliza la entrada al mundo de los muertos</td>
</tr>
</tbody>
</table>
<p>Para aprender más acerca de esta tradición puedes visitar las siguientes páginas
<em> <a href="http://www.uv.mx/cienciahombre/revistae/vol25num1/articulos/altar/">http://www.uv.mx/cienciahombre/revistae/vol25num1/articulos/altar/</a>
</em> <a href="http://www.mexicodesconocido.com.mx/haz-tu-propia-ofrenda-de-dia-de-muertos.html">http://www.mexicodesconocido.com.mx/haz-tu-propia-ofrenda-de-dia-de-muertos.html</a>
* <a href="http://aristeguinoticias.com/2810/lomasdestacado/como-hacer-una-ofrenda-o-altar-de-muertos/">http://aristeguinoticias.com/2810/lomasdestacado/como-hacer-una-ofrenda-o-altar-de-muertos/</a></p></body></html>

Pero nosotros no queremos todo el código. Por el momento sólo nos interesa el t\ítulo de la pá1gina. Para esto primero debemos identificar en que etiquetas se encuentra esta información. En este caso las etiquetas que encierran la información que requerimos son <h1>. Afortunadamente Beautiful Soup nos permite obtener esta información de manera relativamente sencilla.


In [16]:
titulo = sopa.h1.get_text()
print(titulo)


Día de muertos

Hemos obtenido el título.En la primer línea del código anterior hemos escrito title entre soup y get_text() porque de esta manera le indicamos al programa entre que etiquetas buscar. La función get_text() nos permite obtener sólo el texto entre las etiquetas que deseamos.

Segundo Ejemplo

Ya hemos obtenido el título de la página pero eso es muy sencillo. Ahora vamos a obtener las palabras en negritas del texto. Primero debemos identificar las etiquetas en las que se encuentran estas palabras. Las etiquetas son <strong>. Lamentablemente no podemos usar el método anterior porque sólo obtiene el texto de las primeras etiquetas que encuentra, no de el de todas con la misma etiqueta. Por lo tanto debemos usar otro método, para el cual usaremos la función de Beautiful Soup find_all().


In [12]:
palabrasclave = sopa.find_all("strong")
print(palabrasclave)


[<strong>olmecas</strong>, <strong>mayas</strong>, <strong>aztecas</strong>, <strong>vida</strong>, <strong>muerte</strong>, <strong>ciclo</strong>, <strong>2</strong>, <strong>Noviembre</strong>]

Podemos ver que el nuevo método obtuvo todas las palabras que queríamos pero dejo las etiquetas de HTML y esas no nos sirve.


In [13]:
palabrascl = []
for indx, pacl in enumerate(palabrasclave):
          pacl = str(pacl.renderContents())
          palabrascl.append(pacl)
print(palabrascl)


["b'olmecas'", "b'mayas'", "b'aztecas'", "b'vida'", "b'muerte'", "b'ciclo'", "b'2'", "b'Noviembre'"]

Definimos una lista palabrascl en la que guardaremos las palabras después de haber quitado el texto basura. Hemos quitado las etiquetas pero sigue quedando una b'. Agregaremos esto también en la función replace.


In [14]:
palabrascl = []
for indx, pacl in enumerate(palabrasclave):
          pacl = str(pacl.renderContents())
          pacl = pacl.replace("b'","")
          pacl = pacl.replace("'","")
          palabrascl.append(pacl)
print(palabrascl)


['olmecas', 'mayas', 'aztecas', 'vida', 'muerte', 'ciclo', '2', 'Noviembre']

Finalmente hemos obtenido sólo el texto de todas las palabras clave de la página.

Tercer Ejemplo

Ahora hagamos algo que puede ser muy útil para futuros scrapings, obtener los links dentro de una página web. Nuevamente debemos identificar las etiqutas donde se encuentran alojados los links. En el caso de los links esta etiqueta es <a>.


In [18]:
a = sopa.find_all("a")
for indx, links in enumerate(a):
          print(indx,links.get('href'))


0 http://www.uv.mx/cienciahombre/revistae/vol25num1/articulos/altar/
1 http://www.mexicodesconocido.com.mx/haz-tu-propia-ofrenda-de-dia-de-muertos.html
2 http://aristeguinoticias.com/2810/lomasdestacado/como-hacer-una-ofrenda-o-altar-de-muertos/

En este ejemplo usamos la función de Beautiful Soup get(), el primer argumento indica la etiqueta de la que queremos obtener la información en este caso <links> y dentro de get() el atributo de la etiqueta.

Cuarto Ejemplo

Para este ejemplos buscaremos extraer la información de la tabla pero sólo los datos de la primer columna. De nuevo observando el código HTML nos damos cuenta de que la información que necesitamos se encuentran entre las etiquetas <td> pero a diferencia del texto de la segunda columna las etiquetas tienen un atributo "align = center". Podemos aprovechar esto a nuestro favor para indicarle al programa de una manera más específica que es lo que queremos que encuentre.


In [17]:
elementos = []
datostabla = sopa.find_all("td",{"align" : "center"})
for indx, elem in enumerate(datostabla):
          elem = str(elem.renderContents())
          elem = elem.replace("b'","")
          elem = elem.replace("'","")
          elementos.append(elem)
print(elementos)


['Flor de Cempas\\xc3\\xbachil', 'Velas', 'Sal', 'Copal', 'Comida', 'Agua', 'Arco de flores']

En la función find_all() además de indicar la etiqueta que queremos que busque también agregamos el atributo que tiene la primer columna a diferencia del ejemplo de las palabras clave en el que bastaba con indicar la etiqueta donde se encontraban las palabras.

Si no indicamos el atributo obtendrémos las dos columnas ya que el programa busca todo lo que se encuentra en la etiqueta <td>, por eso es importante aprovechar las clases y los atributos.