Criando Web crawlers em Python – Parte I
Ir para: Criando Web Crawlers em Python – Parte II
Ir para: Criando Web Crawlers em Python – Parte III
Iniciemos com a definição de Web crawler:
Um Web crawler é um programa de computador que navega pela World Wide Web de maneira metódica e automatizada. [Wikipedia]
Os Web crawlers (ou simplesmente crawlers) têm um papel importante na nossa vida hoje. Como exemplos clássicos de Web crawlers, podemos citar o Google Bot, o Yahoo! Slurp e o MsnBot. Sem esses crawlers, não teríamos a busca do Google, do Yahoo! ou do Bing.
O objetivo dessa série de tutoriais não é ensinar criar crawlers de alta disponibilidade, alta performance e distribuídos mas mostrar como eles podem ser construidos sem muito custo ou complexidade, de forma que atenda uma necessidade específica. Entenda necessidade específica como download de imagens de um conjunto de páginas, um sistema de download de arquivos de hosts como o Rapidshare ou MegaUpload (sim, é possível!) ou uma busca e categorização de informações distribuídas entre diversos sites (como editais de concursos em portais).
Aspectos legais e ética de crawlers:
Antes de continuar lendo esta série, gostaria de informar que não é todo site que lhe dá permissão de acesso por meios de robores de busca. Procure sempre ler as políticas de uso e sempre respeite o robots.txt: se não é pra você crawlear determinada página, não o faça.
O processo:
Preste atenção aos componentes do crawler:
- Fila: pode conter uma ou mais URLs. Dependendo do tamanho da fila, a mesma pode estar no disco, ao invés de somente na memória.
- Downloader: geralmente costuma-se colocar um downloader multithreaded. No nosso primero exemplo vamos fazer um downloader singlethreaded para evitar complexidade.
- Parser: esse é o mais interessante. Ele vai extrair informações da página baixada pelo downloader segundo as especificações passadas pra ele. É pra ele que você irá dizer que quer extrair todas as imagens de uma determinada página.
- Storage: pode ser qualquer tipo de armazenamento em qualquer tipo de mídia. Não iremos persistir os dados nessa primeira parte do tutorial.
Nota-se que esse diagrama não representa um crawler de alta performance, pois ele mal diz sobre a arquitetura do mesmo, não diz sobre hardware, links de rede, paralelismo e tudo mais, mas serve com o intuito de explicar o básico do sistema.
Maos à obra: fazendo um downloader com uma fila simples
Para download de páginas e arquivos na Web, nós usaremos o urlib e a urlib2 do Python. Apesar das versões das libs, uma complementa a outra. Por exemplo, só se pode mudar os headers HTTP na urllib2 e o método urlencode só está disponível na urllib. Contudo, nós usaremos mais a urllib2. O código:
url = "http://www.google.com"
request = urllib2.Request(url)
response = urllib2.urlopen(request)
document = response.read()
print document
Execute esse código e se tudo der certo você verá o código fonte da página inicial do Google!
Bem, só ter o código fonte da página não é muito útil. Precisamos extrair informações dela. Uma forma de que podemos adotar é por Regex (expressão regular), mas usar regex dificultaria nosso trabalho e fugiríamos da idéia de deixar as coisas simples.
Um grande problema da Web hoje é que muitos desenvolvedores escrevem código (X)HTML mal formado e isso dificulta um pouco nossa vida. Felizmente isso não é um impedimento grave e podemos contorna-lo com o BeautifulSoup. O BeautifulSoup faz um excelente trabalho transformando o código de marcação (HTML, XML ou XHTML) em objetos que podem ser facilmente manipulados. De acordo com o esquema mostrado apresentado aqui, o BeautifulSoup faz parte do parser.
Façamos algo útil: vamos listar todos os links da página inicial do Google.
from BeautifulSoup import BeautifulSoup
url = "http://www.google.com"
request = urllib2.Request(url)
response = urllib2.urlopen(request)
document = response.read()
#normaliza o documento para que o mesmo seja acessível via objetos
soup = BeautifulSoup(document)
# retorna uma lista com todos os links do documento
links = soup.findAll('a')
for link in links:
print link
Fácil não?!
Se tudo correr bem, você deve ver uma saída igual a essa:
<a href="http://images.google.com.br/imghp?hl=pt-BR&tab=wi">Imagens</a><a href="http://video.google.com.br/?hl=pt-BR&tab=wv">Vídeos</a><a href="http://maps.google.com.br/maps?hl=pt-BR&tab=wl">Mapas</a><a href="http://news.google.com.br/nwshp?hl=pt-BR&tab=wn">Notícias</a><a href="http://www.orkut.com/Home.aspx?hl=pt-BR&tab=w0">Orkut</a><a href="http://mail.google.com/mail/?hl=pt-BR&tab=wm">Gmail</a><a href="http://www.google.com.br/intl/pt-BR/options/" style="text-decoration:none"><u>mais</u> »</a><a href="/url?sa=p&pref=ig&pval=3&q=http://www.google.com.br/ig%3Fhl%3Dpt-BR%26source%3Diglk&usg=AFQjCNEufhwNAC9POZqcS5r7r07CUPbvAA">iGoogle</a><a href="/preferences?hl=pt-BR">Configurações da pesquisa</a><a href="https://www.google.com/accounts/Login?hl=pt-BR&continue=http://www.google.com.br/">Fazer login</a><a href="/search?q=Vancouver+2010&ct=olympics10-sskating-hp&oi=ddle"><img src="/logos/olympics10-sskating-hp.png" width="523" height="170" border="0" alt="Vancouver 2010" title="Vancouver 2010" id="logo" onload="window.lol&&lol()" /></a><a href="/advanced_search?hl=pt-BR">Pesquisa avançada</a><a href="/language_tools?hl=pt-BR">Ferramentas de idiomas</a><a href="/intl/pt-BR/ads/">Soluções de publicidade</a><a href="/services/">Soluções empresariais</a><a href="/intl/pt-BR/about.html">Tudo sobre o Google</a><a href="http://www.google.com/ncr">Google.com in English</a><a href="/intl/pt-BR/privacy.html">Privacidade</a><a href="http://images.google.com.br/imghp?hl=pt-BR&tab=wi">Imagens</a><a href="http://video.google.com.br/?hl=pt-BR&tab=wv">Vídeos</a><a href="http://maps.google.com.br/maps?hl=pt-BR&tab=wl">Mapas</a><a href="http://news.google.com.br/nwshp?hl=pt-BR&tab=wn">Notícias</a><a href="http://www.orkut.com/Home.aspx?hl=pt-BR&tab=w0">Orkut</a><a href="http://mail.google.com/mail/?hl=pt-BR&tab=wm">Gmail</a><a href="http://www.google.com.br/intl/pt-BR/options/" style="text-decoration:none"><u>mais</u> »</a><a href="/url?sa=p&pref=ig&pval=3&q=http://www.google.com.br/ig%3Fhl%3Dpt-BR%26source%3Diglk&usg=AFQjCNEufhwNAC9POZqcS5r7r07CUPbvAA">iGoogle</a><a href="/preferences?hl=pt-BR">Configurações da pesquisa</a><a href="https://www.google.com/accounts/Login?hl=pt-BR&continue=http://www.google.com.br/">Fazer login</a><a href="/search?q=Vancouver+2010&ct=olympics10-sskating-hp&oi=ddle"><img src="/logos/olympics10-sskating-hp.png" width="523" height="170" border="0" alt="Vancouver 2010" title="Vancouver 2010" id="logo" onload="window.lol&&lol()" /></a><a href="/advanced_search?hl=pt-BR">Pesquisa avançada</a><a href="/language_tools?hl=pt-BR">Ferramentas de idiomas</a><a href="/intl/pt-BR/ads/">Soluções de publicidade</a><a href="/services/">Soluções empresariais</a><a href="/intl/pt-BR/about.html">Tudo sobre o Google</a><a href="http://www.google.com/ncr">Google.com in English</a><a href="/intl/pt-BR/privacy.html">Privacidade</a>
Na verdade, a linha
não retorna uma lista de strings, mas uma lista de objetos que representam tags em HTML (classe BeautifulSoup.Tag). Logo, há outras propriedades e métodos que podemos explorar. Digamos que você só queira as URLs dos links e não está interessado no texto ou na marcação. O nosso código ficaria assim:
from BeautifulSoup import BeautifulSoup
url = "http://www.google.com"
request = urllib2.Request(url)
response = urllib2.urlopen(request)
document = response.read()
#normaliza o documento para que o mesmo seja acessível via objetos
soup = BeautifulSoup(document)
# retorna uma lista com todos os links do documento
links = soup.findAll('a')
for link in links:
print link['href']
Como saída, você pode obter algo do tipo:
http://images.google.com.br/imghp?hl=pt-BR&tab=wi http://video.google.com.br/?hl=pt-BR&tab=wv http://maps.google.com.br/maps?hl=pt-BR&tab=wl http://news.google.com.br/nwshp?hl=pt-BR&tab=wn http://www.orkut.com/Home.aspx?hl=pt-BR&tab=w0 http://mail.google.com/mail/?hl=pt-BR&tab=wm http://www.google.com.br/intl/pt-BR/options/ /url?sa=p&pref=ig&pval=3&q=http://www.google.com.br/ig%3Fhl%3Dpt-BR%26source%3Diglk&usg=AFQjCNEufhwNAC9POZqcS5r7r07CUPbvAA /preferences?hl=pt-BR https://www.google.com/accounts/Login?hl=pt-BR&continue=http://www.google.com.br/ /search?q=Vancouver+2010&ct=olympics10-sskating-hp&oi=ddle /advanced_search?hl=pt-BR /language_tools?hl=pt-BR /intl/pt-BR/ads/ /services/ /intl/pt-BR/about.html http://www.google.com/ncr /intl/pt-BR/privacy.html
Como você pode ver, o BeautifulSoup é quase uma mãe quando o assunto é extrair informações de HTML
.
No próximo tutorial, eu abordarei usos mais avançados do BeautifulSoup e mostrarei como usar os métodos GET e POST e também mostrarei uma pequena aplicação para procurar e baixar arquivos do SourceForge.net. Até o próximo!


Gostei bastante.
não conhecia e achei bastante interessante
=]
dahora locão!!!
hehe
Diegão
1 Mar 10 at 22:31
Locão? Perdeu o medo mesmo, né? hehehehe.
Bom estudos pra vc aí
herberthamaral
2 Mar 10 at 01:04
[...] post anterior, eu mostrei como recuperar informações básicas de uma página da Web usando urllib, urllib2 e [...]
Criando Web crawlers em Python – Parte II « Herberth Amaral
7 Mar 10 at 11:08
Olá Herberth, tudo bem?
Eu tentei rodar o exemplo mas esta dando o erro:
No module Named BeautifullSoap
Estou usando o Python 3 no Ubuntu 9.10
Ja instalei o python 3All mas mesmo assim nada.
Alguma dica?
Parabens pelo material
Flávio Araújo
23 Mar 10 at 23:46
Opa,
Isso quer dizer que o BeautifulSoup não está instalado. Você pode instala-lo com o comando:
$sudo easy_install BeautifulSoup
Esse exemplo foi feito usando o Python 2.6.4, não tenho certeza se funcionará corretamente no Python 3.
De qq forma, boa sorte aí e avise se funcionar com Python 3
herberthamaral
24 Mar 10 at 00:59
[...] Ir para Criando Web crawlers em Python – Parte I [...]
Criando Web crawlers em Python – Parte II | Herberth Amaral
23 Mar 10 at 23:07
[...] Ir para Criando Web crawlers em Python – Parte I [...]
Criando Web crawlers em Python - Parte III | Herberth Amaral
23 Mar 10 at 23:11
Olá Herberth!
Como diz o nosso amigo ai à cima: Locão… hehe
Matéria bem interessante, estou usando-a como referência para o meu TCC, estou no final do curso de Sistemas de informação.
Até agora só havia encontrado, na maioria, teorias e conceitos sobre o assunto, o legal dessa matéria é que você vê a “coisa” funcionando…
Parabéns amigo!!!
Formagi
1 May 10 at 16:01
Opa, bacana. =)
Qual exatamente é o assunto em que vc vai fazer seu TCC?
Herberth Amaral
1 May 10 at 18:04
Opa Herbeth!
Acabei trocando as “bolas”…
Meu TCC será sobre “Distribuição de fichas, em sistemas de cobrança, usando IA e BI”.
Meu trabalho semestral de IA será sobre “Motores de Busca na WEB”.
Por isso acabei caindo nessa loucura toda aqui, vamos ver no que vai dar… se eu não ficar louco antes.. hehe
Mas é isso aí…
Grato pela ajuda de todos!
Abraços!
Formagi
3 May 10 at 00:11
[...] Web crawlers (distribuidos) em Python – Parte IVOutros posts da série:Parte IParte IIParte IIINa parte III eu mostrei como criar um simples sistema de recuperação de [...]
Criando Web crawlers (distribuidos) em Python – Parte IV | Herberth Amaral
6 May 10 at 10:31
[...] você acompanha este blog, deve conhecer as séries sobre crawling que aqui foram apresentadas (Parte 1, Parte 2, Parte 3, Parte 4). Por ser apenas uma evolução, mas não necessariamente uma [...]
Apresentando o Scrapy: Framework Python para crawling. | Herberth Amaral
6 Jul 10 at 13:32