Voltar ao blogue
Guias
Mihai MaximLast updated on Mar 31, 20265 min read

Parsel: Como extrair texto de HTML em Python

Parsel: Como extrair texto de HTML em Python

Introdução

Web scraping é o processo automatizado de recolha de dados de sites através da utilização de um script ou programa. É utilizado para extrair informações como texto, imagens e outros tipos de dados que podem ser úteis para diferentes fins, como investigação, análise de dados ou análise de mercado.

Hoje em dia, existem inúmeras soluções quando se trata de web scraping com Python. Selenium e Scrapy são algumas das bibliotecas mais utilizadas e populares. Embora estas ferramentas sejam ótimas para tarefas complexas de scraping, podem ser um pouco intimidantes para uma utilização ocasional.

Conheça o Parsel, a pequena biblioteca de scraping. Esta biblioteca leve e fácil de aprender é perfeita para pequenos projetos e é ótima para quem está a dar os primeiros passos no web scraping. É capaz de analisar HTML e extrair dados utilizando seletores CSS e XPath, tornando-a uma excelente ferramenta para qualquer entusiasta de dados que procure uma forma rápida e fácil de recolher informações da web.

Aperta o cinto e prepara-te para aprender a usar esta biblioteca enquanto te juntas a mim nesta aventura de recolha automatizada de dados. Vamos ao scraping!

Introdução ao Parsel

Pode instalar a biblioteca Parsel com:

pip install parsel

Agora vamos mergulhar diretamente num projeto de exemplo e extrair todos os dados dos países deste site simples https://www.scrapethissite.com/pages/simple/.

Para obter o HTML do site, terá de fazer um pedido HTTP GET.

Iremos efetuar pedidos HTTP com a biblioteca Python “requests”, por isso certifique-se de que a instala com:

pip install requests

Agora pode obter o HTML e gravá-lo num ficheiro:

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)

E examinar a estrutura:

Os nossos dados estão armazenados em estruturas semelhantes 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 escrever seletores, terá de passar o HTML bruto para o 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)

Agora estamos prontos para escrever alguns seletores.

Extrair texto usando seletores CSS

Pode imprimir a capital do primeiro país com:

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.

Pode imprimir todos os nomes dos países com:

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.

Repara que tivemos de limpar um pouco a saída. Fizemos isso porque todos os elementos que têm a classe «.country-name» também têm uma tag <i> aninhada no seu interior. Além disso, o nome do país está rodeado por muitos espaços à direita.

<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>

Agora vamos escrever um script para extrair todos os dados com seletores 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'}

... 

Extrair texto usando seletores XPath

O XPath é uma linguagem de consulta para selecionar nós de um documento XML. Significa XML Path Language e utiliza uma notação de caminho semelhante à dos URLs para navegar pelos elementos e atributos de um documento XML. As expressões XPath podem ser utilizadas para selecionar um único elemento, um conjunto de elementos ou um atributo específico de um elemento. O XPath é utilizado principalmente em XSLT, mas também pode ser utilizado para navegar pelo Modelo de Objetos de Documento (DOM) de qualquer documento em linguagem semelhante a XML, como HTML ou SVG.

O XPath pode parecer intimidante à primeira vista, mas na verdade é bastante fácil começar a utilizá-lo assim que se compreendem os conceitos básicos e a sintaxe. Um recurso que pode ser útil é o nosso guia de seletores XPath em https://www.webscrapingapi.com/the-ultimate-xpath-cheat-sheet.

Agora vamos experimentar alguns seletores:

Eis como pode imprimir a primeira letra maiú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

E todos os nomes 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

...

Vamos reimplementar o script com seletores 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'}

...

Remover elementos

Remover elementos é simples. Basta aplicar a função drop a um seletor:

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

Vamos demonstrar esta funcionalidade escrevendo um script que remove o campo “população” 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 os dados

Quando terminar de extrair os dados, é importante pensar em como os quer guardar. Dois formatos comuns para armazenar este tipo de dados são .json e .csv. No entanto, deve escolher aquele que melhor se adequa às necessidades do seu projeto.

Exportar os dados para .json

JSON (JavaScript Object Notation) é um formato leve de intercâmbio de dados, fácil de ler e escrever para humanos e fácil de analisar e gerar para máquinas. É frequentemente utilizado para a troca de dados entre uma aplicação web e um servidor, ou entre diferentes partes de uma aplicação web. O JSON é semelhante a um dicionário Python, na medida em que é utilizado para armazenar dados em pares chave-valor, e pode ser utilizado para armazenar e aceder ao mesmo tipo de dados e ter a mesma estrutura.

A exportação de uma matriz de dicionários Python para .json pode ser feita com a 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"

   }

]

Exportar os dados para .csv

Um CSV é uma forma simples de armazenar dados num ficheiro de texto, onde cada linha representa uma coluna e cada valor é separado por uma vírgula. É frequentemente utilizado em programas de folhas de cálculo ou bases de dados. O Python tem um excelente suporte integrado para trabalhar com ficheiros CSV, através do seu módulo csv. Uma das funcionalidades mais poderosas do módulo CSV é a classe DictWriter, que permite escrever um dicionário Python num ficheiro CSV de forma simples. As chaves do dicionário serão utilizadas como cabeçalhos de coluna no ficheiro CSV, e os valores serão gravados como os dados correspondentes nas linhas.

Veja aqui como pode utilizar a biblioteca csv para exportar uma matriz de dicionários Python para .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

Conclusão

Neste artigo, explorámos a utilização da biblioteca Parsel em Python. Vimos como é fácil utilizar os seletores CSS e XPath que o Parsel fornece para extrair dados de páginas web. No geral, o Parsel oferece uma solução eficiente e versátil para a extração de dados da web. Se estiver interessado em automatizar a recolha de dados, deve definitivamente experimentá-lo.

Quer saber mais sobre web scraping? Conheça o nosso produto, WebScrapingAPI, e descubra como pode levar as suas competências de extração de dados para o próximo nível. A nossa poderosa API foi especificamente concebida para o ajudar a superar os desafios mais comuns do web scraping, como evitar bloqueios de IP ou renderizar Javascript. E a melhor parte? Pode experimentá-la gratuitamente!

Sobre o autor
Mihai Maxim, Desenvolvedor Full Stack @ WebScrapingAPI
Mihai MaximDesenvolvedor Full Stack

Mihai Maxim é um programador Full Stack na WebScrapingAPI, contribuindo em todas as áreas do produto e ajudando a criar ferramentas e funcionalidades fiáveis para a plataforma.

Comece a construir

Pronto para expandir a sua recolha de dados?

Junte-se a mais de 2.000 empresas que utilizam a WebScrapingAPI para extrair dados da Web à escala empresarial, sem quaisquer custos de infraestrutura.