Criando um simples web crawler
Não faz muito tempo trabalhei na construção de web crawler, um
crawler pode ser definido como um software com um objetivo específico,
localizando uma informação ou algo o mesmo deve realizar alguma ação, na
época eu construi uma série de funções com objetivo de encontrar
diversos tipos de padrões e armazená-los, era um trabalho bem divertido,
pois, brincava com Shell, expressão regular entre outras.
Abordarei o software em duas partes, sendo o foco deste post a segunda:
- Localizador
- Coletor
Localizador
Sempre achei importante definir uma estrutura para o armazenamento dessas informações, no principio trabalhei com arquivo ‘.TXT’ mesmo, com o volume crescendo e outras frentes se abrindo fomos obrigados a migrar para uma estrutura mais robusta e optamos por um banco de dados mysql, basicamente nesta fase são armazenadas as URLs que deram origem ao evento, URLs de Destino, data e hora.
ORIGEM | URL | TIMESTAMP |
---|---|---|
http://www.abcdef.com | http://www.xpto.com/?id=1 | 1406385530 |
Certamente o arquivo ou a fonte de conteúdo que vai receber pode ter um ou dezenas de registros cujo o destino seja a mesma URL, você não vai querer perder tempo indexando o mesmo conteúdo, já o timestamp dependerá do tipo de informação que espera coletar, por exemplo, vou passar na mesma página a cada 30 dias, sendo assim, é importante atualizar o campo com a última visita do robô “Coletor”, bom, isso são ideias, existem várias formas de fazer isso e se procurar no github encontrará centenas.
Coletor
A mágica acontece aqui, tendo uma boa base o processo coletor pode iniciar seu trabalho, entrar em cada página armazenada pelo localizador e encontrar os padrões que está programado para encontrar, é exatamente este processo que tentarei demonstrar neste documento, não a parte da inteligência, pois, darei um objetivo especifico, exatamente um website (um único website), este foi escolhido por ser um problema recentemente encaminhado por um amigo, ele enfrentava um problema para pegar os dados após a paginação.
Bora lá.
Existem diversas formas de fazer a mesma coisa, algumas mais simples outras mais complexas, confesso que no momento que trabalhei com essa tecnologia, não tinha qualquer experiência, não conhecia outras ferramentas, mas sabia como entregar a informação, sendo assim, praticamente 95% dos meus scripts foram construídos em Shell script. Sim, é uma boa opção para montar algo assim, já que possui muitos comandos prontos como wget, sed, grep entre outros (não necessito nem falar que conhecer expressão regular ajuda muito). Bom, nem tudo são flores, com shell não era possível paginar, sendo necessário implementar um paginador para cada website que desejava coletar uma informação, alguns em ajax que tornavam o processo até mais simples, de qualquer forma, vai por mim, existem soluções melhores para coletar dados na web. Para tal irei utilizar uma ferramenta não muito convencional, mas extremamente eficiente para a tarefa, o Selenium. O selenium é um suite de aplicações para automatização de teste de interface e aqui iremos dar um outro objetivo ao mesmo, juntamente com Python
Instalando selenium
~# apt-get install python-pip
~# pip install selenium
O bacana é que será utilizado o próprio navegador para renderizar o site, pode ser mais lento, mas temos alguns ganhos com isso, pois, o selenium aguardará até que toda a página termine de renderizar para liberar o processo, podemos percorrer cada elemento, class ou id da página sem a criação de função adicional.
Abaixo a imagem do site que iremos trabalhar neste exemplo

Na próxima imagem temos os itens selecionados box da empresa, nome e o endereço exatamente o que iremos coletar.

Abaixo a explicação simples do código:
Source Code

from selenium import webdriver
from time import sleep
Importando os módulos necessários para o funcionamento do robo. def get_company_name(box):
Name = box.find_elements_by_class_name(‘fig-title’)
return Name[0].text, Name[1].text
def get_address(box):
Address = box.find_elements_by_class_name(‘fig-dates’)
return Address[0].text
Criei duas funções, ambas recebem como parâmetro um objeto que chamei de box, basicamente representa o block de cada empresa no site. firefox = webdriver.Firefox()
O webdriver é sem dúvida muito bacana, podendo ser utilizado com qualquer navegador, Chrome, Firefox, Safari entre outros.
firefox.get(
‘http://www.paginasamarillas.com.co/busqueda/informatica-bogota’
)
A página será carregada dentro do navegador magicamente. 😉 for pag in range(2, 6):
”’ GET all box from company ”’
all_box_company = firefox.find_elements_by_class_name(
‘company-stats’
)
for one_box in all_box_company:
print get_company_name(one_box)
print get_address(one_box)
firefox.execute_script(
“javascript:UpdateOrderResults(“+str(pag)+”,”,”);”
)
sleep(20)
O for é para definir a paginação, poderia elaborar um pouco melhor e
capturar todas ou até dinamicamente a próxima página, bom, não fiz
assim, a variável all_box_company armazena todos os blocks com class company-stats, ou seja, all_box_company é uma lista de objetos de company-stats, isso justifica o próximo for, que envia individualmente cada block para get_company_nome e get_addess e no final executa um script dentro da página para recarregar o ajax alimentando-a com os novos elementos, o sleep é apenas para aguardar o fim da renderização dos elementos.
Não existe uma forma de pegar as classes, id ou tags de uma página sem
olhar o source ok? Sendo assim, olhe o source da página para entender o
que foi feito acima.
firefox.close()
finaliza o processo e fecha o navegador.
Conclusão
Vimos o quanto é facil realizar a extração de conteúdo, dei uma
pequena base e com isso poderá evoluir em alguns conceitos, foi uma
ótima opção dos desenvolvedores do selenium ao juntar o webdriver a sua
estrutura, Python+Selenium+webdriver.
Se observar verá que escrevi pouco código, tarefa que não seria tão simples e outra linguagem sem o suporte do selenium.