Pular para o conteúdo

Exemplos

Alguns exemplos, apresentados nesta página, foram feitos pelos alunos do BSI na disciplina que trabalhou com raspagem de dados.

  • Exemplo: O objetivo de um programa Web Scraper é fazer um rastreamento exaustivo de um site. Ele começa com uma página de nível superior e pesquisa todos os links internos do site. Este tipo de programa pode coletar informações para:
    1. Gerar um mapa do site – rastrear links internos, seções, organizações das páginas, etc
    2. Coletar dados – fazer uma pesquisa especializada (criar rastreadores que percorrem recursivamente um site e coletar apenas os dados encontrados nas páginas)

     O programa apresentado a seguir é um Web Scraper para o site oficial do Python. Dois arquivos são gravados: o “arq_urls.txt” com os links das páginas do site que não tiveram problemas ao fazer conexão (exceto objetos pdf e png); e o “arq_erro.txt” com os links que deram erro ao tentar a conexão.

from bs4 import BeautifulSoup as bs
import requests, re
paginas  = set()
arq_urls = open("arq_urls.txt","w")
arq_erro = open("arq_erro.txt", "w")

def getLinks(URL):
   global paginas
   try:
      PagAtual = requests.get(URL)
   except Exception as erro:
      arq_erro.write(URL + "\n")
      arq_erro.write(str(erro) + "\n\n")
      arq_erro.flush()
   else:
      arq_urls.write(URL + "\n")
      arq_urls.flush()
      resposta = bs(PagAtual.text, 'html.parser')
      for link in resposta.findAll("a", href=re.compile(r'python\.org')):
         NovaPagina = link.attrs['href']
         pdf = re.search(".pdf", NovaPagina)
         png = re.search(".png", NovaPagina)
         if not pdf and not png:      
            if NovaPagina not in paginas:
               paginas.add(NovaPagina)
               getLinks(NovaPagina)
                      
getLinks("https://www.python.org/")
arq_urls.close()
arq_erro.close()

     As primeiras linhas do arquivo “arq_urls.txt”:

https://www.python.org/
https://docs.python.org
https://www.python.org/
https://docs.python.org/3/license.html
https://www.python.org/psf/
https://www.python.org/psf/donations/matching-gifts/
https://wiki.python.org/moin/BeginnersGuide

     As primeiras linhas do arquivo “arq_erro.txt”:

//devguide.python.org/_/downloads/en/latest/htmlzip/
Invalid URL '//devguide.python.org/_/downloads/en/latest/htmlzip/': No scheme supplied. Perhaps you meant http:////devguide.python.org/_/down
loads/en/latest/htmlzip/?

//devguide.python.org/_/downloads/en/latest/epub/
Invalid URL '//devguide.python.org/_/downloads/en/latest/epub/': No scheme supplied. Perhaps you meant http:////devguide.python.org/_/downloa
ds/en/latest/epub/?

mailto:python-dev@python.org
No connection adapters were found for 'mailto:python-dev@python.org'
  • Exemplo: o script acessa o site do Portal da Transparência e extrai os dados de 2021 das duas tabelas que aparecem no início da página do Ministério da Educação.
# 
# Projeto Final - Orçamento do MEC e Universidades Públicas Federais
## Aluno: Matheus Zaiat C. Gomes (20182210007)
## Bacharelado em Sistemas de Informação - UNIRIO (RJ)
#
import requests
import bs4
import csv

headers = {'User-agent': 'Mozilla/5.0'}
site = 'https://www.portaltransparencia.gov.br/orgaos-superiores/26000?ano=2021'  # ano de 2021
r = requests.get(site, headers=headers)
pagina = bs4.BeautifulSoup(r.content, "html.parser",  from_encoding='utf-8')

# Captura as despesas totais (primeira tabela)
# Grava no arquivo "pagamentos.csv"
tabela  = pagina.findAll("table")[0]
celulas = tabela.findAll(['td', 'th'])
with open("pagamentos.csv", "wt+", newline="") as f:
    writer = csv.writer(f, delimiter = ";")
    csv_linha = [] 
    for celula in celulas:
       csv_linha.append(celula.text)
    writer.writerow(csv_linha)
    writer.writerow("")

# Captura a distribuição dos pagamentos (segunda tabela)
# Grava no arquivo "pagamentos.csv"
tabela = pagina.findAll("table")[1]
linhas = tabela.findAll("tr")
with open("pagamentos.csv", "at+", newline="") as f:
    writer = csv.writer(f, delimiter = ";")
    for linha in linhas:
        csv_linha = [] 
        for cell in linha.findAll(["td", "th"]):
            csv_linha.append(cell.get_text()) # colocando cada célula na linha do arquivo
        writer.writerow(csv_linha)

O arquivo “pagamentos.csv” possui o seguinte conteúdo:

"
Despesas previstas (orçamento atualizado)
145.696.563.762,00
";"
Despesas executadas do orçamento
 123.428.612.288,65
";"
Este valor equivale a
3.37%
dos gastos públicos
"

Tipo de pagamento;Valor;Percentual relativo ao todo
Pagamentos referentes ao orçamento próprio (despesas previstas);R$ 124.384.835.638,97;98.14%
Pagamentos referentes ao orçamento de terceiros;R$ 2.361.800.165,92;1.86%
Total de pagamentos realizados;R$ 126.746.635.804,89;100,00%

Acessando o arquivo com uma planilha, pode-se ver:

  • Exemplo: o programa abaixo fornece as emendas parlamentares de um determinado ano para uma Universidade Pública Federal. Os dados são extraídos do Portal da Transparência. Por exemplo, para obter as emendas parlamentares da UNIRIO (Órgão 26269) no ano de 2018, salve o código abaixo como emendas.py e digite na linha de comandos:

          python emendas.py 2018 26269

#
# Projeto Final - Emendas Parlamentares das Universidades Públicas Federais
## Aluna: Laryssa Castro Rangel (20181210010)
## Bacharelado em Sistemas de Informação - UNIRIO (RJ)
#
from numpy import ScalarType
from pandas.core.arrays.categorical import contains
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.firefox.options import Options as FirefoxOptions
import requests
import pandas as pd
import time
import sys

# Códigos das Universidades Públicas Federais
universidades = [26230, 26231, 26232, 26233, 26234, 26235, 26236, 26237, 26238, 26239,
                 26240, 26241, 26242, 26243, 26244, 26245, 26246, 26247, 26248, 26249, 
                 26250, 26251, 26252, 26253, 26254, 26255, 26258, 
                 26260, 26261, 26262, 26263, 26264, 26266, 26267, 26268, 26269, 
                 26270, 26271, 26272, 26273, 26274, 26275, 26276, 26277, 26278, 26279, 
                 26280, 26281, 26282, 26283, 26284, 26285, 26286, 
                 26350, 26351, 26352, 26440, 26441, 26442, 26447]

if len(sys.argv) < 3:
   print("Forneça o ano com 4 dígitos e o código do órgão")
else:
   ano   = int(sys.argv[1])
   orgao = int(sys.argv[2])
   from datetime import date
   data_atual = date.today()
   ano_atual  = data_atual.year
   if ano > ano_atual:
      print("Ano deve ser menor que", ano_atual + 1)
      quit()
   if orgao not in universidades:
      print("Órgão não é de uma Universidade Pública Federal:", orgao)
      quit()
   
options = FirefoxOptions()
options.add_argument("--headless") #Realiza o teste sem abrir a janela do navegador
driver = webdriver.Firefox(options=options)
url_pesq = "http://www.portaltransparencia.gov.br/despesas/orgao/consulta?paginacaoSimples=true&tamanhoPagina=&offset=&direcaoOrdenacao=asc&de=01%2F01%2F" + str(ano) + "&ate=31%2F12%2F" + str(ano) + "&orgaos=OR" + str(orgao) + "&localidadeGasto=ET19&planoOrcamentario=8600018&colunasSelecionadas=mesAno%2CorgaoVinculado%2CunidadeGestora%2Cprograma%2Cacao%2Cautor%2CgrupoDespesa%2CvalorDespesaEmpenhada%2CvalorDespesaLiquidada%2CvalorDespesaPaga%2CvalorRestoPago"

def lista_emendas(url):
    driver.get(url)
    #Utilizando o pandas, cria um dataframe vazio
    df_final = pd.DataFrame()
    while True:
        # Tempo para carregar a página para que as informações da tabela apareçam
        time.sleep(2)
        # Identifica a classe que determina existência de próxima página
        next_page_btn = driver.find_elements(By.XPATH, "//li[@class = 'paginate_button next']/a")
        # Mostra todo o conteúdo da tabela
        pd.set_option('display.max_columns', None) 
        pd.set_option('display.max_rows', None)
        # Busca a tabela
        element = driver.find_element(By.XPATH, '//*[@id="lista"]')
        # Pega o conteúdo html da tabela
        html_content = element.get_attribute('outerHTML')
        # Extrai o conteúdo da tabela sem tags HTML
        df_full  = pd.read_html( str(html_content))[0]
        # Adiciona a tabela da página ao dataframe
        df_final = df_final.append(df_full, ignore_index = True)
        # Se não houver mais próxima página, interromper
        if len(next_page_btn) < 1:
            break
        else:
            # Clica no botão que leva para a próxima página
            driver.find_element(By.ID, 'lista_next').click()
    driver.quit()
    return df_final

# Gera um arquivo csv com as listas 
nome = "emendas" + str(ano) + ".csv"
arq  = open(nome, "w")
lista_emendas(url_pesq).to_csv(arq, index=False, encoding="utf-8", sep=';')
arq.close()

     As primeiras linhas do arquivo CSV são mostradas abaixo.

     O arquivo aberto pela planilha corresponde à figura abaixo.