Desde que o twitter liberou o histórico dos tweets antigos em formato CSV, procurei uma ferramenta para poder um tagcloud das minha palavras.  Como o arquivo era muito grande (mais de 3 MB), as ferramentas online simplesmente travavam.

Procurando por alternativas, encontrei o pouco citado pytagcloud.

Então fiz o seguinte programa pra gerar o tagcloud dos meus tweets:

#! /usr/bin/pyhon
# -*- coding: utf-8 -*-

import re, csv
from pytagcloud import create_tag_image, make_tags
from pytagcloud.lang.counter import get_tag_counts

TWEETS = "tweets.csv"

buffer = ""

tws = csv.reader(open(TWEETS), delimiter=',', quotechar='"')

for rows in tws:
    buffer += rows[5] + "\n"

output = "clound_large.png"
tags = make_tags(get_tag_counts(buffer), maxsize=120)
create_tag_image(tags,
                 output,
                 size=(800, 600),
                 fontname='Lobster')

Foi exatamente a cópia do programa documentado pelo próprio pytagcloud. Pra minha supresa, não funciona e sai o seguinte erro:

Traceback (most recent call last):
  File "generate_cloud.py", line 53, in 
  File "/usr/local/lib/python2.7/dist-packages/pytagcloud/__init__.py", line 344, in create_tag_image
  File "/usr/local/lib/python2.7/dist-packages/pytagcloud/__init__.py", line 275, in _draw_cloud
  File "/usr/local/lib/python2.7/dist-packages/pytagcloud/__init__.py", line 62, in __init__
IOError: unable to read font filename
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/apport_python_hook.py", line 66, in apport_excepthook
ImportError: No module named fileutils

Original exception was:
Traceback (most recent call last):
  File "generate_cloud.py", line 53, in 
  File "/usr/local/lib/python2.7/dist-packages/pytagcloud/__init__.py", line 344, in create_tag_image
  File "/usr/local/lib/python2.7/dist-packages/pytagcloud/__init__.py", line 275, in _draw_cloud
  File "/usr/local/lib/python2.7/dist-packages/pytagcloud/__init__.py", line 62, in __init__
IOError: unable to read font filename

Após muito mexer, pois o código exemplo, com texto menor, funciona perfeitamente, descobri que esse erro é gerado pela quantidade de palavras no arquivo de tweets.  Consegui corrigir isso colocando um limite no tamanho dos tags, que é um array.

Em seguida me deparei com um problema de... codificação.  Apesar de gerar o arquivo de imagem, as palavras que são originalmente utf-8 saem quebradas pois em algum lugar é usado iso-8859-1.  Tentei utilizar o formato objeto.decode('utf-8').encode('latin-1') para recodificar o texto, mas o mesmo apresentava erro sempre.  Fui descobrir que o causador era o danado do texto em árabe que postei no twitter pra sacanear o pessoal que usa Apple.  Fiz uma conversão caractér a caractér e desconsiderei os que davam errado.  Com isso terminei com o seguinte código:

#! /usr/bin/pyhon
# -*- coding: utf-8 -*-

import re, csv, sys
from pytagcloud import create_tag_image, make_tags
from pytagcloud.lang.counter import get_tag_counts

TWEETS = "tweets.csv"
LIMIT = int(sys.argv[-1])

buffer = ""

tws = csv.reader(open(TWEETS), delimiter=',', quotechar='"')

for rows in tws:
    buffer += rows[5] + "\n"

buffer = re.sub("http://", "", buffer)
buffer = re.sub("https://", "", buffer)
buffer = re.sub("RT", "", buffer)
buffer = re.sub("mltp.ly/", "", buffer)
buffer = re.sub("bit.ly/", "", buffer)
buffer = re.sub("eri.cx/", "", buffer)
buffer = re.sub("via @addthis", " ", buffer)
buffer = re.sub("youtu.be/", "", buffer)
buffer = re.sub("twitthis.com/", "", buffer)
buffer = re.sub("t.co/", "", buffer)
buffer = re.sub("miud.in/", "", buffer)
buffer = re.sub("[,\. ](eu|da|do|de|com|to|tem|ter)[,\. ]", " ", buffer)
buffer = re.sub("[,\. ](mesmo|pelo|que|by|via|the|um|dos)[,\. ]", " ", buffer)
buffer = re.sub("[,\. ](é|to|tô|pra|para|muito|mto)[,\. ]", " ", buffer)
buffer = re.sub("[,\. ](em|vou|foi|as|us|me|I|you)[,\. ]", " ", buffer)
buffer = re.sub("[,\. ](para|pôr|is|esse|essa|isso|na)[,\. ]", " ", buffer)
buffer = re.sub("[,\. ](uma|um|ao|pelo|por|mais|com|eu)[,\. ]", " ", buffer)
buffer = re.sub("[,\. ](pra|quando|qdo|do|da|tb|também)[,\. ]", " ", buffer)
buffer = re.sub("[,\. ](isso|mas|meu|vc|in|on|so|of)[,\. ]", " ", buffer)
buffer = re.sub("[,\. ](end|for|esta|está|ter|at|ou)[,\. ]", " ", buffer)
buffer = re.sub("[,\. ](seu|sua|eu|and|so|sem|só)[,\. ]", " ", buffer)

text = ""
for c in buffer:
    try:
        a = c.decode('utf-8')
        text += a.encode('iso-8859-1')
    except:
        pass

output = "clound_large_%d.png" % LIMIT
tags = make_tags(get_tag_counts(text), maxsize=120)
create_tag_image(tags[:LIMIT],
                 output,
                 size=(800, 600),
                 fontname='Lobster')

for i in xrange(LIMIT):
    print i, tags[i]['tag'], tags[i]['size']

E assim gerei os tagclouds com limite de palavras mas sempre de mesmo tamanho.  Os resultado foram esses:

10 palavras mais usadas

 

30 palavras mais usadas

 

50 palavras mais usadas

100 palavras mais usadas

 

200 palavras mais usadas

 

300 palavras mais usadas

 

400 palavras mais usadas

 

500 palavras mais usadas

Acima de 500 palavras, o pytagcloud cospe o famigerado erro.  O engraçado é que com 500 palavras, o uso de espaço é melhor aproveitado que com 30.

E qual é o seu tagcloud?