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 FranciscoConclusã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!




