Abrindo Arquivos de Texto#

Neste curso de mineração de textos usaremos como material principal de trabalho, os verbetes do Dicionário Histórico e Biográfico do Brasil – DHBB. Estes verbetes stão disponíveis para Download público.

Neste capítulo vamos aprender a interagir com os verbetes no disco e extrair informações simples a partir dos mesmos.

Vamos começar importando alguma bibliotecas que nos serão úteis nesta tarefa:

Hide code cell source
import warnings
warnings.filterwarnings('ignore')
import os
import glob
print("alô turma!")
alô turma!

Assumindo que os dados do DHBB já foram baixados para um diretório local, podemos começar inspecionando o diretório e listando o seu conteúdo.

# caminho = "F:/dhbb-master/text/*.text"
caminho = "../dhbb/text/*.text"
arquivos  = glob.glob(caminho)
len(arquivos)
7838

Temos 7838 verbetes neste diretório. Vamos agora ver como abrir um destes verbetes e inspecionar o seu conteúdo:

arquivos[0]
'../dhbb/text/4736.text'

Para abrir um arquivo utilizamos um bloco with.

with open(arquivos[0],'r', encoding='utf8') as arquivo_aberto:
    verbete = arquivo_aberto.read()
print(verbete)
---
title: RUBIM, Floriano
natureza: biográfico
sexo: m
cargos: 
 - militar
 - dep. fed. ES 1955-1959
 - dep. fed. ES 1963-1971
---

«Floriano Lopes Rubim» nasceu em Alegre (ES) no dia 18 de janeiro de
1912, filho de Francisco Lopes Rubim, funcionário público, e de Maria
Sílvia Lousada Rubim.

Bacharel em ciências jurídicas e sociais pela Faculdade de Direito da
Universidade do Espírito Santo, formou-se também na Escola de Educação
Física do Rio de Janeiro, então Distrito Federal, em 1941. Nesse mesmo
ano ingressou na Força Policial do Espírito Santo, onde faria carreira.
Participou da campanha militar brasileira na Itália durante a Segunda
Guerra Mundial (1939-1945), retornando ao Brasil em 1945, ao término do
conflito.

Em 1946 assumiu a direção da Penitenciária do Estado do Espírito Santo,
que ocupou até o ano seguinte. Em 1948 passou a ajudante-de-ordens na
Casa Militar do governador do Espírito Santo, Carlos Lindenberg
(1947-1951), função que exerceu até 1949. Em outubro de 1950 elegeu-se
deputado estadual pelo Espírito Santo, na legenda do Partido Trabalhista
Brasileiro (PTB). Para assumir o mandato, foi reformado na Força
Policial do estado no posto de coronel, ocupando a sua cadeira no
Legislativo em fevereiro de 1951. Nessa legislatura integrou as
comissões de Educação e Cultura e de Justiça da Assembléia capixaba.

Em outubro de 1954 elegeu-se deputado federal por seu estado, agora com
o apoio da Coligação Democrática formada pelo PTB e pelos partidos
Republicano (PR), de Representação Popular (PRP) e Social Progressista
(PSP). Encerrou o mandato estadual em janeiro de 1955, assumindo no mês
seguinte sua cadeira na Câmara Federal. Ocupou-a, no entanto, apenas de
2 a 9 de fevereiro, quando se licenciou para assumir a Secretaria de
Viação e Obras Públicas do Espírito Santo no governo de Francisco
Lacerda de Aguiar (1955-1959). Em abril reassumiu o mandato parlamentar
e, até o fim da legislatura, foi vice-presidente da Comissão de
Segurança Nacional da Câmara. Em maio de 1957, tornou-se vice-líder do
PTB. Em outubro de 1958 tentou a reeleição, na mesma legenda, mas obteve
apenas uma suplência. Concluiu o mandato em janeiro de 1959.

Em 1960, participou da campanha de Jânio Quadros para a presidência da
República, filiando-se ao Partido Democrata Cristão (PDC). No entanto,
no dia seguinte ao pleito realizado em outubro e vencido por Jânio,
desligou-se do PDC, filiando-se ao Partido Trabalhista Nacional (PTN).
Em outubro de 1962 voltou a se eleger deputado federal com o apoio da
coligação formada pelo PTN e o Partido Social Democrático (PSD). Assumiu
o mandato em fevereiro de 1963, tornando-se vice-líder do partido na
Câmara em junho do ano seguinte.

Com a edição do Ato Institucional nº 2 (AI-2), em 27 de outubro de 1965,
extinguindo os partidos políticos, e com a posterior implantação do
bipartidarismo, filiou-se à Aliança Renovadora Nacional (Arena), partido
de apoio ao regime militar instalado no país após a deposição do
presidente João Goulart em 31 de março de 1964.

Em novembro de 1966 reelegeu-se deputado federal pelo Espírito Santo, já
na legenda da Arena, exercendo o mandato de fevereiro de 1967 a janeiro
de 1971.

Fundou a Imexferral Ltda., empresa de sua propriedade.

Faleceu no dia 4 de maio de 1997.

Uma outra maneira de abrir um arquivo, seria como se segue, mas teríamos que usar uma linha de código a mais, para fechar o arquivo, que podemos economizar, lendo o arquivo dentro de um bloco with como fizemos anteriormente.

arquivo_aberto = open(arquivos[0], 'r', encoding='utf8')
verbete = arquivo_aberto.read()
arquivo_aberto.close()

A variável verbete que criamos na célula anterior é uma variável do tipo string, que é a otipo usado pelo Python para representar um bloco de texto. Podemos manipular o texto dentro de uma string de diversas maneiras:

type(verbete)
str
print(verbete.split('---')[1])
title: RUBIM, Floriano
natureza: biográfico
sexo: m
cargos: 
 - militar
 - dep. fed. ES 1955-1959
 - dep. fed. ES 1963-1971

Tipos de dados em Python, também conhecidos como objetos, possuem métodos. O método split do tipo string segmenta uma string nas posicões em que ocorram uma sequência específica de caracteres, retornando um outro tipo de dado, denominado lista.

type(verbete.split('---'))
list

Listas são sequências de objetos de quaisquer tipos que também apresentam seu conjunto de métodos. Para descobrir os métodos de qualquer objeto, basta colocar um ponto após o nome da variável e pressionar a tecla <tab>. Listas são delimitadas por colchetes: [] (lista vazia). Abaixo vamos dividir o verbete em uma lista de strings.

l = verbete.split('---')
l
['',
 '\ntitle: RUBIM, Floriano\nnatureza: biográfico\nsexo: m\ncargos: \n - militar\n - dep. fed. ES 1955-1959\n - dep. fed. ES 1963-1971\n',
 '\n\n«Floriano Lopes Rubim» nasceu em Alegre (ES) no dia 18 de janeiro de\n1912, filho de Francisco Lopes Rubim, funcionário público, e de Maria\nSílvia Lousada Rubim.\n\nBacharel em ciências jurídicas e sociais pela Faculdade de Direito da\nUniversidade do Espírito Santo, formou-se também na Escola de Educação\nFísica do Rio de Janeiro, então Distrito Federal, em 1941. Nesse mesmo\nano ingressou na Força Policial do Espírito Santo, onde faria carreira.\nParticipou da campanha militar brasileira na Itália durante a Segunda\nGuerra Mundial (1939-1945), retornando ao Brasil em 1945, ao término do\nconflito.\n\nEm 1946 assumiu a direção da Penitenciária do Estado do Espírito Santo,\nque ocupou até o ano seguinte. Em 1948 passou a ajudante-de-ordens na\nCasa Militar do governador do Espírito Santo, Carlos Lindenberg\n(1947-1951), função que exerceu até 1949. Em outubro de 1950 elegeu-se\ndeputado estadual pelo Espírito Santo, na legenda do Partido Trabalhista\nBrasileiro (PTB). Para assumir o mandato, foi reformado na Força\nPolicial do estado no posto de coronel, ocupando a sua cadeira no\nLegislativo em fevereiro de 1951. Nessa legislatura integrou as\ncomissões de Educação e Cultura e de Justiça da Assembléia capixaba.\n\nEm outubro de 1954 elegeu-se deputado federal por seu estado, agora com\no apoio da Coligação Democrática formada pelo PTB e pelos partidos\nRepublicano (PR), de Representação Popular (PRP) e Social Progressista\n(PSP). Encerrou o mandato estadual em janeiro de 1955, assumindo no mês\nseguinte sua cadeira na Câmara Federal. Ocupou-a, no entanto, apenas de\n2 a 9 de fevereiro, quando se licenciou para assumir a Secretaria de\nViação e Obras Públicas do Espírito Santo no governo de Francisco\nLacerda de Aguiar (1955-1959). Em abril reassumiu o mandato parlamentar\ne, até o fim da legislatura, foi vice-presidente da Comissão de\nSegurança Nacional da Câmara. Em maio de 1957, tornou-se vice-líder do\nPTB. Em outubro de 1958 tentou a reeleição, na mesma legenda, mas obteve\napenas uma suplência. Concluiu o mandato em janeiro de 1959.\n\nEm 1960, participou da campanha de Jânio Quadros para a presidência da\nRepública, filiando-se ao Partido Democrata Cristão (PDC). No entanto,\nno dia seguinte ao pleito realizado em outubro e vencido por Jânio,\ndesligou-se do PDC, filiando-se ao Partido Trabalhista Nacional (PTN).\nEm outubro de 1962 voltou a se eleger deputado federal com o apoio da\ncoligação formada pelo PTN e o Partido Social Democrático (PSD). Assumiu\no mandato em fevereiro de 1963, tornando-se vice-líder do partido na\nCâmara em junho do ano seguinte.\n\nCom a edição do Ato Institucional nº 2 (AI-2), em 27 de outubro de 1965,\nextinguindo os partidos políticos, e com a posterior implantação do\nbipartidarismo, filiou-se à Aliança Renovadora Nacional (Arena), partido\nde apoio ao regime militar instalado no país após a deposição do\npresidente João Goulart em 31 de março de 1964.\n\nEm novembro de 1966 reelegeu-se deputado federal pelo Espírito Santo, já\nna legenda da Arena, exercendo o mandato de fevereiro de 1967 a janeiro\nde 1971.\n\nFundou a Imexferral Ltda., empresa de sua propriedade.\n\nFaleceu no dia 4 de maio de 1997.\n\n']

Note que nas strings acima existem várias ocorrências da sequencia de caracteres '\n'. Esta sequência identifica quebra de linhas. Podemos então utilizá-la para dividir o cabeçalho do verbete em uma lista de linhas:

cabeçalho = verbete.split('---')[1]
cabeçalho.splitlines()
['',
 'title: RUBIM, Floriano',
 'natureza: biográfico',
 'sexo: m',
 'cargos: ',
 ' - militar',
 ' - dep. fed. ES 1955-1959',
 ' - dep. fed. ES 1963-1971']

Elementos de uma lista podem ser acessado por sua posição na sequência, por exemplo para acessar a 3ª string da lista:

print(l[2])
«Floriano Lopes Rubim» nasceu em Alegre (ES) no dia 18 de janeiro de
1912, filho de Francisco Lopes Rubim, funcionário público, e de Maria
Sílvia Lousada Rubim.

Bacharel em ciências jurídicas e sociais pela Faculdade de Direito da
Universidade do Espírito Santo, formou-se também na Escola de Educação
Física do Rio de Janeiro, então Distrito Federal, em 1941. Nesse mesmo
ano ingressou na Força Policial do Espírito Santo, onde faria carreira.
Participou da campanha militar brasileira na Itália durante a Segunda
Guerra Mundial (1939-1945), retornando ao Brasil em 1945, ao término do
conflito.

Em 1946 assumiu a direção da Penitenciária do Estado do Espírito Santo,
que ocupou até o ano seguinte. Em 1948 passou a ajudante-de-ordens na
Casa Militar do governador do Espírito Santo, Carlos Lindenberg
(1947-1951), função que exerceu até 1949. Em outubro de 1950 elegeu-se
deputado estadual pelo Espírito Santo, na legenda do Partido Trabalhista
Brasileiro (PTB). Para assumir o mandato, foi reformado na Força
Policial do estado no posto de coronel, ocupando a sua cadeira no
Legislativo em fevereiro de 1951. Nessa legislatura integrou as
comissões de Educação e Cultura e de Justiça da Assembléia capixaba.

Em outubro de 1954 elegeu-se deputado federal por seu estado, agora com
o apoio da Coligação Democrática formada pelo PTB e pelos partidos
Republicano (PR), de Representação Popular (PRP) e Social Progressista
(PSP). Encerrou o mandato estadual em janeiro de 1955, assumindo no mês
seguinte sua cadeira na Câmara Federal. Ocupou-a, no entanto, apenas de
2 a 9 de fevereiro, quando se licenciou para assumir a Secretaria de
Viação e Obras Públicas do Espírito Santo no governo de Francisco
Lacerda de Aguiar (1955-1959). Em abril reassumiu o mandato parlamentar
e, até o fim da legislatura, foi vice-presidente da Comissão de
Segurança Nacional da Câmara. Em maio de 1957, tornou-se vice-líder do
PTB. Em outubro de 1958 tentou a reeleição, na mesma legenda, mas obteve
apenas uma suplência. Concluiu o mandato em janeiro de 1959.

Em 1960, participou da campanha de Jânio Quadros para a presidência da
República, filiando-se ao Partido Democrata Cristão (PDC). No entanto,
no dia seguinte ao pleito realizado em outubro e vencido por Jânio,
desligou-se do PDC, filiando-se ao Partido Trabalhista Nacional (PTN).
Em outubro de 1962 voltou a se eleger deputado federal com o apoio da
coligação formada pelo PTN e o Partido Social Democrático (PSD). Assumiu
o mandato em fevereiro de 1963, tornando-se vice-líder do partido na
Câmara em junho do ano seguinte.

Com a edição do Ato Institucional nº 2 (AI-2), em 27 de outubro de 1965,
extinguindo os partidos políticos, e com a posterior implantação do
bipartidarismo, filiou-se à Aliança Renovadora Nacional (Arena), partido
de apoio ao regime militar instalado no país após a deposição do
presidente João Goulart em 31 de março de 1964.

Em novembro de 1966 reelegeu-se deputado federal pelo Espírito Santo, já
na legenda da Arena, exercendo o mandato de fevereiro de 1967 a janeiro
de 1971.

Fundou a Imexferral Ltda., empresa de sua propriedade.

Faleceu no dia 4 de maio de 1997.

Muitas vezes, as atrings podem vir acompanhadas de um ou mais espaços no ínicio ou no fim. Para removê-los podemos usar o método strip como exemplificado abaixo. Caso queiramos remover apenas os espaços no início ou no fim, podemos usar lstrip ou rstrip, respectivamente.

"   gjsldfkgj    ".strip()
'gjsldfkgj'

Um outro tipo de estrutura de dados fundamental no Python, é chamado um dicionário, e é denotado por um conjunto de pares de (chave: valor). Abaixo vamos construir um dicionário com os campos de um verbete.

campos = {l.split(':')[0].strip() :l.split(':')[1].strip() for l in cabeçalho.split('\n') if l and ':' in l}
campos
{'title': 'RUBIM, Floriano',
 'natureza': 'biográfico',
 'sexo': 'm',
 'cargos': ''}

No exemplo acima usamos um laço for para percorrer repetidamente o campos do cabeçalho e inseri-los um-a-um no dicionário, em apenas uma linha de código. esta maneira de prencher o dicionário é chamada de “dict comprehension”. Para entendermos melhor como funciona um laço for, e exatament a sequencia de operações realizada acima, vamos escrever “por extenso” o código acima.

campos = {}
for linha in cabeçalho.split('\n'):
    if linha and ':' in linha:
        chave, valor = linha.split(':')
        campos[chave.strip()] = valor.strip()

campos
{'title': 'RUBIM, Floriano',
 'natureza': 'biográfico',
 'sexo': 'm',
 'cargos': ''}

Exercícios#

Construa para 5 verbetes, um dicionário com o seguinte conteúdo: {"nome-do-cargo":"período"} para todos os cargos de cada verbetado.

def pega_cabeçalho(caminho, natureza):
    with open(caminho, 'r', encoding='utf8') as verb:
        cabeçalho = verb.read().split('---')[1]
    if natureza in cabeçalho:
        return cabeçalho
    else:
        return

respostas = []
for verbete in arquivos[10:18]:
    resposta = {}
    cabeçalho = pega_cabeçalho(verbete, 'biográfico')

    if cabeçalho is None:
        continue

    cargos = cabeçalho.split('cargos:')[1]
    lista_de_cargos = [cargo.strip('- ') for cargo in cargos.splitlines() if cargo.strip('- ') != ""]
    for cargo in lista_de_cargos:
        partes = cargo.split()
        if len(partes) > 1:
            per = partes[-1]
            nome = ' '.join(partes[:-1])
        else:
            nome = partes[0]
            per = "NA"
        resposta[nome] = per
    respostas.append(resposta)
#     print(cargos)
    print(resposta)
print(sum([1 for r in respostas if 'autor:' in r]))
{'empresário': 'NA', 'autor:': 'NA', 'Maria Ester Lopes': 'Moreira'}
{'dep. fed. TO': '2007'}
{'militar': 'NA', 'rev.': '1930', 'dep. fed. MG': '1959-1979'}
{'magistrado': 'NA', 'min. STF': '2003-2012', 'autor:': 'NA', 'Eduardo': 'Junqueira', 'Raimundo': 'Hélio'}
{'magistrada': 'NA', 'min. STF': '2006', 'pres. STF': '2016', 'autor:': 'NA', 'Eduardo': 'Junqueira', 'Raimundo': 'Hélio', 'Regina Hippolito': '(atualização)'}
{'dep. fed. PR': '1999'}
{'magistrado': 'NA', 'min. STF': '2006', 'autor:': 'NA', 'Eduardo': 'Junqueira'}
{'dep. fed. SC': '1971-1979'}
4

Na célula acima contruímos uma variável de tipo Dicionário, que é basicamente um conjunto de pares, delimitado por {}. Estes pares são chamados pares chave: valor, como dissemos anteriormente.

Modifique o código acima para criar outro dicionário com a seguinte estrutura:

{
    "nome": ["nome do verbetado", "nome do verbetado", ...],
    "cargo":[cargo 1, cargo2, ...],
    "início": [1987,1987, ...],
    "fim": [1988, 1991, ...]
}
import re
regex = re.compile('([0-9-]{4,5})')
cargo = " - emb. Itália no Brasil 1932-1937"
re.findall(regex,cargo)
['1932-', '1937']
import re
regex = re.compile('([0-9-]{4,5})')
resposta = {"nome": [], "cargo":[], "sexo":[], "inicio":[], "fim":[]}
for verbete in arquivos:
    cabeçalho = pega_cabeçalho(verbete, 'biográfico')
    if cabeçalho is None:
        continue
    cabeçalho = cabeçalho.split('autor:')[0]
    
    linhas = cabeçalho.splitlines()
    
    cargos = cabeçalho.split('cargos:')[1]
    lista_de_cargos = [cargo.strip('- ') for cargo in cargos.splitlines() if cargo.strip('- ') != ""]
    for cargo in lista_de_cargos:
        resposta['nome'].append([linha.split(':')[1].strip() for linha in linhas if linha.startswith('title:')][0])
        try:
            resposta['sexo'].append([linha.split(':')[1].strip() for linha in linhas if linha.startswith('sexo:')][0])
        except IndexError:
            resposta['sexo'].append('NA')
            print("sexo: ")
            print(cabeçalho)
        m = re.findall(regex,cargo)
        if m:
            corte = cargo.index(m[0])
            partes = (cargo[:corte], cargo[corte:])
        else:
            partes = [cargo]
        if len(partes) > 1:
            per = m
            nome = partes[0]
            try:
                resposta['inicio'].append(int(m[0].strip('-')))
            except ValueError: 
                resposta['inicio'].append('NA')
                #print("inicio:", per, per.split('-')[0])
                print(cabeçalho)
            if len(per)>1:
                try:
                    resposta['fim'].append(int(m[1]))
                except ValueError:
                    resposta['fim'].append("NA")
                    print("fim:", per, m[1])
            else:
                resposta['fim'].append("NA")
        else:
            nome = partes[0]
            resposta['inicio'].append("NA")
            resposta['fim'].append("NA")
        resposta['cargo'].append(nome.strip())
        

#     print(cargos)
   # print(resposta)
#print(sum([1 for r in resposta if 'autor:' in r]))
print(pega_cabeçalho(arquivos[3], 'biográfico'))
title: KRÜGER, Nivaldo
natureza: biográfico
sexo: m
cargos: 
 - dep. fed. PR 1979-1983
 - sen. PR 2002-2003

Abrindo um grande número de documentos texto#

Como vimos acima existem 7687 verbetes à nossa disposição no disco, mas não podemos abrir todos ao mesmo tempo pois, em primeiro lugar podem não caber na memória, em segundo lugar raramente precisaremos inpecioná-los todos ao mesmo tempo. O mais comum é analisá-los em sequência. Vamos inspecionar os primeiros 10:

for a in arquivos[:10]:
    with open (a, 'r', encoding='utf8') as f:
        verbete = f.readlines()
    print('Verbete: ', a.split('.text')[0].split('/')[-1])
    print(verbete[1])
Verbete:  4736
title: RUBIM, Floriano

Verbete:  1376
title: COELHO, Inocêncio Mártires

Verbete:  732
title: BOPP, Raul

Verbete:  2669
title: KRÜGER, Nivaldo

Verbete:  6310
title: POLÍTICA DE CLIENTELA

Verbete:  3752
title: NASCIMENTO, César

Verbete:  10928
title: COLA, Camilo

Verbete:  3756
title: NASCIMENTO, Paulo

Verbete:  41
title: ADEODATO, Francisco

Verbete:  11169
title: LIMA, Eliene
arquivos[1]
'../dhbb/text/1376.text'

Acima utilizamos uma estrutura de repetição, denominada “laço for” para abrir sequencialmente os arquivos. É importante notar que a cada volta do laço, o arquivo texo é atribuído à mesma variável, o que significa que nunca há mais do que apenas um verbete na memória. Desta forma poderíamos potencialmente analisar todos os milhares de verbetes ocupando apenas uma quantidade pequena e constante de memória. Outro detalhe do código acima é que, para facilitar a extração do título do verbete, Fizemos a leitura do arquivo com o método readlines que retorna o verbete já divido em uma lista de linhas ao invés de uma string.

Outros recursos do DHBB#

O arquivo do DHBB disponível no Github oferece outros recursos textuais para nos auxiliar em nossa pesquisa, como por exemplos dicionários com identificadores de “Entidades” presentes nos verbetes, como pessoas, organizações, eventos, etc.

with  open("../dhbb/dic/pessoa-individuo.txt", 'r', encoding='utf8') as f:
    pessoas = f.readlines()
pessoas[:10]
['Aarão Rebelo\n',
 'Aarão Steinbruch\n',
 'Abalcazar Garcia\n',
 'Abdias Do Nascimento\n',
 'Abdon Goncalves Nanhay\n',
 'Abdon Gonçalves\n',
 'Abdon Sena\n',
 'Abdon de Mello\n',
 'Abdur R. Khan\n',
 'Abel Avila dos Santos\n']
with  open("../dhbb/dic/pessoa-papel.txt", 'r', encoding='utf8') as f:
    profissão = f.readlines()
profissão[:10]
['Advogado\n',
 'Advogado Geral da União\n',
 'Agente de investimento\n',
 'Agente de segurança judiciária\n',
 'Alfaiate\n',
 'Analista administrativo\n',
 'Analista de comércio exterior\n',
 'Antiquário\n',
 'Arcebispo\n',
 'Armador\n']
with  open("../dhbb/dic/evento.txt", 'r', encoding='utf8') as f:
    evento = f.readlines()
evento[:10]
['A Rusga\n',
 'ATENTADO DA TONELEIROS\n',
 'ATENTADO DO RIOCENTRO\n',
 'Aclamação de Amador Bueno\n',
 'Balaiada\n',
 'Batalha da Maria Antônia\n',
 'Batalha da Venda Grande\n',
 'Batalha das Toninhas\n',
 'Batalha de Santa Luzia\n',
 'COMÍCIO DAS REFORMAS\n']
with  open("../dhbb/dic/organizacao.txt", 'r', encoding='utf8') as f:
    organização = f.readlines()
organização[:10]
['Abrigo Lar dos Velhos Vicentini\n',
 'Academia Alagoana de Letras\n',
 'Academia Brasileira de Ciências\n',
 'Academia Brasileira de Ciências Econômicas e Administrativas\n',
 'Academia Brasileira de Ciências Sociais e Políticas\n',
 'Academia Brasileira de Direito Empresarial\n',
 'Academia Brasileira de Letras\n',
 'Academia Brasileira de Música\n',
 'Academia Brasiliense de Letras\n',
 'Academia Cultural de Curitiba\n']
with  open("../dhbb/dic/formulacao-politica.txt", 'r', encoding='utf8') as f:
    politica = f.readlines()
politica[:10]
['anteprojeto Constitucional\n',
 'anteprojeto da Carta Magna\n',
 'anteprojeto da Comissão Provisória\n',
 'anteprojeto da Comissão Provisória de Estudos Constitucionais\n',
 'anteprojeto da Comissão de Sistematização\n',
 'anteprojeto da Consolidação das Leis do Trabalho\n',
 'anteprojeto da Constituição\n',
 'anteprojeto da Lei Orgânica da Magistratura\n',
 'anteprojeto da Lei de Acidentes no Trabalho\n',
 'anteprojeto da Lei de Direitos Autorais\n']

Extraindo Informação Estruturada#

Agora que sabemos como abrir arquivos de texto e ler o seu conteúdo, podemos experimentar a extração de imformações específicas dos verbetes e organizá-la em uma tabela. Para isso vamos lançar mão de uma biblioteca chamada Pandas para organizar em uma estrutura tabular, chamada DataFrame os dados que vamos extrair.

import pandas as pd
# pd.set_option("display.latex.repr", True)
%matplotlib inline

Nós vimos acima que os verbetes contém uma seção inicial delimitada pelos caracteres --- vamos utilizar esta característica do texto para guiar nossa extração de informação. Como você pode perceber, já começamos a reutilizar código que escrevemos anteriormente. Para facilitar o reuso e reduzir a necessidade de escrever múltiplas vezes o mesmo código vamos aprender a organizá-lo melhor. Vamos começar definindo uma função.

def tabula_verbete(n=None):
    """
    Carrega todos os verbetes disponíveis, ou os primeiros n.
    n:  número de verbetes a tabular
    """
    if n is None:
        n = len(arquivos)
    linhas = []
    for a in arquivos[:n]:
        with open (a, 'r', encoding='utf8') as f:
            verbete = f.read()
        cabeçalho = verbete.split('---')[1]
        campos = {l.split(':')[0].strip() :l.split(':')[1].strip() for l in cabeçalho.split('\n')[:4] if l}
        campos['arquivo'] = os.path.split(a)[1]
        campos['cargos'] = 'NA' if 'cargos:' not in cabeçalho else cabeçalho.split('cargos:')[1]
        campos['corpo'] = verbete.split('---')[2]
        linhas.append(campos)
    tabela = pd.DataFrame(data = linhas, columns=['arquivo','title', 'natureza', 'sexo', 'cargos', 'corpo'])
    return tabela

A função acima inclui a maior parte do código que escrevemos anteriormente, só que encapsulado em uma função que nos permite executar a extração e tabulação do cabeçalho para o numero de verbetes que desejarmos. Podemos ver abaixo que na verdade é muito rápido processar todos os verbetes.

help(tabula_verbete)
Help on function tabula_verbete in module __main__:

tabula_verbete(n=None)
    Carrega todos os verbetes disponíveis, ou os primeiros n.
    n:  número de verbetes a tabular
tab = tabula_verbete()
tab.head()
arquivo title natureza sexo cargos corpo
0 4736.text RUBIM, Floriano biográfico m \n - militar\n - dep. fed. ES 1955-1959\n - d... \n\n«Floriano Lopes Rubim» nasceu em Alegre (E...
1 1376.text COELHO, Inocêncio Mártires biográfico m \n - proc. ger. Rep. 1981-1985\nautor: \n - L... \n\n«Inocêncio Mártires Coelho» nasceu em Belé...
2 732.text BOPP, Raul biográfico m \n - diplomata\n - emb. Bras. Peru 1962-1963\n \n\n«Raul Bopp» nasceu em Santa Maria (RS) no ...
3 2669.text KRÜGER, Nivaldo biográfico m \n - dep. fed. PR 1979-1983\n - sen. PR 2002-... \n\n«Nivaldo Passos Krüger» nasceu em Canoinha...
4 6310.text POLÍTICA DE CLIENTELA temático NaN NA \n\nExpressão cunhada e conceito desenvolvido ...

Podemos visualizar uma descrição básica da tabela resultante

tab.describe()
arquivo title natureza sexo cargos corpo
count 7838 7838 7838 6865 7838 7838
unique 7838 7760 2 2 6189 7836
top 2058.text ALVES, José biográfico m NA \n\nPartido político que se habilitou junto ao...
freq 1 3 6865 6615 973 2

Por exemplo fica fácil ver que no DHBB predominam biografias de personagens do sexo masculino.

print(tab.sexo.value_counts())
sexo
m    6615
f     250
Name: count, dtype: int64
tab.sexo.hist();
_images/126bd81ebdd88f6cb1c71f48f1d0951cbedf8ad7b149c77552991f2436e56e50.png

Percebemos também que a natureza predominante dos verbetes é biográfica e que só existem duas naturezas, mas qua a outra?

print(tab.natureza.value_counts())
natureza
biográfico    6865
temático       973
Name: count, dtype: int64
tab2 = pd.DataFrame(resposta)
tab2.inicio = tab2.inicio.replace('NA', pd.NA)
tab2.fim = tab2.fim.replace('NA', pd.NA)
tab2.head()
nome cargo sexo inicio fim
0 RUBIM, Floriano militar m <NA> <NA>
1 RUBIM, Floriano dep. fed. ES m 1955 1959
2 RUBIM, Floriano dep. fed. ES m 1963 1971
3 COELHO, Inocêncio Mártires proc. ger. Rep. m 1981 1985
4 BOPP, Raul diplomata m <NA> <NA>
for c, v in resposta.items():
    print(c, len(v))
nome 15083
cargo 15083
sexo 15083
inicio 15083
fim 15083
tab2.dropna()
nome cargo sexo inicio fim
1 RUBIM, Floriano dep. fed. ES m 1955 1959
2 RUBIM, Floriano dep. fed. ES m 1963 1971
3 COELHO, Inocêncio Mártires proc. ger. Rep. m 1981 1985
5 BOPP, Raul emb. Bras. Peru m 1962 1963
6 KRÜGER, Nivaldo dep. fed. PR m 1979 1983
... ... ... ... ... ...
15075 MACIEL, Antunes dep. fed. RS m 1924 1927
15078 MACIEL, Antunes min. Just. m 1932 1934
15079 FOGAÇA, José dep. fed. RS m 1983 1987
15080 FOGAÇA, José const. m 1987 1988
15081 FOGAÇA, José sen. RS m 1987 2003

9893 rows × 5 columns

tab2[(['dep.' in c for c in tab2.cargo])&(tab2.inicio >1917)&(tab2.inicio<=2015)]
nome cargo sexo inicio fim
1 RUBIM, Floriano dep. fed. ES m 1955 1959
2 RUBIM, Floriano dep. fed. ES m 1963 1971
6 KRÜGER, Nivaldo dep. fed. PR m 1979 1983
8 NASCIMENTO, César dep. fed. SC m 1973 1975
9 NASCIMENTO, César dep. fed. SC m 1977 1980
... ... ... ... ... ...
15071 CORREIA, Hélio dep. fed. BA m 1983 1987
15073 MACIEL, Antunes dep. fed. RS m 1921 1923
15075 MACIEL, Antunes dep. fed. RS m 1924 1927
15076 MACIEL, Antunes dep. fed. RS m 1930 <NA>
15079 FOGAÇA, José dep. fed. RS m 1983 1987

6469 rows × 5 columns

tab2[(tab2.cargo.isin(['dep. fed. RJ', 'dep. fed. SP']))&(tab2.inicio==1991)]
#tab2.iloc[14825].cargo
nome cargo sexo inicio fim
91 MIGUEL, Sidnei de dep. fed. RJ m 1991 1995
212 ALMEIDA, Paulo de dep. fed. RJ m 1991 1995
520 BASTOS, Laerte dep. fed. RJ m 1991 1995
745 MELO, Euclides de dep. fed. SP m 1991 1995
923 VIEIRA, Laprovita dep. fed. RJ m 1991 1999
... ... ... ... ... ...
13587 MENDES, João (2) dep. fed. RJ m 1991 1993
14044 JORGE, Eduardo dep. fed. SP m 1991 1995
14082 CAMPOS, Cidinha dep. fed. RJ f 1991 1999
14674 MARIANO, Maurici dep. fed. SP m 1991 1995
14692 MASCARENHAS, Eduardo dep. fed. RJ m 1991 1993

66 rows × 5 columns

'dep. fed.' in "dep. fed. MT"
True

Exercícios#

  1. Construa uma função para buscar apenas verbetes de personagens que tenham ocupado o cargo de deputado federal. Tabule os resultados incluindo o número de mandatos.

  2. Construa uma função para buscar o primeiro verbete temático e apresente o seu conteúdo.

  3. Encontre todos os verbetes que contenham “Academia Brasileira de Letras”. Que porcentagem destes correspondem a membros da dita academia?

  4. Construa uma linha do tempo que represente a cobertura histórica do DHBB.

Exportando para Bancos de Dados#

Depois de realizarmos a nossa análise e tabular os resultados, podemos exportar a tabela em vários formatos. Em primeiro lugar, caso queiramos abri nossa trabalho em uma planilha, devemos salvar no formato CSV, ou “comma-separated-values”. Este formato pode ser aberto imediatamente em uma planilha.

tab.to_csv("minha_tabela.csv.gz", sep='|')

Acima usamos o caracter “|” como separador para evitar confusões com as virgulas existentes no texto.

Exportando para um banco de dados relacional#

Para exportar para um banco relacional, precisamos de uma biblioteca adicional, o SQLAlchemy. Estabiblioteca nos permite interagir com a maioria dos banco relacionais. Aqui vamos usar o banco SQLite.

from sqlalchemy import create_engine, text
engine = create_engine('sqlite:///minha_tabela.sqlite', echo=False)
tab.to_sql('resultados', con=engine, if_exists='replace')
7838
tab2.to_sql("cargos", con=engine, if_exists='replace')
15083

Uma vez inserido no banco relacional, podemos fazer consultas aos dados usando a linguagem SQL. Abaixo obtemos o resultado da consulta em uma lista.

with engine.connect() as con:
    rs = con.execute(text("select * from resultados where natureza='temático'"))
    print(rs.fetchall()[:10])
[(4, '6310.text', 'POLÍTICA DE CLIENTELA', 'temático', None, 'NA', '\n\nExpressão cunhada e conceito desenvolvido por Hélio Jaguaribe em seu\ntrabalho “Política ideológica e política de clientela”, publicado no\n«Jorn ... (2014 characters truncated) ... r derivação da expressão latina equivalente e das relações que, no\ninício da República Romana, existiam entre o pater famílias e seus\nclientes.\n\n'), (21, '5742.text', 'ASSEMBLÉIA NACIONAL CONSTITUINTE DE 1987-88', 'temático', None, 'NA', '\n\nNo dia 1º de fevereiro de 1987, os membros da Câmara dos Deputados e do\nSenado Federal reuniram-se, unicameralmente, em Assembléia Nacional\nCon ... (57523 characters truncated) ... nal ficou composto por 315 artigos, dos quais 245\ndistribuídos por oito títulos das disposições permanentes e 70 nas\ndisposições transitórias. \n\n'), (42, '5793.text', 'I CONGRESSO ANTIFASCISTA', 'temático', None, 'NA', '\n \nReunião realizada no Rio de Janeiro em agosto de 1934 sob a direção do\nPartido Comunista Brasileiro (PCB).\n\nSua finalidade era condenar a política fascista em ascensão. Contou,\nentre outras, com a presença de representantes operários.\n\n'), (52, '6346.text', 'REDE BANDEIRANTES', 'temático', None, 'NA', '\n\nRede de televisão pertencente ao grupo paulista Bandeirantes, fundado\npor João Jorge Saad, e que teve origem a partir da criação da TV\nBandeira ... (18363 characters truncated) ... ireção na emissora: Hélio Vargas (Direção de\nProgramação), Raimundo Lima (Direção de Produção) e Fernando Mitre\n(Direção Nacional de Jornalismo).\n'), (60, '11892.text', 'AGÊNCIA NACIONAL DE ENERGIA ELÉTRICA (ANEEL)', 'temático', None, 'NA', '\n\nAutarquia em regime especial, vinculada ao Ministério de Minas e Energia (MME), criada pela Lei nº 9.427, de 26 de dezembro de 1996, com a finali ... (39336 characters truncated) ... ão do aproveitamento hidrelétrico de Jirau, o segundo do Complexo do Rio Madeira, com capacidade estimada em 3.300 MW, foi realizado em maio de 2008.'), (66, '5703.text', 'AÇÃO CÍVICA NACIONAL', 'temático', None, 'NA', '\n\nPartido político do Rio de Janeiro (então Distrito Federal) fundado em\nmarço de 1933. Sua comissão central executiva era integrada por Luís\nMez ... (439 characters truncated) ... ão e a nacionalização da economia, e a defesa da\nreorganização política do país em bases novas, independente de quaisquer\ncoligações políticas.\n\n'), (67, '6221.text', 'PARTIDO REPUBLICANO REGENERADOR DO DISTRITO FEDERAL', 'temático', None, 'NA', '\n\nPartido político do Rio de Janeiro (então Distrito Federal) fundado em\n22 de setembro de 1934.\n\nSeu diretório central era constituído por Raul ... (872 characters truncated) ... rro Central do Brasil”.\n\nO partido pretendia eleger representantes à Câmara Municipal do Distrito\nFederal, mas não obteve êxito nesse sentido.\n\n'), (80, '5770.text', 'CÓDIGO DE MINAS', 'temático', None, 'NA', '\n\nO regime das minas no Brasil obedecia ao sistema estabelecido pelas\nOrdenações do Reino, pelo qual as minas eram de propriedade da Coroa.\nCom a ... (6078 characters truncated) ... 967)\nprocurou atualizar a legislação mineira no país, refletindo a\nexperiência de aplicação dos novos princípios legais pelo prazo de 33\nanos.\n\n'), (82, '5846.text', 'ELETROBRAS (Centrais Elétricas Brasileiras S.A.)', 'temático', None, 'NA', "\n\nEmpresa estatal criada em 25 de abril de 1961 pela Lei nº 3.890-A e\ninstalada em 11 de junho de 1962.\n\n## Antecedentes\n\nO desenvolvimento da ... (103944 characters truncated) ... 2009, a União detinha 52% das ações ordinárias com direito a voto,\ncorrespondentes a 41,5% do seu capital social, estimado em R$26.156\nmilhões.\n\n"), (83, '7789.text', 'COMISSÃO MISTA BRASIL-ESTADOS UNIDOS', 'temático', None, 'NA', '\n\nGrupo de trabalho oficialmente instalado na órbita e no próprio prédio\ndo Ministério da Fazenda em 19 de julho de 1951. Tendo completado seus\ne ... (10617 characters truncated) ... da Comissão Mista, em dezembro de 1953, coube ao BNDE\no encargo de levar avante as negociações para execução dos projetos por\nela recomendados.\n\n')]

Se quisermos os resultado na forma de um Dataframe, podemos usar o Pandas.

pd.read_sql_query("select * from resultados where natureza='temático'", con=engine).head()
index arquivo title natureza sexo cargos corpo
0 4 6310.text POLÍTICA DE CLIENTELA temático None NA \n\nExpressão cunhada e conceito desenvolvido ...
1 21 5742.text ASSEMBLÉIA NACIONAL CONSTITUINTE DE 1987-88 temático None NA \n\nNo dia 1º de fevereiro de 1987, os membros...
2 42 5793.text I CONGRESSO ANTIFASCISTA temático None NA \n \nReunião realizada no Rio de Janeiro em ag...
3 52 6346.text REDE BANDEIRANTES temático None NA \n\nRede de televisão pertencente ao grupo pau...
4 60 11892.text AGÊNCIA NACIONAL DE ENERGIA ELÉTRICA (ANEEL) temático None NA \n\nAutarquia em regime especial, vinculada ao...