Mineração de dados com Ruby e Twitter

Pessoal, estou aproveitando uma dica do Grimaldo (BI com Vatapá), um dos maiores especialista do Brasil em Mineração de Dados, e estou copiando um texto que ele recomendou em seu Facebook. Acredito que esse texto, bem como os exemplos que ele apresentam, definem bem, ‘by example‘, o conceito de ‘Mineração de Dados’, muito em voga nos dias de hoje. Grimaldo, meu velho, obrigado pela força!!!

Aproveitando, Ruby é uma Linguagem de programação interpretada, com Tipagem Dinâmica e Tipagem Forte, orientada a objetos e, com várias semelhanças com Perl, Python e SmallTalk. Projetada tanto para a programação em grande escala quanto para codificação rápida, tem um suporte a orientação a objetos simples e prático. A linguagem foi criada pelo japonês Yukihiro Matsumoto (Matz), que aproveitou as melhores idéias das outras linguagens da época. Esta linguagem possui vastos repositórios de bibliotecas disponíveis em sites como Ruby Forge e Ruby Application Archive (RAA). Existe, ainda, uma ferramenta bastante útil para instalação de bibliotecas, chamada Ruby Gems. O projeto mais famoso desenvolvido em Ruby é o meta-framework Ruby on Rails. 

Quarta-feira, 27/06/2012 às 08h40, por developerWorks Brasil – Autor: M. Tim Jones é arquiteto de firmware integrado e autor de vários livros na área de TI. Tim é Consultor de Engenharia da Emulex Corp. em Longmont, Colorado.

Criei uma conta no Twitter por curiosidade em outubro de 2008 como muitos outros fizeram. Como a maioria das pessoas, conectei-me com amigos e fiz algumas pesquisas aleatórias para entender melhor o serviço. A comunicação com 140 caracteres não parecia uma ideia que se tornaria popular. Mas um acontecimento que não teve nada a ver com o Twitter me ajudou a entender seu valor real.

No início de julho de 2009, meu provedor de hospedagem da web saiu do ar. Depois de pesquisar pela web, encontrei informações que apontavam o incêndio no Fisher Plaza de Seattle como sendo o culpado.

Informações vindas de fontes tradicionais baseadas na web eram lentas e não davam indicação de quando o serviço poderia retornar. No entanto, ao pesquisar no Twitter, encontrei relatos pessoais do incidente, incluindo informações em tempo real sobre o que estava acontecendo no local.

Por exemplo, logo antes que meu serviço de hospedagem retornasse, houve um tweet indicando que geradores a diesel estavam do lado de fora do prédio. Foi quando me dei conta de que o verdadeiro poder do Twitter é a comunicação aberta e em tempo real de informações entre indivíduos e grupos. Mas, sob a superfície, ele tem um tesouro de informações sobre comportamentos dos usuários e de tendências em níveis local e global.

Exploro isso no contexto de scripts simples usando a linguagem Ruby e o gem do Twitter, um wrapper da API para o Twitter. Também demonstro como criar mashups simples para visualização de dados usando outros serviços e aplicativos da web.

Twitter e APIs

Embora, inicialmente, a web se destinasse à interação entre homens e máquinas, hoje ela trata da interação entre máquinas, ativando o uso de WebServices. Esses serviços existem para os sites mais populares —de vários serviços do Google ao LinkedIn, Facebook e Twitter. WebServices criam APIs por meio das quais aplicativos externos podem consultar ou manipular conteúdo nos sites da internet.

Os WebServices são implementados usando uma série de estilos. Hoje, um dos mais populares é o Representational State Transfer, ou REST. Uma implementação do REST é sobre o bem conhecido protocolo HTTP, permitindo que o HTTP exista como um meio para uma arquitetura RESTful (usando operações HTTP padrão como GET, PUT das atualizações, POSTe DELETE).

A API para o Twitter foi desenvolvida como uma abstração sobre esse meio. Dessa forma, não há conhecimento de REST, HTTP ou formatos de dados, como XML ou JSON, mas, em vez disso, uma interface com base em objeto que se integra de forma eficiente na linguagem Ruby.

Um tour rápido do Ruby e do Twitter

Vamos explorar como é possível usar a API do Twitter com Ruby. Primeiro, precisamos obter os recursos necessários. Se, como eu, você está usando o Ubuntu Linux®, use a estrutura apt .

Para obter a distribuição completa mais recente do Ruby (um download de aproximadamente 13MB), use essa linha de comando:

$ sudo apt-get install ruby1.9.1-full           

A seguir, obtenha o gem do Twitter usando o utilitário gem:

$ sudo gem install twittertall twitter

Agora você tem tudo o que é necessário para essa etapa. Vamos então continuar com um teste do wrapper do Twitter. Para essa demonstração, use um shell chamado Interactive Ruby Shell (IRB). Esse shell permite executar comandos do Ruby e experimentar a linguagem em tempo real. O IRB tem um grande número de capacidades, mas nós o usaremos para experimentação simples.

O código abaixo mostra uma sessão com o IRB que foi dividida em três seções para auxiliar na capacidade de leitura:

  • $ irb
  • irb(main):001:0> require “rubygems”
  • => true
  • irb(main):002:0> require “twitter”
  • => true
  • irb(main):003:0> puts Twitter.user_timeline(“developerworks”).first.text
  • dW Twitter is saving #IBM over $600K per month: will #Google+ add to that? >
  • http://t.co/HiRwir7 #Tech #webdesign #Socialmedia #webapp #app
  • => nil
  • irb(main):004:0> puts Twitter.user(“MTimJones”).location
  • Colorado, USA
  • => nil
  • irb(main):005:0> search = Twitter::Search.new
  • => #<Twitter::Search:0xb7437e04 @oauth_token_secret=nil,
  •     @endpoint=”https://api.twitter.com/1/&#8221;,
  •     @user_agent=”Twitter Ruby Gem 1.6.0″,
  •     @oauth_token=nil, @consumer_secret=nil,
  •     @search_endpoint=”https://search.twitter.com/&#8221;,
  •     @query={:tude=>[], :q=>[]}, @cache=nil, @gateway=nil, @consumer_key=nil,
  •     @proxy=nil, @format=:json, @adapter=:net_http<
  • irb(main):006:0> search.containing(“why”).to(“LulzSec”).
  • result_type(“recent”).each do |r| puts r.text end
  • @LulzSec why not stop posting <bleep> and get a full time job! MYSQLi isn’t
  • hacking you <bleep>.
  • irb(main):007:0>

A primeira seção (linhas 001 e 002) simplesmente prepara o ambiente ao importar os elementos necessários de tempo de execução (o método exige carrega e executa a biblioteca nomeada). A próxima linha (003) demonstra o uso do gem do Twitter para exibir o tweet mais recente do IBM® developerWorks®. Como mostrado, você usa o método user_timeline do módulo Client::Timeline para exibir um tweet.

Esse primeiro exemplo demonstra a capacidade de “métodos encadeados” do Ruby. Um método user_timeline retorna um array de 20 tweets que podem ser encadeados no método first . Isso extrai o primeiro tweet do array (first é um método da classe Array ). Para esse único tweet, você extrai o campo de texto emitido para a saída via puts. A seção seguinte (linha 004) usa o campo de localização definido pelo usuário, um campo de formato livre no qual o usuário pode fornecer informações de localização úteis e não úteis. Neste exemplo, o módulo User obtém informações do usuário restringidas dentro do campo de localização.

A seção final (a partir da linha 005) explora o módulo Twitter::Search . O módulo de pesquisa fornece uma interface extremamente rica com a qual pesquisar no Twitter. Nesse exemplo, primeiro você cria uma instância de pesquisa (linha 005) e, a seguir, especifica uma pesquisa na linha 006.

Você está pesquisando os tweets mais recentes contendo a palavra why (porquê, em inglês) que sejam direcionados ao usuário LulzSec. A lista resultante foi reduzida e editada. Pesquisas são persistentes com relação ao fato de que a instância da pesquisa mantém os filtros definidos. É possível limpar esses filtros executando search.clear.

A seguir, veremos o esquema para um usuário no Twitter. Também é possível fazer isso por meio do IRB, mas reformatarei o resultado para ilustrar de forma mais simples a anatomia de um usuário do Twitter. O código abaixo mostra o resultado da impressão da estrutura do usuário que, no Ruby, é um Hashie::Mash.

  • irb(main):007:0> puts Twitter.user(“MTimJones”)
  • <#Hashie::Mash
  •   contributors_enabled=false
  •   created_at=”Wed Oct 08 20:40:53 +0000 2008″
  •   default_profile=false default_profile_image=false
  •   description=”Platform Architect and author (Linux, Embedded, Networking, AI).”
  •   favourites_count=1
  •   follow_request_sent=nil
  •   followers_count=148
  •   following=nil
  •   friends_count=96
  •   geo_enabled=true
  •   id=16655901 id_str=”16655901″
  •   is_translator=false
  •   lang=”en”
  •   listed_count=10
  •   location=”Colorado, USA”
  •   name=”M. Tim Jones”
  •   notifications=nil
  •   profile_background_color=”1A1B1F”
  •   profile_background_image_url=”…”
  •   profile_background_image_url_https=”…”
  •   profile_background_tile=false
  •   profile_image_url=”http://a0.twimg.com/profile_images/851508584/bio_mtjones_normal.JPG&#8221;
  •   profile_image_url_https=”…”
  •   profile_link_color=”2FC2EF”
  •   profile_sidebar_border_color=”181A1E” profile_sidebar_fill_color=”252429″
  •   profile_text_color=”666666″
  •   profile_use_background_image=true
  •   protected=false
  •   screen_name=”MTimJones”
  •   show_all_inline_media=false
  •   status=<#Hashie::Mash
  •     contributors=nil coordinates=nil
  •     created_at=”Sat Jul 02 02:03:24 +0000 2011″
  •     favorited=false
  •     geo=nil
  •     id=86978247602094080 id_str=”86978247602094080″
  •     in_reply_to_screen_name=”AnonymousIRC”
  •     in_reply_to_status_id=nil in_reply_to_status_id_str=nil
  •     in_reply_to_user_id=225663702 in_reply_to_user_id_str=”225663702″
  •     place=<#Hashie::Mash
  •       attributes=<#Hashie::Mash>
  •       bounding_box=<#Hashie::Mash
  •         coordinates=[[[-105.178387, 40.12596],
  •                       [-105.034397, 40.12596],
  •                       [-105.034397, 40.203495],
  •                       [-105.178387, 40.203495]]]
  •         type=”Polygon”
  •       >
  •       country=”United States” country_code=”US”
  •       full_name=”Longmont, CO”
  •       id=”2736a5db074e8201″
  •       name=”Longmont” place_type=”city”
  •       url=”http://api.twitter.com/1/geo/id/2736a5db074e8201.json&#8221;
  •     >
  •     retweet_count=0
  •     retweeted=false
  •     source=”web”
  •     text=”@AnonymousIRC @anonymouSabu @LulzSec @atopiary @Anonakomis Practical reading
  •           for future reference… LULZ \”Prison 101\” http://t.co/sf8jIH9&#8243; truncated=false
  •   >
  •   statuses_count=79
  •   time_zone=”Mountain Time (US & Canada)”
  •   url=”http://www.mtjones.com&#8221;
  •   utc_offset=-25200
  •   verified=false
  • => nil
  • irb(main):008:0>

Essa estrutura é útil porque permite que um objeto tenha acessos de método para chaves de hash (um objeto aberto). Como é possível ver no código acima, esse objeto contém uma série de informações (informações específicas do usuário e de renderização), incluindo o status atual do usuário (com informações de codificação geográfica). Um tweet também contém um grande volume de informações e é possível visualizá-las facilmente gerando essas informações usando a classe user_timeline .

E esse é o fim do tour rápido. Vamos explorar agora alguns scripts simples que podem ser usados para coletar e visualizar dados usando Ruby e a API do Twitter. Ao longo do caminho, você conhecerá alguns dos conceitos do Twitter, como autenticação e limitação de taxa.

Mineração de dados do Twitter

As seções a seguir apresentam vários scripts para coletar e apresentar dados disponíveis por meio da API do Twitter. Esses scripts têm como foco a simplicidade, mas é possível estendê-los e combiná-los para criar novas capacidades. Além disso, essa seção explora de forma geral a API gem do Twitter, onde muitas outras capacidades estão disponíveis.

É importante notar que a API do Twitter somente permite que clientes façam um número limitado de chamadas em uma certa hora, ou seja, Twitter limita as solicitações (atualmente, não mais do que 150 por hora), o que significa que, depois de um certo volume de uso, você receberá uma mensagem de erro e deverá aguardar antes de enviar novas solicitações. Lembre-se do código acima, em que um grande volume de informações está disponível sobre cada usuário do Twitter. Essas informações só estão acessíveis se o usuário não estiver protegido. Vejamos como é possível extrair os dados de um usuário e apresentá-los de uma forma mais conveniente.

O código abaixo presenta um script simples do Ruby para recuperar as informações de um usuário (com base em seu nome de exibição) e, a seguir, emitir alguns dos elementos mais úteis. Use o método to_s do Ruby para converter o valor em uma cadeia de caracteres, conforme necessário. Observe que primeiro é preciso assegurar-se de que o usuário não está protegido; caso contrário, esses dados não estarão acessíveis.

  • #!/usr/bin/env ruby
  • require “rubygems”
  • require “twitter”
  • screen_name = String.new ARGV[0]
  • a_user = Twitter.user(screen_name)
  • if a_user.protected != true
  •   puts “Username   : ” + a_user.screen_name.to_s
  •   puts “Name       : ” + a_user.name
  •   puts “Id         : ” + a_user.id_str
  •   puts “Location   : ” + a_user.location
  •   puts “User since : ” + a_user.created_at.to_s
  •   puts “Bio        : ” + a_user.description.to_s
  •   puts “Followers  : ” + a_user.followers_count.to_s
  •   puts “Friends    : ” + a_user.friends_count.to_s
  •   puts “Listed Cnt : ” + a_user.listed_count.to_s
  •   puts “Tweet Cnt  : ” + a_user.statuses_count.to_s
  •   puts “Geocoded   : ” + a_user.geo_enabled.to_s
  •   puts “Language   : ” + a_user.lang
  •   puts “URL        : ” + a_user.url.to_s
  •   puts “Time Zone  : ” + a_user.time_zone
  •   puts “Verified   : ” + a_user.verified.to_s
  •   puts
  •   tweet = Twitter.user_timeline(screen_name).first
  •   puts “Tweet time : ” + tweet.created_at
  •   puts “Tweet ID   : ” + tweet.id.to_s
  •   puts “Tweet text : ” + tweet.text
  • end

Para chamar esse script, assegurando-se de que ele seja executável (chmod +x user.rb), ele é chamado com um usuário.

O resultado é mostrado no código abaixo para o usuário developerworks, mostrando as informações do usuário e o status atual (últimas informações de tweet). Observe aqui que o Twitter define followers como pessoas que seguem você; mas pessoas que você segue são chamadas de friends.

$ ./user.rb developerworks Username   : developerworks Name       : developerworks Id         : 16362921 Location   :  User since : Fri Sep 19 13:10:39 +0000 2008 Bio        : IBM’s premier Web site for Java, Android, Linux, Open Source, PHP, Social,  Cloud Computing, Google, jQuery, and Web developer educational resources Followers  : 48439 Friends    : 46299 Listed Cnt : 3801 Tweet Cnt  : 9831 Geocoded   : false Language   : en URL        : http://bit.ly/EQ7te Time Zone  : Pacific Time (US & Canada) Verified   : false  Tweet time : Sun Jul 17 01:04:46 +0000 2011 Tweet ID   : 92399309022167040 Tweet text : dW Twitter is saving #IBM over $600K per month: will #Google+ add to that? >  http://t.co/HiRwir7 #Tech #webdesign #Socialmedia #webapp #app

Popularidade dos amigos

Veja seus amigos (pessoas que você segue) e reúna dados para entender sua popularidade. Nesse caso, você reúne seus amigos e os classifica na ordem de suas contagens de seguidores. Esse script simples é mostrado no código abaixo.

  • #!/usr/bin/env ruby
  • require “rubygems”
  • require “twitter”
  • name = String.new ARGV[0]
  • user = Hash.new
  • # Iterate friends, hash their followers
  • Twitter.friends(name).users.each do |f|
  •   # Only iterate if we can see their followers
  •   if (f.protected.to_s != “true”)
  •     user[f.screen_name.to_s] = f.followers_count
  •   end
  • enduser.sort_by {|k,v| -v}.each { |user, count| puts “#{user}, #{count}” }

Nesse script, depois de entender o usuário que deseja analisar (com base em seu nome de exibição), você cria um hash de usuário. Um hash do Ruby (ou array associativo) é uma estrutura de dados que permite definir a chave para armazenamento (em vez de um índice numérico simples). Seu hash, então, é indexado pelo nome de exibição do Twitter e o valor associado é a contagem de seguidores do usuário. O processo é simplesmente para iterar seus amigos e fazer hash de suas contagens de seguidores. Classifique seu hash (em ordem descendente) e emita-o como saída.

A amostra de saída do script friends na no código acima é mostrada abaixo. Cortei a saída para economizar espaço, mas, como podem ver, ReadWriteWeb (RWW) e Playstation são usuários populares do Twitter em minha rede direta.

  • $ ./friends.rb MTimJones
  • RWW, 1096862
  • PlayStation, 1026634
  • HarvardBiz, 541139
  • tedtalks, 526886
  • lifehacker, 146162
  • wandfc, 121683
  • AnonymousIRC, 117896
  • iTunesPodcasts, 82581
  • adultswim, 76188
  • forrester, 72945
  • googleresearch, 66318
  • Gartner_inc, 57468
  • developerworks, 48518           

Onde estão meus seguidores?

Lembre-se do segundo código apresentado, quando foi dito que o Twitter fornece uma variedade de informações de localização. Há um campo de localização que tem formato livre, definido pelo usuário, e dados de codificação geográfica opcionais. No entanto, um fuso horário definido pelo usuário também pode fornecer uma dica sobre a localização real do seguidor.

Nesse exemplo, você criará um mash-up que extrai dados de fuso horário de seus seguidores do Twitter e, a seguir, visualiza esses dados usando Google Charts.

O Google Charts é um projeto interessante que permite criar uma variedade de tipos diferentes de gráficos na web definindo o tipo de gráfico e os dados como uma solicitação de HTTP, onde o resultado é renderizado diretamente no navegador como resposta. Para instalar o gem do Ruby para o Google Charts, use a seguinte linha de comando:

$ gem install gchartrb

O próximo código fornece o script para extrair dados de fuso horário e, a seguir, criar a solicitação para o Google Charts. Primeiro, diferentemente de scripts anteriores, esse script requer que você esteja autenticado no Twitter.

  • #!/usr/bin/env ruby
  • require “rubygems”
  • require “twitter”
  • require ‘google_chart’
  • screen_name = String.new ARGV[0]
  • tweetlocation = Hash.new
  • timezones = 0.0
  • # Authenticate
  • Twitter.configure do |config|
  •   config.consumer_key = ‘<consumer_key>’
  •   config.consumer_secret = ‘<consumer_secret>’
  •   config.oauth_token = <oauth_token>’
  •   config.oauth_token_secret = ‘<oauth_token_secret>’
  • end
  • # Iterate followers, hash their location
  • followers = Twitter.followers.users.each do |f|
  •   loc = f.time_zone.to_s
  •   if (loc.length > 0)
  •     if tweetlocation.has_key?(loc)
  •       tweetlocation[loc] = tweetlocation[loc] + 1
  •     else
  •       tweetlocation[loc] = 1
  •     end
  •     timezones = timezones + 1.0
  •   endend# Create a pie chart
  • GoogleChart::PieChart.new(‘650×350’, “Time Zones”, false ) do |pc|
  •   tweetlocation.each do |loc,count|
  •     pc.data loc.to_s.delete(“&”), (count/timezones*100).round
  •   end
  •   puts pc.to_url
  • end

Para tanto, é preciso registrar um aplicativo no Twitter, o que fornece um conjunto de chaves e tokens. Esses tokens podem ser aplicados ao script do código acima para extrair os dados com sucesso. Seguindo um padrão similar, esse script aceita um nome de exibição e, a seguir, percorre os seguidores daquele usuário. O fuso horário é extraído do seguidor atual e armazenado no hash tweetlocation.

Observe que primeiro você testa se essa chave está no hash e, se estiver, incrementa o contador para aquela chave. Você também mantém uma guia com o número total de fusos horários para a criação posterior de porcentagens. A última porção do script é a criação da URL do gráfico de setores circulares do Google. Você cria um novo PieChart e especifica algumas opções (tamanho, título e se ele é 3D). A seguir, você percorre o hash de fuso horário, emitindo dados da cadeia de caractere do fuso horário para o gráfico (removendo o símbolo &) e a porcentagem do fuso horário do total

Para executar o script do código acima, forneça a ele um nome de exibição do Twitter e, a seguir, copie e cole a URL resultante em um navegador. O código a seguir mostra esse processo com a URL gerada resultante:

$ ./followers-location.rb MTimJones http://chart.apis.google.com/chart?chl=Seoul|Santiago|Paris|Mountain+Time+(US++Canada)| Madrid|Central+Time+(US++Canada)|Warsaw|Kolkata|London|Pacific+Time+(US++Canada)| New+Delhi|Pretoria|Quito|Dublin|Moscow|Istanbul|Taipei|Casablanca|Hawaii|Mumbai| International+Date+Line+West|Tokyo|Ulaan+Bataar|Vienna|Osaka|Alaska|Chennai|Bern| Brasilia|Eastern+Time+(US++Canada)|Rome|Perth|La+Paz &chs=650×350&chtt=Time+Zones&chd=s:KDDyKcKDOcKDKDDDDDKDDKDDDDOKK9DDD&cht=p $

Ao colar a URL do código em um navegador, você obtém o resultado mostrado na figura abaixo.

Comportamento do usuário do Twitter

O Twitter contém um grande volume de dados que podem ser minerados para entender alguns elementos do comportamento dos usuários. Dois exemplos simples são analisá-los quando um usuário do Twitter enviar um tweet e de que aplicativo o usuário enviou o tweet. É possível usar os seguintes dois scripts simples para extrair e visualizar essas informações.

O código abaixo apresenta um script que percorre os tweets de um usuário particular (usando o método user_timeline ) e, a seguir, para cada tweet, extrai o dia particular no qual o tweet foi originado.  Use um hash simples novamente para acumular as contagens dos dias da semana e, a seguir, gere um gráfico de barras usando o Google Charts de forma similar ao exemplo anterior do fuso horário.

  • #!/usr/bin/env ruby
  • require “rubygems”
  • require “twitter”
  • require “google_chart”
  • screen_name = String.new ARGV[0]
  • dayhash = Hash.new
  • timeline = Twitter.user_timeline(screen_name, :count => 200 )
  • timeline.each do |t|
  • tweetday = t.created_at.to_s[0..2]
  • if dayhash.has_key?(tweetday)
  • dayhash[tweetday] = dayhash[tweetday] + 1
  • else
  • dayhash[tweetday] = 1
  • end
  • endGoogleChart::BarChart.new(‘300×200’, screen_name, :vertical, false) do |bc|
  • bc.data “Sunday”, [dayhash[“Sun”]], ‘00000f’
  • bc.data “Monday”, [dayhash[“Mon”]], ‘0000ff’
  • bc.data “Tuesday”, [dayhash[“Tue”]], ’00ff00′
  • bc.data “Wednesday”, [dayhash[“Wed”]], ’00ffff’
  • bc.data “Thursday”, [dayhash[“Thu”]], ‘ff0000’
  • bc.data “Friday”, [dayhash[“Fri”]], ‘ff00ff’
  • bc.data “Saturday”, [dayhash[“Sat”]], ‘ffff00’
  • puts bc.to_url
  • end

A figura abaixo fornece o resultado da execução do script tweet-days neste código para a conta developerWorks. Como mostrado, quarta-feira tende a ser o dia mais ativo de tweets, com sábado e domingo sendo os menos ativos.

O próximo script determina de que origem um usuário particular envia tweets. Há várias formas de enviar tweets e esse script não codifica todos eles. Como mostrado abaixo, use um padrão similar para extrair a linha de tempo para um dado usuário e, a seguir, tente decodificar a origem do tweet em um hash.

Use o hash posteriormente para criar um gráfico de setores circulares simples usando o Google Charts para visualizar os dados.

  • #!/usr/bin/env ruby
  • require “rubygems”
  • require “twitter”
  • require ‘google_chart’
  • screen_name = String.new ARGV[0]
  • tweetsource = Hash.new
  • timeline = Twitter.user_timeline(screen_name, :count => 200 )
  • timeline.each do |t|
  • if (t.source.rindex(‘blackberry’)) then
  • src = ‘Blackberry’
  • elsif (t.source.rindex(‘snaptu’)) then
  • src = ‘Snaptu’
  • elsif (t.source.rindex(‘tweetmeme’)) then
  • src = ‘Tweetmeme’
  • elsif (t.source.rindex(‘android’)) then
  • src = ‘Android’
  • elsif (t.source.rindex(‘LinkedIn’)) then
  • src = ‘LinkedIn’
  • elsif (t.source.rindex(‘twitterfeed’)) then
  • src = ‘Twitterfeed’
  • elsif (t.source.rindex(‘twitter.com’)) then
  • src = ‘Twitter.com’
  • else
  • src = t.source
  • end
  • if tweetsource.has_key?(src)
  • tweetsource[src] = tweetsource[src] + 1
  • else
  • tweetsource[src] = 1
  • end
  • endGoogleChart::PieChart.new(‘320×200’, “Tweet Source”, false) do |pc|
  • tweetsource.each do|source,count|
  • pc.data source.to_s, count
  • end
  • puts “\nPie Chart”
  • puts pc.to_url
  • end

A figura abaixo fornece uma visualização de um usuário no Twitter que tem um conjunto interessante de origens de tweets. O site tradicional do Twitter é usado com mais frequência, com um aplicativo para celular a seguir.

Gráfico de seguidores

O Twitter é uma imensa rede de usuários que forma um gráfico. Como visto nos scripts, é fácil percorrer seus contatos e, a seguir, percorrer os contatos deles. Isso forma a base de um grande gráfico, mesmo nesse nível. Para visualizar um gráfico, escolhi usar o software de visualização de gráficos GraphViz. No Ubuntu, é possível instalar facilmente essa ferramenta usando a seguinte linha de comando:

$ sudo apt-get install graphviz 

O script mostrado no código abaixo percorre os seguidores de um usuário e, a seguir percorre os seguidores deles. A única diferença real nesse padrão é a criação do arquivo formatado com pontos do GraphViz.

  • #!/usr/bin/env ruby
  • require “rubygems”
  • require “twitter”
  • require ‘google_chart’

  • screen_name = String.new ARGV[0]

  • tweetlocation = Hash.new

  • # Authenticate
  • Twitter.configure do |config|
  • config.consumer_key = ‘<consumer_key>’
  • config.consumer_secret = ‘<consumer_secret>’
  • config.oauth_token = ‘<oauth_token>’
  • config.oauth_token_secret = ‘<oauth_token_secret>’
  • end

  • my_file = File.new(“graph.dot”, “w”)

  • my_file.puts “graph followers {“
  • my_file.puts ” node [ fontname=Arial, fontsize=6 ];”

  • # Iterate followers, hash their location
  • followers = Twitter.followers(screen_name, :count=>10 ).users.each do |f|

  • # Only iterate if we can see their followers
  • if (f.protected.to_s != “true”)

  • my_file.puts ” \”” + screen_name + “\” — \”” + f.screen_name.to_s + “\””

  • followers2 = Twitter.followers(f.screen_name, :count =>10 ).users.each do |f2|

  • my_file.puts ” \”” + f.screen_name.to_s + “\” — \”” +
  • f2.screen_name.to_s + “\””

  • endendendmy_file.puts “}”

O GraphViz usa um formato de script simples para definir gráficos, que você emitirá como parte de sua enumeração dos usuários do Twitter. Como mostrado, você define um gráfico simplesmente especificando os relacionamentos dos nós. Execute o script da listagem acima nos resultados de um usuário em um arquivo dot para, a seguir, gerar uma imagem usando o GraphViz.

Primeiro, chame o script do Ruby para reunir os dados do gráfico (armazenado como graph.dot); depois, use o GraphViz para gerar a imagem do gráfico (aqui, usando circo, que especifica um layout circular). O processo de geração dessa imagem é definido da seguinte forma:

$ ./followers-graph.rb MTimJones $ circo graph.dot -Tpng -o graph.png 

A imagem resultante é mostrada na figura abaixo. Observe que os gráficos do Twitter tendem a ser grandes, portanto restringi o gráfico ao minimizar o número de usuários e seus seguidores a enumerar (conforme a opção :count no código acima).

 Informações de localização

Quando ativado, o Twitter coleta dados de geolocalização sobre você e seus tweets. Esses dados consistem em informações de latitude e longitude que podem ser usadas para determinar um usuário ou de onde um tweet foi originado.

Além disso, pesquisas podem incorporar essas informações para que possa identificar locais ou pessoas com base em uma localização definida ou em sua localização.

Nem todos os usuários ou tweets têm dados de geolocalização ativados (por questões de privacidade), mas essas informações servem como uma dimensão interessante para a experiência geral do Twitter. Vejamos um script que permite visualizar com dados de geolocalização, bem como outro que permite pesquisar com essas informações.

No primeiro script (mostrado no código abaixo), você obtém dados de latitude e longitude de um usuário (lembre-se da caixa delimitadora do segundo código). Apesar de a caixa delimitadora ser um polígono definindo a área representada para o usuário, simplifiquei e usei um ponto desses dados.

  • #!/usr/bin/env ruby
  • require “rubygems”
  • require “twitter”

  • Twitter.configure do |config|
  • config.consumer_key = ‘<consumer_key>
  • config.consumer_secret = ‘<consumer_secret>
  • config.oauth_token = ‘<oauth_token>
  • config.oauth_token_secret = ‘<token_secret>
  • end

  • screen_name = String.new ARGV[0]

  • a_user = Twitter.user(screen_name)

  • if a_user.geo_enabled == true

  • long = a_user.status.place.bounding_box.coordinates[0][0][0];
  • lat = a_user.status.place.bounding_box.coordinates[0][0][1];

  • my_file = File.new(“test.html”, “w”)

  • my_file.puts “<!DOCTYPE html>
  • my_file.puts “<html><head>
  • my_file.puts “<meta name=\”viewport\” content=\”initial-scale=1.0, user-scalable=no\”/>”
  • my_file.puts “<style type=\”text/css\”>”
  • my_file.puts “html { height: 100% }”
  • my_file.puts “body { height: 100%; margin: 0px; padding: 0px }”
  • my_file.puts “#map_canvas { height: 100% }”
  • my_file.puts “</style>”
  • my_file.puts “<script type=\”text/javascript\””
  • my_file.puts “src=\”http://maps.google.com/maps/api/js?sensor=false\”>”
  • my_file.puts “</script>”
  • my_file.puts “<script type=\”text/javascript\”>”
  • my_file.puts “function initialize() {“
  • my_file.puts “var latlng = new google.maps.LatLng(” + lat.to_s + “, ” + long.to_s + “);”
  • my_file.puts “var myOptions = {“
  • my_file.puts “zoom: 12,”
  • my_file.puts “center: latlng,”
  • my_file.puts “mapTypeId: google.maps.MapTypeId.HYBRID”
  • my_file.puts “};”
  • my_file.puts “var map = new google.maps.Map(document.getElementById(\”map_canvas\”),”
  • my_file.puts “myOptions);”
  • my_file.puts “}”
  • my_file.puts “</script>”
  • my_file.puts “</head>”
  • my_file.puts “<body onload=\”initialize()\”>”
  • my_file.puts “<div id=\”map_canvas\” style=\”width:100%; height:100%\”></div>”
  • my_file.puts “</body>”
  • my_file.puts “</html>”

  • elseputs “no geolocation data available.”

  • end

Com esses dados, gerei uma função JavaScript simples em um arquivo HTML simples. Esse código JavaScript interage com o Google Maps para apresentar um mapa superior dessa localização (com os dados de latitude e longitude extraídos do usuário do Twitter).

O script no código acima é executado simplesmente como:

$ ./where-am-i.rb MTimJones 

O arquivo HTML resultante é renderizado por meio de um navegador, como:

$ firefox test.html

Esse script pode falhar se não houver informações de localização disponíveis; mas, se ele for bem-sucedido, é gerado um arquivo HTML que pode ser lido por um navegador para renderizar o mapa.

A figura abaixo apresenta a imagem resultante do mapa, que mostra uma porção de Front Range do norte do Colorado, EUA.

Com a geolocalização, também é possível pesquisar o Twitter para identificar usuários e tweets relacionados a uma localização particular. A API Search do Twitter permite que informações de codificação geográfica restrinjam seus resultados.

O exemplo seguinte, mostrado no código abaixo, extrai dados de latitude e longitude para um usuário e, a seguir, usa esses dados para buscar tweets dentro de um raio de 5 milhas daquele local.

  • #!/usr/bin/env ruby
  • require “rubygems”
  • require “twitter”

  • Twitter.configure do |config|
  • config.consumer_key = ‘<consumer_key>’
  • config.consumer_secret = ‘<consumer_secret>’
  • config.oauth_token = ‘<oauth_token>’
  • config.oauth_token_secret = ‘<oauth_token_secret>’
  • end

  • screen_name = String.new ARGV[0]

  • a_user = Twitter.user(screen_name)

  • if a_user.geo_enabled == true

  • long = a_user.status.place.bounding_box.coordinates[0][0][0]
  • lat = a_user.status.place.bounding_box.coordinates[0][0][1]

  • Array tweets = Twitter::Search.new.geocode(lat, long, “5mi”).fetch

  • tweets.each do |t|

  • puts t.from_user + ” | ” + t.text

  • endend

O resultado do script acima é mostrado no código abaixo. Esse é um subconjunto dos tweets, dada a frequência de tweeters que existe.

$ ./tweets-local.rb MTimJones Breesesummer | @DaltonOls did he answer u LongmontRadMon | 60 CPM, 0.4872 uSv/h, 0.6368 uSv/h, 2 time(s) over natural radiation graelston | on every street there is a memory; a time and place we can never be again. Breesesummer | #I'minafight with @DaltonOls to see who will marry @TheCodySimpson I will marry him!!! :/ _JennieJune_ | ok I'm done, goodnight everyone! Breesesummer | @DaltonOls same _JennieJune_ | @sylquejr sleep well! Breesesummer | @DaltonOls ok let's see what he says LongmontRadMon | 90 CPM, 0.7308 uSv/h, 0.7864 uSv/h, 2 time(s) over natural radiation Breesesummer | @TheCodySimpson would u marry me or @DaltonOls natcapsolutions | RT hlovins: The scientific rebuttal to the silly Forbes release this morning: Misdiagnosis of Surface Temperatu... http://bit.ly/nRpLJl $

Indo além

Esse artigo apresentou uma série de scripts simples para extação de dados do Twitter usando a linguagem Ruby. A ênfase foi no desenvolvimento e apresentação de scripts simples para ilustrar as ideias fundamentais, mas é possível fazer muito mais. Por exemplo, também é possível usar a API para explorar as redes de seus amigos e identificar os usuários mais populares do Twitter que sejam de seu interesse. Outra área interessante é a mineração dos tweets em si, usando dados de geolocalização para entender comportamentos ou eventos com base em localização (como epidemias de gripes).

Esse artigo apenas introduziu o tema, mas sinta-se à vontade para comentar com seus próximos mash-ups. O Ruby e o gem do Twitter torna simples desenvolver mash-ups ou painéis úteis para suas necessidades de mineração de dados.

Recursos

Aprender

  • Web site oficial da linguagem é a fonte isolada para notícias, informações, releases, documentação e suporte da comunidade da linguagem Ruby. Dado o crescente uso do Ruby em estruturas da Web (como Ruby on Rails), também é possível conhecer as mais recentes vulnerabilidades de segurança e suas soluções.
  • O site de codificação social Github fornece a fonte original do gem do Twitter. Nesse site, é possível acessar o código fonte, a documentação e a lista de distribuição do gem do Twitter para o Ruby.
  • Registrar um aplicativo do Twitter é necessário para usar certos elementos da API do Twitter. O processo é gratuito e permite acessar alguns dos elementos mais úteis da API.
  • O tutorial da API JavaScript do Google Maps mostra como usar o Google Maps para renderizar mapas de vários tipos usando dados de geolocalização fornecidas pelo usuário. O JavaScript usado nesse artigo foi baseado no código de exemplo “Hello World” fornecido.
  • Zona de software livre do developerWorks fornece muitas informações sobre ferramentas de software livre e de como utilizar tecnologias de software livre.
  • developerWorks no Twitter: Siga-nos e siga esse autor em M. Tim Jones.
  • Demos on demand do developerWorks: acompanhe e saiba com demos que vão da instalação de produtos e de configuração para iniciantes a funcionalidades avançadas para desenvolvedores experientes.

Obter produtos e tecnologias

  • O gem do Twitter para Ruby , desenvolvido por John Nunemaker, fornece uma interface útil para o serviço Twitter que se integra de forma eficiente na linguagem Ruby.
  • A API Google Chart é um serviço útil que fornece a capacidade de criar gráficos ricos e complexos usando uma variedade de estilos e opções. Esse serviço fornece uma API por meio da qual resulta uma URL que é renderizada no site do Google.
  • O wrapper do Ruby para a API Google Chart fornece uma interface do Ruby para a API Google Charts pra a criação de gráficos úteis dentro do Ruby.

Discutir

  • comunidade do developerWorks: Conecte-se a outros usuários do developerWorks enquanto explora os blogs, fóruns, grupos e wikis voltados para desenvolvedores.

Até a próxima!!!

Uma resposta to “Mineração de dados com Ruby e Twitter”

  1. Grimaldo Says:

    Lito, obrigado meu amigo, você que é um grande colega!!!!


Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: