Volver al blog
Guías
Mihai MaximLast updated on Mar 31, 20265 min read

Parsel: Cómo extraer texto de HTML en Python

Parsel: Cómo extraer texto de HTML en Python

Introducción

El web scraping es el proceso automatizado de recopilación de datos de sitios web mediante el uso de un script o programa. Se utiliza para extraer información como texto, imágenes y otros tipos de datos que pueden resultar útiles para diversos fines, como la investigación, el análisis de datos o el análisis de mercado.

Hoy en día, existen un montón de soluciones para el web scraping con Python. Selenium y Scrapy son algunas de las bibliotecas más utilizadas y populares. Aunque estas herramientas son excelentes para tareas de scraping complicadas, pueden resultar un poco abrumadoras para un uso ocasional.

Te presento a Parsel, la pequeña biblioteca de scraping. Esta biblioteca ligera y fácil de aprender es perfecta para proyectos pequeños y es ideal para quienes se inician en el scraping web. Es capaz de analizar HTML y extraer datos utilizando selectores CSS y XPath, lo que la convierte en una herramienta estupenda para cualquier amante de los datos que busque una forma rápida y sencilla de recopilar información de la web.

Abróchate el cinturón y prepárate para aprender a usar esta biblioteca mientras me acompañas en esta aventura de recopilación automatizada de datos. ¡Manos a la obra con el scraping!

Introducción a Parsel

Puedes instalar la biblioteca Parsel con:

pip install parsel

Ahora vamos a sumergirnos directamente en un proyecto de ejemplo y extraer todos los datos de países de este sencillo sitio web: https://www.scrapethissite.com/pages/simple/.

Para obtener el HTML del sitio web, tendrás que realizar una solicitud HTTP GET.

Realizaremos las solicitudes HTTP con la biblioteca de Python «requests», así que asegúrate de instalarla con:

pip install requests

Ahora puedes recuperar el HTML y guardarlo en un archivo:

import parsel

import requests

response = requests.get("https://www.scrapethissite.com/pages/simple/")

with open("out.html", "w", encoding="utf-8") as f:

f.write(response.text)

Y examinar la estructura:

Nuestros datos se almacenan en estructuras similares a esta:

<div class="col-md-4 country">

   <h3 class="country-name">

       <i class="flag-icon flag-icon-af"></i>

       Afghanistan

   </h3>

   <div class="country-info">

       <strong>Capital:</strong> <span class="country-capital">Kabul</span><br>

       <strong>Population:</strong> <span class="country-population">29121286</span><br>

       <strong>Area (km<sup>2</sup>):</strong> <span class="country-area">647500.0</span><br>

   </div>

</div><!--.col-->

Para escribir selectores, tendrás que pasar el HTML sin procesar a Parsel:

import parsel

import requests

response = requests.get("https://www.scrapethissite.com/pages/simple/")

raw_html = response.text

parsel_dom = parsel.Selector(text = raw_html)

Ahora estamos listos para escribir algunos selectores.

Extraer texto utilizando selectores CSS

Puedes mostrar la capital del primer país con:

parsel_dom = parsel.Selector(text=raw_html)

first_capital = parsel_dom.css(".country-capital::text").get()

print(first_capital)

// Output

Andorra la Vella

parsel_dom.css(".country-capital::text").get() will select the inner text of the first element that has the country-capital class.

Puedes mostrar todos los nombres de los países con:

countries_names = filter(lambda line: line.strip() != "", parsel_dom.css(".country-name::text").getall())

for country_name in countries_names:

   print(country_name.strip())

// Output

Andorra

United Arab Emirates

Afghanistan

Antigua and Barbuda

Anguilla

. . .

parsel_dom.css(".country-name::text").getall() will select the inner texts of all the elements that have the "country-name" class.

Fíjate en que hemos tenido que limpiar un poco el resultado. Lo hemos hecho porque todos los elementos que tienen la clase «.country-name» también tienen una etiqueta <i> anidada en su interior. Además, el nombre del país está rodeado de muchos espacios al final.

<h3 class="country-name">

 <i class="flag-icon flag-icon-ae"></i> //this is picked up as an empty string

  United Arab Emirates // this is picked up as “  United Arab Emirates  “

</h3>

Ahora escribamos un script para extraer todos los datos con selectores CSS:

import parsel

import requests

response = requests.get("https://www.scrapethissite.com/pages/simple/")

raw_html = response.text

parsel_dom = parsel.Selector(text=raw_html)

countries = parsel_dom.css(".country")

countries_data = []

for country in countries:

  country_name = country.css(".country-name::text").getall()[1].strip()

  country_capital = country.css(".country-capital::text").get()

  country_population = country.css(".country-population::text").get()

  country_area = country.css(".country-area::text").get()

  countries_data.append({

     "name": country_name,

     "capital": country_capital,

     "population": country_population,

     "area": country_area

  })

for country_data in countries_data:

  print(country_data)

// Outputs

{'name': 'Andorra', 'capital': 'Andorra la Vella', 'population': '84000', 'area': '468.0'}

{'name': 'United Arab Emirates', 'capital': 'Abu Dhabi', 'population': '4975593', 'area': '82880.0'}

{'name': 'Afghanistan', 'capital': 'Kabul', 'population': '29121286', 'area': '647500.0'}

... 

Extracción de texto mediante selectores XPath

XPath es un lenguaje de consulta para seleccionar nodos de un documento XML. Son las siglas de XML Path Language, y utiliza una notación de ruta similar a la de las URL para navegar por los elementos y atributos de un documento XML. Las expresiones XPath se pueden utilizar para seleccionar un único elemento, un conjunto de elementos o un atributo específico de un elemento. XPath se utiliza principalmente en XSLT, pero también puede usarse para navegar por el Modelo de Objetos de Documento (DOM) de cualquier documento en un lenguaje similar a XML, como HTML o SVG.

XPath puede parecer intimidante al principio, pero en realidad es bastante fácil empezar a utilizarlo una vez que se comprenden los conceptos básicos y la sintaxis. Un recurso que puede resultar útil es nuestra guía de selectores XPath en https://www.webscrapingapi.com/the-ultimate-xpath-cheat-sheet.

Ahora probemos algunos selectores:

Así es como puedes imprimir la primera letra mayúscula:

parsel_dom = parsel.Selector(text=raw_html)

first_capital = parsel_dom.xpath('//*[@class="country-capital"]/text()').get()

print(first_capital)

// Output

Andorra la Vella

Y todos los nombres de países:

countries_names = filter(lambda line: line.strip() != "", 

parsel_dom.xpath('//*[@class="country-name"]//text()').getall())

for country_name in countries_names:

  print(country_name.strip())

// Output

Andorra la Vella

Abu Dhabi

Kabul

St. John's

The Valley

Tirana

...

Reimplementemos el script con selectores XPath:

import parsel

import requests

response = requests.get("https://www.scrapethissite.com/pages/simple/")

raw_html = response.text

parsel_dom = parsel.Selector(text=raw_html)

countries = parsel_dom.xpath('//div[contains(@class,"country")][not(contains(@class,"country-"))]')

countries_data = []

for country in countries:

 country_name = country.xpath(".//h3/text()").getall()[1].strip()

 country_capital = country.xpath(".//span/text()").getall()[0]

 country_population = country.xpath(".//span/text()").getall()[1]

 country_area = country.xpath(".//span/text()").getall()[2]

 countries_data.append({

    "name": country_name,

    "capital": country_capital,

    "population": country_population,

    "area": country_area

 })

for country_data in countries_data:

 print(country_data)

// Output

{'name': 'Andorra', 'capital': 'Andorra la Vella', 'population': '84000', 'area': '468.0'}

{'name': 'United Arab Emirates', 'capital': 'Abu Dhabi', 'population': '4975593', 'area': '82880.0'}

{'name': 'Afghanistan', 'capital': 'Kabul', 'population': '29121286', 'area': '647500.0'}

...

Eliminar elementos

Eliminar elementos es sencillo. Solo hay que aplicar la función drop a un selector:

selector.css(".my_class").drop()

Veamos cómo funciona esta funcionalidad escribiendo un script que elimine el campo «población» de cada país:

import parsel

import requests

response = requests.get("https://www.scrapethissite.com/pages/simple/")

raw_html = response.text

parsel_dom = parsel.Selector(text=raw_html)

countries = parsel_dom.css(".country")

for country in countries:

 country.css(".country-population").drop()

 country.xpath(".//strong")[1].drop()

 country.xpath(".//br")[1].drop()

countries_without_population_html = parsel_dom.get()

with open("out.html", "w", encoding="utf-8") as f:

  f.write(countries_without_population_html)

Exportar los datos

Cuando hayas terminado de extraer los datos, es importante pensar en cómo quieres guardarlos. Dos formatos habituales para almacenar este tipo de datos son .json y .csv. Sin embargo, debes elegir el que mejor se adapte a las necesidades de tu proyecto.

Exportar los datos a .json

JSON (JavaScript Object Notation) es un formato ligero de intercambio de datos que resulta fácil de leer y escribir para las personas, y fácil de analizar y generar para las máquinas. Se utiliza a menudo para intercambiar datos entre una aplicación web y un servidor, o entre diferentes partes de una aplicación web. JSON es similar a un diccionario de Python, ya que se utiliza para almacenar datos en pares clave-valor, y puede utilizarse para almacenar y acceder al mismo tipo de datos y tener la misma estructura.

La exportación de una matriz de diccionarios de Python a .json se puede realizar con la biblioteca json:

import json

countries_dictionaries = [

{'name': 'Andorra', 'capital': 'Andorra la Vella', 'population': '84000', 'area': '468.0'},

{'name': 'United Arab Emirates', 'capital': 'Abu Dhabi', 'population': '4975593', 'area': '82880.0'}

]

json_data = json.dumps(countries_dictionaries, indent=4)

with open("data.json", "w") as outfile:

   outfile.write(json_data)

// data.json

[

   {

       "name": "Andorra",

       "capital": "Andorra la Vella",

       "population": "84000",

       "area": "468.0"

   },

   {

       "name": "United Arab Emirates",

       "capital": "Abu Dhabi",

       "population": "4975593",

       "area": "82880.0"

   }

]

Exportación de datos a .csv

Un CSV es una forma sencilla de almacenar datos en un archivo de texto, donde cada línea representa una fila y cada valor está separado por una coma. Se utiliza a menudo en hojas de cálculo o programas de bases de datos. Python cuenta con un excelente soporte integrado para trabajar con archivos CSV, a través de su módulo csv. Una de las características más potentes del módulo CSV es la clase DictWriter, que permite escribir un diccionario de Python en un archivo CSV de forma sencilla. Las claves del diccionario se utilizarán como encabezados de columna en el archivo CSV, y los valores se escribirán como los datos correspondientes en las filas.

A continuación se muestra cómo se puede utilizar la biblioteca csv para exportar una matriz de diccionarios de Python a un archivo .csv.

countries_dictionaries = [

{"name": "John Smith", "age": 35, "city": "New York"},

{"name": "Jane Doe", "age": 28, "city": "San Francisco"}

]

with open("data.csv", "w") as outfile:

   writer = csv.DictWriter(outfile, fieldnames=countries_dictionaries[0].keys())

   writer.writeheader()

   for row in countries_dictionaries:

       writer.writerow(row)

// data.csv

name,age,city

John Smith,35,New York

Jane Doe,28,San Francisco

Conclusión

En este artículo, hemos explorado el uso de la biblioteca Parsel en Python. Hemos visto lo fácil que es utilizar los selectores CSS y XPath que ofrece Parsel para extraer datos de páginas web. En general, Parsel proporciona una solución eficiente y versátil para el web scraping. Si te interesa automatizar la recopilación de datos, sin duda deberías probarla.

¿Quieres saber más sobre el web scraping? Echa un vistazo a nuestro producto, WebScrapingAPI, y descubre cómo puedes llevar tus habilidades de extracción de datos al siguiente nivel. Nuestra potente API está diseñada específicamente para ayudarte a superar los retos más comunes del web scraping, como evitar bloqueos de IP o renderizar Javascript. ¿Y lo mejor de todo? ¡Puedes probarla gratis!

Acerca del autor
Mihai Maxim, Desarrollador Full Stack @ WebScrapingAPI
Mihai MaximDesarrollador Full Stack

Mihai Maxim es desarrollador full stack en WebScrapingAPI, donde colabora en todas las áreas del producto y ayuda a crear herramientas y funciones fiables para la plataforma.

Empieza a crear

¿Estás listo para ampliar tu recopilación de datos?

Únete a más de 2000 empresas que utilizan WebScrapingAPI para extraer datos de la web a escala empresarial sin ningún gasto de infraestructura.