Apesar do uso cada vez mais difundido das API (“Application Programming Interface”) para obter dados via internet, ainda é comum a disponibilização de dados através de tabelas em arquivos de planilhas (do tipo Microsoft Excel ou mesmo HTML). Já foram publicadas rotinas em shell script e script em R para abrir arquivos no formato XLS(X) para extrair informações disponíveis nos arquivos para uso interno ou gravar a saída em um arquivo CSV.
Os scripts a seguir foram escritos em python para baixar um arquivo HTML (ou XLSX) e extrair as informações. Como exemplo, são usados arquivos do ONS, com o objetivo de extrair os nomes dos reservatórios e valores dos volumes úteis.
Primeiramente, deve-se montar o link a ser consultado, recebendo data e número do subsistema, assim como o nome do arquivo a ser gravado no computador. Para baixar o arquivo, é usada a biblioteca “urllib“.
O script a seguir baixa uma arquivo HTML e seu conteúdo é interpretado pela biblioteca “BeautifulSoup“. Outro exemplo de uso dessa lib pode ser visto no post Leitura automática de páginas com envio de informações. A função “findAll” busca por tags HTML, podendo restringir por seus atributos (como “id” ou “class”). Ao encontrar uma tabela (tag “table”), as linhas (“tr”, de “table row”) e células (“td” ou “th”, de “table head”) podem ser selecionadas por colunas.
#!/usr/bin/python # -*- coding: utf-8 -*- import os from datetime import datetime import urllib from bs4 import BeautifulSoup path = os.path.dirname(os.path.realpath(__file__)) # Montar link #data = "{:%Y_%m_%d}".format(datetime.now()) data = '2018_09_01' sub = 24 link = "http://sdro.ons.org.br/SDRO/DIARIO/%s/HTML/%s_SituacaoPrincipaisReservatorios_Regiao.html" %(data,sub) html_file = "%s/temp_ons/volume_util.html" %path # Baixar arquivo #testfile = urllib.URLopener() #testfile.retrieve(link, html_file) # Buscar valores por coluna soup = BeautifulSoup(open(html_file), "html.parser") table = soup.find("table", attrs={"id":"gridViewSituacaoPrincipaisReservatorios"}) # Busca somente nomes com restrições e guarda em vetor #names = soup.find_all('td', {'class' : 'fonte_itens_situacao_principais_reservatorios', 'style' : 'WIDTH: 120px' }) # Varrer tabela e imprimir conteúdo for row in soup.findAll('table')[0].tbody.findAll('tr'): #print(row) size = len(row.findAll('td')) if size > 0: first_column = row.findAll('td')[0].contents third_column = row.findAll('td')[2].contents else: first_column = row.findAll('th')[0].contents third_column = row.findAll('th')[2].contents print(first_column) print(third_column) print('------') #exit()
A variável “size” e a condicional a seguir foram feitas para o caso da célula ter a tag “td” ou “th”.
O segundo script baixa um arquivo do tipo XLSX, que é lido e interpretado diretamente pela biblioteca “pandas“, guardando os valores em um “dataframe”. Também foi incluído um loop para quatro valores diferentes de subsistemas.
#!/usr/bin/python # -*- coding: utf-8 -*- import os import urllib import pandas as pd path = os.path.dirname(os.path.realpath(__file__)) # Montar strings de datas data1 = '2018_10_13' data2 = '13-10-2018' # Loop de subsistemas: SE-24; S-23; NE-25; N-26 for sub in range(23,27): print(sub) # Montar link link = "http://sdro.ons.org.br/SDRO/DIARIO/%s/HTML/%s_SituacaoPrincipaisReservatorios_Regiao_%s.xlsx" %(data1, sub, data2) file_name = "%s/temp_ons/volume_util.xlsx" %path # Baixar arquivo testfile = urllib.URLopener() testfile.retrieve(link, file_name) # Ler arquivo para dataframe dfs = pd.read_excel(file_name) # Selecionar colunas com nome do reservatório e volume útil; da 5a linha pra frente df = dfs.iloc[5:, [1,4]] # Tirar linhas indefinidas #df = df.dropna() # Renomear colunas df.columns = ['reservatorio', 'vol_util'] # Gravar tabela em arquivo CSV - dar append se não for o primeiro subsistema file_out = "%s/temp_ons/volume_util_%s.csv" %(path,data1) if sub == 23: df.to_csv(file_out, index=False, encoding='utf-8') else: dff = pd.read_csv(file_out, encoding='utf-8') dff = dff.append(df) dff.to_csv(file_out, index=False, encoding='utf-8')
A condicional serve para criar um novo arquivo, se for o primeiro subsistema, ou para incluir os novos valores no final do arquivo já criado (sem o cabeçalho).
2 comments