9.2 beautifulsoup
El paquete Beautiful Soup es ampliamente utilizado en técnicas de «scraping» permitiendo «parsear»2 principalmente código HTML.
Para empezar a trabajar con Beautiful Soup es necesario construir un objeto de tipo BeautifulSoup que reciba el contenido a «parsear»:
A partir de aquí se abre un abanico de posibilidades que iremos desgranando en los próximos epígrafes.
Una de las tareas más habituales en técnicas de «scraping» y en «parsing» de contenido es la localización de determinadas elementos de interés.
Fórmulas de localización
A continuación se muestran, mediante ejemplos, distintas fórmulas para localizar elementos dentro del DOM:
- Localizar todos los enlaces:
El primer argumento posicional de find_all() es el nombre del «tag» que queremos localizar.
- Localizar todos los elementos con la clase inline:
Los argumentos nominales de find_all() se utilizan para localizar elementos que contengan el atributo referenciado.
Truco: Si el atributo a localizar tiene guiones medios (por ejemplo aria-label) no podremos usarlo como nombre de argumento (error sintáctico). Pero sí podemos usar un diccionario en su lugar:
- Localizar todos los «divs» con la clase footer:
- Localizar todos los elementos cuyo atributo type tenga el valor text:
- Localizar todos los los h2 que contengan el texto Formulario:
- Localizar todos los elementos de título h1, h2, h3, …. Esto lo podemos atacar usando expresiones regulares:
- Localizar todos los «input» y todos los «span»:
- Localizar todos los párrafos que están dentro del pie de página (usando selectores
CSS):
Localizar único elemento
Hasta ahora hemos visto las funciones find_all() y select() que localizan un conjunto de elementos. Incluso en el caso de encontrar sólo un elemento, se devuelve una lista con ese único elemento.
Beautiful Soup nos proporciona la función find() que trata de localizar un único elemento. Hay que tener en cuenta dos circunstancias:
- En caso de que el elemento buscado no exista, se devuelve None.
- En caso de que existan múltiples elementos, se devuelve el primero.
Veamos algunos ejemplos de esto:
Localizar desde elemento
Todas las búsquedas se pueden realizar desde cualquier elemento preexistente, no únicamente desde la raíz del DOM.
Veamos un ejemplo de ello. Si tratamos de localizar todos los títulos «h2» vamos a encontrar dos de ellos:
Pero si, previamente, nos ubicamos en el segundo bloque de contenido, sólo vamos a encontrar uno de ellos:
Otras funciones de búsqueda
Hay definidas una serie de funciones adicionales de búsqueda para cuestiones más particulares:
- Localizar los «div» superiores a partir de un elemento concreto:
Se podría decir que la función find_all() busca en descendientes y que la función find_parents() busca en ascendientes.
También existe la versión de esta función que devuelve un único elemento: find_parent().
- Localizar los elementos hermanos siguientes a uno dado:
Al igual que en las anteriores, es posible aplicar un filtro al usar esta función.
También existe la versión de esta función que devuelve un único elemento: find_next_sibling().
- Localizar los elementos hermanos anteriores a uno dado:
Al igual que en las anteriores, es posible aplicar un filtro al usar esta función.
También existe la versión de esta función que devuelve un único elemento: find_previous_sibling().
Localizar todos los elementos a continuación de uno dado:
Al igual que en las anteriores, es posible aplicar un filtro al usar esta función. También existe la versión de esta función que devuelve un único elemento: find_next().
- Localizar todos los elementos previos a uno dado:
También existe la versión de esta función que devuelve un único elemento: find_previous().
Si hubiéramos hecho esta búsqueda usando find_parents() no habríamos obtenido el mismo resultado ya que los elementos de título no son elementos superiores de «ul»:
Atajo para búsquedas
Dado que la función find_all() es la más utilizada en Beautiful Soup se ha implementado un atajo para llamarla:
Aunque uno de los preceptos del Zen de Python es «Explicit is better than implicit», el uso de estos atajos puede estar justificado en función de muchas circunstancias.