<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ruby Vault &#187; Scraping</title>
	<atom:link href="http://www.tbueno.com/blog/category/scraping/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.tbueno.com/blog</link>
	<description>Explorando o maravilhoso mundo de Ruby</description>
	<lastBuildDate>Tue, 24 Aug 2010 03:02:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Delicious-Ext Atualizado</title>
		<link>http://www.tbueno.com/blog/ruby/2009/08/delicious-ext-atualizado/</link>
		<comments>http://www.tbueno.com/blog/ruby/2009/08/delicious-ext-atualizado/#comments</comments>
		<pubDate>Thu, 06 Aug 2009 22:02:06 +0000</pubDate>
		<dc:creator>bueno</dc:creator>
				<category><![CDATA[Projetos]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Scraping]]></category>
		<category><![CDATA[Delicious]]></category>
		<category><![CDATA[Delicious-Ext]]></category>

		<guid isPermaLink="false">http://www.tbueno.com/blog/?p=231</guid>
		<description><![CDATA[Quando eu fiz um post descrevendo a extensão da API do Delicious feita com scraping, um dos riscos que eu citei era de o site mudar sua estrutura, fazendo com que os scripts de scraping quebrassem. Pois há dois dias atrás aconteceu, o Delicious sofreu reformulações e a implementação que eu tinha foi pro espaço. [...]]]></description>
			<content:encoded><![CDATA[<p>Quando eu <a href="http://www.tbueno.com/blog/scraping/2009/02/extendendo-apis-com-scraping/">fiz um post descrevendo a extensão da API</a> do Delicious feita com scraping, um dos riscos que eu citei era de o site mudar sua estrutura, fazendo com que os <em>scripts</em> de <em>scraping</em> quebrassem. </p>
<p>Pois há dois dias atrás aconteceu, o <a href="http://blog.delicious.com/blog/2009/08/delicious-homepage-gets-%e2%80%9cfresh%e2%80%9d.html">Delicious sofreu reformulações</a> e a implementação que eu tinha foi pro espaço.  </p>
<p>Já consertei todos os problemas e consegui implementar já algumas funções novas, como a busca por &#8220;Fresh links&#8221; que retornam páginas mais atuais, seguindo a tendência de <em>instant search</em> que anda sendo discutida bastante atualmente. Algumas features novas ainda não foram mapeadas, mas estas não afetam o funcionamento das atuais.</p>
<p>Hoje eu dei um <em>push</em> das correções pro Github e atualizei o <em>readme</em> para quem quiser usar. O código atualizado pode ser encontrado aqui:<br />
<a href="http://github.com/tbueno/delicious-ext/tree/master">http://github.com/tbueno/delicious-ext/tree/master</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.tbueno.com/blog/ruby/2009/08/delicious-ext-atualizado/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Acessando o Orkut com Ruby e Scraping</title>
		<link>http://www.tbueno.com/blog/ruby/2009/03/acessando-o-orkut-com-ruby-e-scraping/</link>
		<comments>http://www.tbueno.com/blog/ruby/2009/03/acessando-o-orkut-com-ruby-e-scraping/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 19:17:26 +0000</pubDate>
		<dc:creator>bueno</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Scraping]]></category>
		<category><![CDATA[Orkut]]></category>

		<guid isPermaLink="false">http://www.tbueno.com/blog/?p=109</guid>
		<description><![CDATA[Se você é brasileiro, provavelmente deve fazer parte do que foi chamado de &#8220;WTF Crazy Brazilian Invasion&#8220;, lá pelos idos de 2006/2007, ao site de relacionamentos Orkut. Quando assumimos a liderança no número de usuários do Orkut, logo um efeito colateral começou a se manifestar: o excesso de scams, spams e outras filhadaputices tão típicas [...]]]></description>
			<content:encoded><![CDATA[<p>Se você é brasileiro, provavelmente deve fazer parte do que foi chamado de &#8220;<strong>WTF Crazy Brazilian Invasion</strong>&#8220;, lá pelos idos de 2006/2007, ao site de relacionamentos Orkut. Quando assumimos a liderança no número de usuários do Orkut, logo um efeito colateral começou a se manifestar: o excesso de scams, spams e outras filhadaputices tão típicas de brasileiros e países do leste europeu.</p>
<p>Essa ploriferação do mal, fez com que o Google começasse a aprimorar a parte de segurança do site, tornando ele hoje um dos sub-sites do conglomerado mais difíceis de se acessar por vias &#8220;automatizadas&#8221;.</p>
<p>Mas que tipo de informação seria possível de obter do site?</p>
<h2>Acessando o Orkut com Ruby</h2>
<p>Uma das medidas adotadas pelo Google para evitar os bots que atazanavam a vida de todos, foi a adoção de chamadas via Ajax, muito mais difíceis de ser capturadas e entendidas. Passei um bom tempo tentando entender o fluxo de dados de login, através do firebug, mas sempre esbarrava em arquivos javascript como <a href="http://static4.orkut.com/js/gen/in_frame031.js">esse</a>, obviamente ofuscados de propósito.</p>
<p>Antigamente, alguns já haviam conseguido <a href="http://schf.uc.org/articles/2007/02/26/breaking-into-orkut-with-mechanize">quebrar</a> o Orkut com Ruby  e <em>scraping</em>, mas hoje os mesmos métodos não funcionam mais.</p>
<p>A solução encontrada para evitar as chamadas com Ajax foi acessar o &#8220;lado sem javascript&#8221; do site, no caso, a <a href="http://m.orkut.com">interface para dispositívos móveis do site</a>.</p>
<p><span id="more-109"></span></p>
<p>De cara, me deparei com a tela de login comum nos serviços do Google &#8211; que inclusive já possui uma<a href="http://code.google.com/apis/gdata/articles/gdata_on_rails.html"> api para Ruby</a>. Como o Orkut não faz parte dos serviços cobertos pela API oficial, tive que preencher o formulário de login usando o <a href="http://mechanize.rubyforge.org/mechanize/WWW/Mechanize.html">Mechanize</a>.</p>
<pre class="brush: ruby">
require 'mechanize'
require 'hpricot'

agent = WWW::Mechanize.new
page = @agent.get "https://www.google.com/accounts/ServiceLogin?service=orkut&#038;hl=en-US&#038;rm=false&#038;continue=http%3A%2F%2Fm.orkut.com%2FRedirLogin%3Fmsg%3D0%26page%3Dhttp%253A%252F%252Fm.orkut.com%252FHome&#038;cd=US&#038;nui=5&#038;btmpl=mobile&#038;ltmpl=mobile&#038;passive=true&#038;skipvpage=true&#038;sendvemail=false"

form = page.forms.first
form.Email = @email
form.Passwd = @pass
page = @agent.submit form
</pre>
<p>Não se assustem com a URL gigantesca. Ela é mostrada quando você tenta acessar algum serviço privado sem estar logado. Após o login, o site gerará uma URL intermediária de autenticação antes de redirecionar para a home do usuário propriamente dita. Esse fluxo é reproduzido da seguinte maneira:</p>
<pre class="brush: ruby">
#Call home page to get the temporary URL that google generates
page = @agent.get "http://m.orkut.com/Home"
#Try to access the temporary URL to pass the authentication token
page = @agent.get page.meta[0].uri.to_s
</pre>
<h2>Lendo os Scraps Recebidos Usando Ruby</h2>
<p>Após os passos anteriores, conseguiremos acesso ao conteúdo da página. Depois, é só questão de mandar ver no scraping para obter as informações necessárias. </p>
<p>O código final é mostrado abaixo, e também pode ser <a href="http://gist.github.com/77639">acessado no gist</a>. Sempre é bom lembrar que ele foi feito às pressas e está sujeito a erros e melhorias.</p>
<pre class="brush: ruby">
require 'mechanize'
require 'hpricot'

class Orkut

  def initialize(email, pass)
    @agent = WWW::Mechanize.new
    @email = email
    @pass = pass
  end

  def print_scraps
    page = scrap_page
    scraps = page.search "div[@class='mblock']/div"
    scraps.each do |l|
      parts = Hpricot(l).inner_html.split("\n")
      puts "Name: #{parts[1]}"
      puts "Date: #{parts[3]}"
      puts "Message: "
      parts[4..parts.size-2].each {|line| puts line}
      puts "-" * 50
   end
  end

  private

  def scrap_page
    log_in
    #Call home page to get the temporary URL that google generates
    page = @agent.get "http://m.orkut.com/Home"
    #Try to access the temporary URL to pass the authentication token
    page = @agent.get page.meta[0].uri.to_s
    #Now, with authentication ready we can access the content
    page = @agent.get "http://m.orkut.com/Scrapbook"
  end

  def log_in
    page = @agent.get "https://www.google.com/accounts/ServiceLogin?service=orkut&#038;hl=en-US&#038;rm=false&#038;continue=http%3A%2F%2Fm.orkut.com%2FRedirLogin%3Fmsg%3D0%26page%3Dhttp%253A%252F%252Fm.orkut.com%252FHome&#038;cd=US&#038;nui=5&#038;btmpl=mobile&#038;ltmpl=mobile&#038;passive=true&#038;skipvpage=true&#038;sendvemail=false"

    form = page.forms.first
    form.Email = @email
    form.Passwd = @pass
    page = @agent.submit form
  end
end

o = Orkut.new('your_email@gmail.com', 'your_pass')
o.print_scraps
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.tbueno.com/blog/ruby/2009/03/acessando-o-orkut-com-ruby-e-scraping/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Extendendo APIs Com Scraping</title>
		<link>http://www.tbueno.com/blog/scraping/2009/02/extendendo-apis-com-scraping/</link>
		<comments>http://www.tbueno.com/blog/scraping/2009/02/extendendo-apis-com-scraping/#comments</comments>
		<pubDate>Mon, 16 Feb 2009 19:49:06 +0000</pubDate>
		<dc:creator>bueno</dc:creator>
				<category><![CDATA[Scraping]]></category>
		<category><![CDATA[APIs]]></category>

		<guid isPermaLink="false">http://www.tbueno.com/blog/?p=52</guid>
		<description><![CDATA[APIs públicas são uma das coisas mais bacanas da internet, a força propulsora da revolução web 2.0. A possibilidade da criação de mashups através de dados disponibilizados publicamente por sites como Flickr, NYTimes, Digg e outros, nos permite uma possibilidade de combinações limitadas apenas à nossa imaginação. Porém, como nem tudo são flores, nem sempre [...]]]></description>
			<content:encoded><![CDATA[<p>APIs públicas são uma das coisas mais bacanas da internet, a força propulsora da revolução web 2.0. A possibilidade da criação de mashups através de dados disponibilizados publicamente por sites como <a href="http://www.flickr.com/">Flickr</a>, <a href="http://www.nytimes.com/">NYTimes</a>, <a href="http://digg.com">Digg</a> e outros, nos permite uma possibilidade de combinações limitadas apenas à nossa imaginação. Porém, como nem tudo são flores, nem sempre os sites que disponibilizam seus dados fornecem 100% das funcionalidades oferecidas no próprio site em si. Na verdade, nem deveriam.</p>
<p>Como faríamos para extender as possibilidades fornecidas por estas Apis?</p>
<h2>Scraping</h2>
<p>De acordo com o Wikipedia:</p>
<blockquote><p>&#8220;Web scraping (or Web harvesting, Web data extraction) is a computer technique of extracting information from websites using specially coded software programs. Usually, such software programs simulate human exploration of the Web by either implementing the low-level Hypertext Transfer Protocol (HTTP), or embedding certain full-fledged Web browsers, such as the Internet Explorer (IE) and the Mozilla Web browser.&#8221;</p></blockquote>
<p>Resumindo de maneira mais técnica, (X)HTML é no fundo XML. Ao navegarmos pelo conteúdo de uma página, podemos extrair informações através de parsing desse conteúdo. Existem diversas ferramentas, tanto de parsing quanto de scraping:</p>
<p>Scraping</p>
<ul>
<li> ScRUBYt</li>
<li>Mechanize</li>
</ul>
<p>Parsing</p>
<ul>
<li> Hpricot</li>
<li>Nokogiri</li>
<li>REXML</li>
</ul>
<p>Neste exemplo, utilizarei o Hpricot, por razões pessoais. Nunca parei para avaliar critérios como velocidade, facilidade, etc&#8230;</p>
<p><span id="more-52"></span></p>
<h2>Extendendo API do Delicious</h2>
<p>O site Delicious é uma das mais úteis ferramentas disponíveis na web. É um site que, ao meu ver, é bem definido em duas partes: personal bookmarking e social bookmarking. Na primeira, você o utiliza como um gerenciador centralizado de bookmarks, salvando tudo o que ver pela frente e organizando através de tags e bundles. Na segunda opção, você utiliza os recursos como busca em bookmarks de outros usuários, ranking de links mais votados( a la digg), entre outros.</p>
<p>Ambas as opções são ótimas e se complementam, porém, a API do Delicious nos fornece apenas métodos de acesso à parte &#8220;personal&#8221; dos bookmarks. E quanto à parte &#8220;social&#8221;?</p>
<h2>Trazendo o &#8220;Social&#8221; Para o Bookmarking</h2>
<p>Ao consultarmos a<a title="Delicious API" href="http://delicious.com/help/api"> documentação da API do Delicious</a>, percebemos que os métodos disponíveis na API são de escopo do usuário, permitindo gerenciar os bookmarks pessoais através de mensagens HTTP:</p>
<ul class="toc">
<li><a href="http://delicious.com/help/api#update">Update</a>
<ul>
<li><a href="http://delicious.com/help/api#posts_update">posts/update</a> &#8211; Check to see when a user last posted an item.</li>
</ul>
</li>
<li><a href="http://delicious.com/help/api#posts">Posts</a>
<ul>
<li><a href="http://delicious.com/help/api#posts_add">posts/add</a> &#8211; add a new bookmark</li>
<li><a href="http://delicious.com/help/api#posts_delete">posts/delete</a> &#8211; delete an existing bookmark</li>
<li><a href="http://delicious.com/help/api#posts_get">posts/get</a> &#8211; get bookmark for a single date, or fetch specific items</li>
<li><a href="http://delicious.com/help/api#posts_dates">posts/dates</a> &#8211; list dates on which bookmarks were posted</li>
<li><a href="http://delicious.com/help/api#posts_recent">posts/recent</a> &#8211; fetch recent bookmarks</li>
<li><a href="http://delicious.com/help/api#posts_all">posts/all</a> &#8211; fetch all bookmarks by date or index range</li>
<li><a href="http://delicious.com/help/api#posts_all_hashes">posts/all?hashes</a> &#8211; fetch a change detection manifest of all items</li>
<li><a href="http://delicious.com/help/api#posts_suggest">posts/suggest</a> &#8211; fetch popular, recommended and network tags for a specific url</li>
</ul>
</li>
<li><a href="http://delicious.com/help/api#tags">Tags</a>
<ul>
<li><a href="http://delicious.com/help/api#tags_get">tags/get</a> &#8211; fetch all tags</li>
<li><a href="http://delicious.com/help/api#tags_delete">tags/delete</a> &#8211; delete a tag from all posts</li>
<li><a href="http://delicious.com/help/api#tags_rename">tags/rename</a> &#8211; rename a tag on all posts</li>
</ul>
</li>
<li><a href="http://delicious.com/help/api#bundles">Tag Bundles</a>
<ul>
<li><a href="http://delicious.com/help/api#tags_bundles_all">tags/bundles/all</a> &#8211; fetch tag bundles</li>
<li><a href="http://delicious.com/help/api#tags_bundles_set">tags/bundles/set</a> &#8211; assign a set of tags to a bundle</li>
<li><a href="http://delicious.com/help/api#tags_bundles_delete">tags/bundles/delete</a> &#8211; delete a tag bundle</li>
</ul>
</li>
</ul>
<p>Mas tão útil quando gerenciar o seu bookmark é dar uma espiada no que anda rolando de interessante, através de listas como a de links populares. Então, vamos colocar a mão na massa para criarmos novos métodos de acesso ao delicious.</p>
<p>Os métodos que serão criados nessa primeira versão são:</p>
<ul>
<li> Popular</li>
<li>Hot List</li>
<li> Recent</li>
<li> Search</li>
</ul>
<p>Utilizando o indispensável <a href="http://getfirebug.com/">Firebug</a>, conseguiremos descobrir a hierarquia dos objetos da página. No exemplo abaixo, consigo achar os elementos que representam o título e o link de cada url listada.</p>
<p><center><img class="aligncenter size-medium wp-image-53" title="delicious1" src="http://www.tbueno.com/blog/wp-content/uploads/2009/02/delicious1-300x147.png" alt="delicious1" width="300" height="147" /></center></p>
<p>Tanto o link, quanto o título mostrados na imagem acima podem ser capturado, com o uso do HPricot, através de parsing dos elementos contidos dentro da div da classe &#8220;data&#8221;:</p>
<pre class="brush: ruby">#Assumindo que 'result' é o trecho da página que representa cada bookmark mostrado na página
text = (result/"div[@class='data']/h4/a[@href").first.inner_text
url =  (result/"div[@class='data']/h4/a[@href").first['href']</pre>
<p>Dessa maneira, ao iterar sobre cada item da lista, ao final já teremos no mínimo uma lista de links interessantes para mostra. Outras buscas devem ser feitas para cada elemento que queiramos adicionar aos resultados finais, como autor do link, número de pessoas que salvaram e tags.</p>
<p>O autor por sua vez, pode ser consultado da seguinte maneira:</p>
<pre class="brush: ruby">name = (result/"div[@class='meta']/span/a[@class='user").first['href'].gsub("/", "")</pre>
<p>E seguindo nesse procedimento, vamos recheando a nossa pseudo-api. O processo é braçal mesmo, dividido nas seguintes partes:</p>
<p>1. Acessar a URL a ser analisada, através do Firefox<br />
2. Descobrir os elementos DOM de cada elemento que queremos salvar<br />
3. Traduzir a consulta para alguma forma que o Hpricot reconheça (nos exemplos, utilizo XPath)<br />
4. Juntar tudo com métodos publicos de acesso com Ruby.</p>
<h2>Resultados</h2>
<p>Após o desenvolvimento da API, podemos testar os outputs apresentados para ver como ficou o funcionamento final. Caso queiram brincar,<a> o código está disponível no Github</a>.</p>
<p>Confiram como fica uma consulta a 5 dos links mais populares do momento no delicious:</p>
<pre class="brush: ruby">d = Delicious::Collector.new
links = d.popular
links[1..5].each do |link|
  puts '------------------------------------------'
  puts "Text: #{link.text}"
  puts "URL: #{link.url}"
  puts "People: #{link.people}"
  puts "Posted By: #{link.posted_by.name}"
  puts "Tags:  #{link.tags * ','}"
end</pre>
<p><code><br />
######## Resultado ############</code></p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Text: 99 ways to make your computer blazingly fast<br />
URL: http://helpdeskgeek.com/windows-xp-tips/99-ways-to-make-your-computer-blazingly-fast/comment-page-1/<br />
People: 476<br />
Posted By: jimbeau<br />
Tags:  windows,computer,tips,performance,speed<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Text: 5 Ways to Instantly Write Better CSS &#8211; NETTUTS<br />
URL: http://nettuts.com/tutorials/html-css-techniques/5-tips-to-writing-better-css/<br />
People: 280<br />
Posted By: ani625<br />
Tags:  css,tips,webdesign,design,webdev<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Text: Facebook&#8217;s New Terms Of Service: &#8220;We Can Do Anything We Want With Your Content. Forever.&#8221;<br />
URL: http://consumerist.com/5150175/facebooks-new-terms-of-service-we-can-do-anything-we-want-with-your-content-forever<br />
People: 352<br />
Posted By: mlanger<br />
Tags:  facebook,privacy,copyright,legal,socialnetworking<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Text: 40+ Useful &amp; Handy Web Designer’s Web Services &amp; Tools | Noupe<br />
URL: http://www.noupe.com/tools/40-useful-handy-web-designers-web-services-tools.html<br />
People: 566<br />
Posted By: anadeixis<br />
Tags:  webdesign,tools,resources,design,reference<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Text: 50 Tutorials To Get You Started With Gimp | LinuxHaxor.net<br />
URL: http://www.linuxhaxor.net/2009/02/09/50-tutorials-to-get-you-started-with-gimp/<br />
People: 251<br />
Posted By: pavs<br />
Tags:  gimp,tutorial,tutorials,graphics,linux</p>
<p>Bacana, não?</p>
<h2>Pontos Negativos da Abordagem</h2>
<p>Na verdade, eu utilizar scraping em um site, estamos de certa forma o hackeando &#8211; no &#8220;bom&#8221; sentido do termo -, aonde informações são adquiridas na base da força bruta. Em sites aonde existem APIs públicas, se parte das informações não estão disponveis, provavelmente isso se deve a uma decisão arquitetural ou de direito de propriedade. Por esses e outros motivos, <strong>não é recomendado o uso desta abordagemna criação de ferramentas comerciais</strong>.</p>
<p>Além disso, como scraping se fundamenta diretamente na navegação de uma estrutura definida, o funcionamento de sua aplicação depende diretamente da manutenção desta estrutura por parte do site que você efetua o scraping. Um exemplo real ocorreu quando, no ano passado, o site do delicious passou por reformulações fazendo com que esta extenção que eu criei parasse de funcionar em cerca de 70% das funções.</p>
<h2>Considerações Finais</h2>
<p>Com um pouquinho mais de esforço é possível, por exemplo, criar um sistema de widget semelhantes <a href="http://digg.com/add-digg">aos do Digg </a>, para ser adicionado à um blog pessoal. O resto fica a cabo da imaginação do desenvolvedor. A internet é uma grande fonte de informações espalhadas e cabe a nós utilizarmos a imaginação para a criação de novas maneiras de coletar e apresentar dados. Scraping é bacana, mas vicia. Use com moderação.</p>
<p>Código fonte: <a href="http://github.com/tbueno/delicious-ext/tree/master">http://github.com/tbueno/delicious-ext/tree/master</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.tbueno.com/blog/scraping/2009/02/extendendo-apis-com-scraping/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
