1. O formato CSV

O que é um CSV? Trata-se de uma forma de traduzir uma tabela em uma string. Tabelas são estruturas bidimensionais, que organizam dados segundo uma estrutura fixa, baseada na existência de um número finito de linhas e de colunas. Nessas tabelas, cada valor é arquivado em uma célula específica, cujo endereço corresponde a uma combinação de coluna + linha.

Nos modelos de dados que usamos (ou seja, na forma que usamos para organizar os dados de maneira estruturada), cada linha corresponde a uma unidade de análise (processo, relator, decisão, etc) e cada coluna corresponde a um atributo desse objeto (nome, numero, data de ajuizamento, tipo de decisão, etc.). Nas tabelas, a primeira linha costuma indicar os nomes dos atributos, sendo por isso chamada de cabeçalho (head), mas isso não é necessário, pois, desde que você saiba quais são os atributos mapeados, o nome é dispensável.

Isso significa que a tabela tem uma estrutura bidimensional do tipo:

Uma estrutura csv  representa uma forma de traduzir essa bidimensionalidade para uma string única, como a que aparece no texto:

Nesse caso, não existe uma divisão explícita de colunas, mas ocorre um aparente emplilhamento de várias linhas que têm a mesma estrutura, sendo que as vírgulas servem como marcadores de distinguem os vários elementos justapostos em cada linha. A sensação de emplilhamento decorre do fato de que os editores em geral (Bloco de Notas, Word e mesmo o editor interno do Spyder) plota na tela cada marca de parágrafo como uma quebra de linha, mas essa é só uma questão de visualização. Quando carregamos esse arquivo para o Python, a string que obtemos é:

'Atributo1:Nome,Atributo2:Origem,Atributo3:Relator,Atributo4:DataDeIngresso,Atributo5:TempoDeTramitação\nValor(string),Valor(string),Valor(string),Valor:(data),Valor:(int)\nValor(string),Valor(string),Valor(string),Valor:(data),Valor:(int)\nValor(string),Valor(string),Valor(string),Valor:(data),Valor:(int)\nValor(string),Valor(string),Valor(string),Valor:(data),Valor:(int)\n'

A quebra de linha é representada pelo '\n' e, com isso, é possível traduzir uma tabela para uma string, que pode ser reconvertida para uma tabela por instrumentos adequados de leitura.

2. Gravando em formato

Aparentemente, seria fácil ir escrevendo os dados com o nosso módulo de gravação, apenas usando a função adicionar. Porém, a função write somente admite como arqumento strings, o que não nos permite uma gestão adequada das quebras de linha nem nos permite gravar diretamente uma lista com as variáveis.

É justamente esse o papel da biblioteca csv, que está na base da função que definimos, e que tem duas funções que nos interessam. Foi com base nela que criamos as funções de escrever cabeçalho e linhas, no módulo dsd.py.

  1. A função csv.writer transforma o elemento aberto pela função open (cujo conteúdo é do tipo TextIOWrapper) em um outro tipo de elemento (do tipo writer), que admite a gravação de listas (e não apenas de strings).
  2. A função writerow, que realiza a gravação de uma lista (ou de strings), seguida por uma quebra de linha, o que gera um arquivo CSV.

O código dos módulos de gravação é semelhante, e por isso coloco ambos lado a lado para serem visíveis as diferenças.

    # Módulo básico de gravação
    nomedoarquivo = 'ADIhtml\\ADI' + NumProcesso + '.html'
    arquivoaberto = open(nomedoarquivo, 'w', encoding='utf-8')
    arquivoaberto.write(url)
    arquivoaberto.close()
Módulo básico de gravação
    ### gravação dos dados em csv
    nomedoarquivo = "ADI.csv"
    arquivoaberto = open(nomedoarquivo, mode='a+', encoding="utf-8", newline='')
    arquivoaberto_csv = csv.writer(arquivoaberto, delimiter=',')
    arquivoaberto_csv.writerow(dados)        
    arquivoaberto.close()

Observando as diferenças entre ambos, você deve notar alguns pontos relevantes:

  1. a necessidade de importar a biblioteca csv, para poder usar o comando csv.writer;
  2. o mode da função open deve ser "a" (adicionar) ou "a+" (adicionar ou ler);
  3. sem o parâmetro newline="", o writerow insere um comando que o Excel interpreta como uma linha extra vazia em cada gravação;
  4. usamos o writerow em vez do write, para poder gravar a lista com os conteúdos dos atributos de cada processo.