Há muita discussão sobre o uso de código livre e/ou aberto no governo. No entanto, geralmente as opiniões mais externadas são extremas de all or nothing. Aqui na Repúblida Digital temos uma posição mais equilibrada. O importante é saber quando pagar e quando usar uma solução free. Com isso em mente, para aqueles que querem criar ferramentas que possam auxiliá-los na descoberta de informação, ou mesmo para aqueles que apenas ficaram curiosos sobre como fizemos a nossa, vai aí, de uma forma simplificada, a descrição das técnicas, bibliotecas e ferramentas (todas free) que foram utilizadas para produzir o aplicativo que vocês viram no post sobre análise de redes sociais.

Neste trabalho foi utilizada a linguagem de programação Python. Para quem não conhece é uma linguagem com uma curva de aprendizado rápida e que possui diversas bibliotecas muito utilizadas em Ciência de Dados. Não é nosso foco ensinar a linguagem, então, caso não tenha nenhum conhecimento em Python ou mesmo em programação, existem vários tutoriais na rede que servem como um bom ponto de partida (basta um “introdução python” no Google que está tudo resolvido! rs).

Utilizamos o framework Django para criar a aplicação Web e a biblioteca D3.js para exibir o grafo em JavaScript. Também não faz parte do nosso foco ensinar Django ou mesmo D3, por isso, preparamos uma forma simples de exibir o grafo ao final do processo no seu browser.

A biblioteca que utilizamos para pesquisar no Twitter foi a Python Twitter Tools. Entretanto, vamos aproveitar um dos comentários (e único pedido oficial que recebemos de melhoria na nossa ferramenta! Vamos lá, pessoal… eu esperava mais de vocês! :-P) do post anterior e vamos fazer a leitura de um arquivo Excel para utilizar como entrada.

Os exemplos abaixo são de 1.000 tweets sobre a França que estão disponíveis no arquivo “textos.xlsx”.  BTW, todo código que utilizamos para esse post está no GitHub (also free).

Se você utiliza Windows, sugiro fortemente instalar Anaconda 3 principalmente por conta de bibliotecas como o numpy. Normalmente o pip (instalador de pacotes/libs do python) apresenta erros ao instalar esses pacotes se você não tiver o Visual C Compiler for Python na versão certa para as versões de Windows e Python que você está utilizando. O Anaconda traz estas e outras bibliotecas pré-instaladas. Isso vai economizar bastante o seu tempo de configuração de um ambiente.

Então vamos começar!

Vamos ler as informações do Excel. Isso é feito na nossa função ler_excel, definida no arquivo relacao_palavras.py, que realiza a leitura do conteúdo da primeira planilha do arquivo. Consideramos a primeira linha como o cabeçalho. O retorno da função é um DataFrame do Pandas, uma biblioteca que possui algumas estruturas para facilitar a manipulação e transformação de dados. O dataframe representa uma tabela com colunas e linhas.

df_dados = ler_excel(os.path.join(BASE_DIR, 'textos.xlsx'))
print("Total de Registros Lidos: {}".format(len(df_dados)))
print(df_dados.head())
Total de Registros Lidos: 1000

Tweets Coletados \
0 Brigitte Macron: de professora à primeira-dama da França https://t...
1 RT @Julieta100Romeo: Ao menos a França se livrou do pesadelo da ex...
2 França: Marine Le Pen quer mudar o nome da Frente Nacional (vídeo)...
3 RT @RDTLadyGaga: Na França, "The Cure" ganha edição física promoci...
4 RT @sopqlarry: Sempre é bom lembrarmos dessa entrevista maravilhos...

Índice
0 1.0
1 2.0
2 3.0
3 4.0
4 5.0

Após a leitura das informações, criamos um DataFrame novo apenas com a primeira coluna do arquivo lido e renomeamos a coluna para ‘texto’.

df_textos = df_dados[[df_dados.columns[0]]]
df_textos.columns = ['texto']
print(df_textos.head())
texto
0 Brigitte Macron: de professora à primeira-dama da França https://t...
1 RT @Julieta100Romeo: Ao menos a França se livrou do pesadelo da ex...
2 França: Marine Le Pen quer mudar o nome da Frente Nacional (vídeo)...
3 RT @RDTLadyGaga: Na França, "The Cure" ganha edição física promoci...
4 RT @sopqlarry: Sempre é bom lembrarmos dessa entrevista maravilhos...

Antes da análise dos textos é importante fazer a limpeza do conteúdo.

Números que possuem máscaras como, por exemplo, CPFs, CNPJs, CEPs e Leis podem virar apenas números 000.000.000-00 -> 00000000000. Dependendo do seu propósito também pode ser interessante alguma marcação do tipo <cpf|00000000000>. No nosso caso, apenas limparemos os caracteres entre os números para mais tarde remover todos os números. A função utilizada nesse caso foi a tratar_numeros.

resultado = TratamentoTexto.tratar_numeros(resultado)

Remoção de URLs, usando a função remover_urls.

resultado = TratamentoTexto.remover_urls(resultado)

Conversão do texto para letras minúsculas, usando função do próprio Python.

resultado = resultado.lower()

Precisamos remover as stopwords, que são palavras que não têm relevância, principalmente se nosso objetivo é avaliar frequência de termos. Preposições são bons exemplos de stopwords. Aqui utilizamos uma lista de stopwords definidas pelo NTLK, uma biblioteca em Python utilizada para processamento de linguagem natural. Para não aumentar ainda mais o número de dependências no código apenas copiamos as palavras para uma array dentro da classe TratamentoTexto, chamado de stopwords.

A remoção de palavras irrelevantes para nosso propósito é uma das estapas do tratamento do texto, definida na função remover_stopwords.

resultado = TratamentoTexto.remover_stopwords(resultado)

Se explorarmos melhor a classe TratamentoTexto podemos verificar que há uma sequência de tratamentos distintos que são realizados, como a remoção de caracteres especiais e pontuações, através da função remover_caracteres_especiais.

resultado = TratamentoTexto.remover_caracteres_especiais(resultado)

Também temos a remoção de acentuações, através da função remover_acentuacao. No caso de textos livres, como no Twitter, é comum que algumas pessoas não escrevam utilizando acentuação. Neste caso, é mais interessante remover a acentuação de todas as palavras para ter uma contagem de frequências mais correta. Há casos onde a falta de acentuação nos levará a uma resultado divergente (farão, faraó -> farao), mas na maioria dos casos compensa. Em publicações ou outros textos que passam por revisão talvez manter a acentuação seja mais interessante. Fica a critério de quem utiliza.

resultado = TratamentoTexto.remover_acentuacao(resultado)

Outro tratamento é a remoção dos números isolados, ou seja, que não fazem parte de alguma palavra. Para isso usamos a função remover_numeros.

resultado = TratamentoTexto.remover_numeros(resultado)

Removemos também espaços extras, através da função remover_espacos_excessivos.

resultado = TratamentoTexto.remover_espacos_excessivos(resultado)
resultado = resultado.strip()

Nó código abaixo, aplicamos o tratamento de texto em todas as linhas lidas do arquivo e armazenamos em uma nova coluna chamada ‘texto_tratado’, usando a função tratar_texto.

tratamento = TratamentoTexto()
df_textos['texto_tratado'] = df_textos['texto'].map(lambda x: tratamento.tratar_texto(x))
print(df_textos.head())
texto \
0 Brigitte Macron: de professora à primeira-dama da França https://t...
1 RT @Julieta100Romeo: Ao menos a França se livrou do pesadelo da ex...
2 França: Marine Le Pen quer mudar o nome da Frente Nacional (vídeo)...
3 RT @RDTLadyGaga: Na França, "The Cure" ganha edição física promoci...
4 RT @sopqlarry: Sempre é bom lembrarmos dessa entrevista maravilhos...

texto_tratado
0 brigitte macron professora primeira-dama franca auto pickup by wikyou
1 @julieta100romeo menos franca livrou pesadelo extrema-direita enqu...
2 franca marine le pen quer mudar nome frente nacional video -
3 @rdtladygaga franca the cure ganha edicao fisica promocional
4 @sopqlarry sempre e bom lembrarmos dessa entrevista maravilhosa fr...

Você deve ter visto algumas coisas estranhas como ‘(^|\b)(\d+)(\b|$)’. Isso é uma expressão regular. Muito útil para encontrar padrões dentro de textos. Esse exemplo identifica uma sequência de um ou mais dígitos (\d+) que podem estar no início de uma linha (^|\b) ou com espaço em branco à esquerda ou no final de uma linha ou com espaço em branco à direita (\b|$). Esta é a referência para a biblioteca de expressões regulares do Python 3.

Uma boa limpeza nos dados pode fazer toda a diferença entre encontrar algo útil nos resultados ou apenas um grafo cheio de conexões sem muita informação.

Você não precisa parar por aqui. Provavelmente encontrará diversas palavras para colocar no array de stopwords. Também dependerá dos textos que você vai utilizar.

E se fosse possível reduzir as formas verbais ou derivações de uma palavra a um mesmo radical?

falassem, falarem, falei, falou -> fal????

Já ouviu falar de stemming? É o processo de extrair a raiz de uma palavra, elminando contrações e derivações. O NTLK possui um algoritmo para fazer isso em palavras da língua portuguesa.

import nltk
stemmer = nltk.stem.RSLPStemmer()
stemmer.stem("falassem") -> 'fal'
stemmer.stem("falaram") -> 'fal'
stemmer.stem("falei") -> 'fal'
stemmer.stem("falar") -> 'fal'

Pode ser um recurso interessante, ou pode ser algo um pouco radical demais. Depende do seu propósito. Vale a pena testar.

Se o seu objetivo abrange, ainda, encontrar similaridade entre textos, algoritmos fonéticos também podem ser interessantes. Quem sabe podemos explorar isso em outro momento.

Até aqui nós lemos as informações e fizemos um tratamento básico usando Python e algumas funções que criamos para facilitar o seu trabalho (pode copiar e colar, fique à vontade!). No próximo post vamos falar um pouco sobre as frequências das palavras e como transformamos elas em informação relevante para decidir quais palavras podem ser mais importantes e quais devemos ignorar. Ainda vamos falar de clusterização e como gerar grafos de palavras, não percam e até a próxima! 😉


Fernando Sola é Bacharel em Ciências da Computação pela PUCRS, Cientista de Dados no Observatório da Despesa Pública, SCJP, SCWCD, SCBCD e entusiasta Python.