Introdução
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 diversos fins, tais como investigação, análise de dados ou análise de mercado.
Hoje em dia, existem inúmeras soluções para a extração de dados da Web com Python. O Selenium e o Scrapy são algumas das bibliotecas mais utilizadas e populares. Embora estas ferramentas sejam excelentes para tarefas complexas de extração de dados, podem revelar-se um pouco complicadas para uma utilização ocasional.
Apresentamos o Parsel, uma pequena biblioteca de scraping. Esta biblioteca leve e fácil de aprender é perfeita para projetos de pequena dimensão e é ideal para quem está a dar os primeiros passos no scraping na Web. É 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.
Apertem os cintos e preparem-se para aprender a usar esta biblioteca enquanto me acompanham nesta aventura de recolha automatizada de dados. Vamos começar a extrair dados!
Introdução ao Parsel
Pode instalar a biblioteca Parsel com:
pip install parsel
Vamos agora passar diretamente a um projeto de exemplo e extrair todos os dados relativos aos países deste site simples: https://www.scrapethissite.com/pages/simple/.
Para obter o código HTML do site, terá de efetuar um pedido HTTP GET.
Vamos efetuar pedidos HTTP com a biblioteca «requests» do Python, por isso certifique-se de que a instala com:
pip install requests
Agora pode obter o código HTML e guardá-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 analise a estrutura:

Os nossos dados sã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 código HTML bruto ao 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 utilizando 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)
// Resultado
Andorra-a-Velha
parsel_dom.css(".country-capital::text").get() selecionará o texto interno do primeiro elemento que tenha a classe "country-capital".
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())
// Resultado
Andorra
Emirados Árabes Unidos
Afeganistão
Antígua e Barbuda
Anguilla
. . .
parsel_dom.css(".country-name::text").getall() irá selecionar os textos internos de todos os elementos que tenham a classe "country-name".
Notice that we had to clean-up the output a bit. We did that because all the elements that have the “.country-name” class also have an <i> tag nested inside of them. Also, the country name is surrounded by many trailing spaces.
<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 utilizando seletores XPath
O XPath é uma linguagem de consulta para selecionar nós de um documento XML. É a sigla de 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, disponível em https://www.webscrapingapi.com/the-ultimate-xpath-cheat-sheet.
Agora vamos experimentar alguns seletores:
Veja 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)
// Resultado
Andorra-a-Velha
E todos os nomes dos 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())
// Saída
Andorra-a-Velha
Abu Dhabi
Cabul
St. John's
The Valley
Tirana
...
Vamos reescrever o script utilizando 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 remova 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 na forma como pretende guardá-los. Dois formatos comuns para armazenar este tipo de dados são o .json e o .csv. No entanto, deve escolher aquele que melhor se adequa às necessidades do seu projeto.
Exportar os dados para o formato .json
O JSON (JavaScript Object Notation) é um formato leve de intercâmbio de dados, fácil de ler e escrever para os utilizadores e fácil de analisar e gerar para as 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.
É possível exportar uma matriz de dicionários Python para o formato .json utilizando 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 um ficheiro .csv
Um CSV é uma forma simples de armazenar dados num ficheiro de texto, em que cada linha representa uma entrada e cada valor é separado por uma vírgula. É frequentemente utilizado em programas de folhas de cálculo ou bases de dados. O Python possui 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 gravar 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 um ficheiro .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 FranciscoConcluir
Neste artigo, explorámos a utilização da biblioteca Parsel em Python. Vimos como é fácil utilizar os seletores CSS e XPath que a Parsel disponibiliza para extrair dados de páginas web. Em geral, a 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á-la.
Quer saber mais sobre web scraping? Conheça o nosso produto, o WebScrapingAPI, e descubra como pode levar as suas competências em 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 a execução de Javascript. E o melhor de tudo? Pode experimentá-la gratuitamente!




