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:
- Gerar um mapa do site – rastrear links internos, seções, organizações das páginas, etc
- 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.
