Sempre algum amigo meu me pergunta sobre como extrair informações de sites. Os objetivos são os mais diversos: obter lista de preços de sites concorrentes, conseguir telefones ou email e um monte de outros interesses. Dão nomes até engraçados aos programas/scripts que desejam. Já escutei "Chupa cabra", "Chupizque" e por ai vai. Sempre fiz scripts para "Chupinhar" informações em sites em Perl e até em Python. Mas recentemente tenho utilizado o Scrapy. O objetivo desse post e ajudar meus amigos e quem quiser a iniciar com o Scrapy. De fato, ele é muito fácil de usar.
O que é o Scrapy?
O Scrapy é um webcrawler muito rápido escrito e programável em Python. As características do Scrapy que mais chamam a atenção são:
- simplicidade - ele é muito simples de usar e automatiza várias tarefas comuns neste tipo de trabalho;
- produtividade - nunca tive a experiência de usar um webcrawler onde tão rapidamente eu obtivesse algum resultado;
- velocidade - provavelmente por utilizar o Python Twisted, que toma conta do IO de forma assíncrona, o Scrapy é muito rápido
Instalação
Se você esta utilizando Linux, de forma geral, não é interessante utilizar os sistemas de pacotes nativos. Nestes casos o Scrapy costumam estar em versões antigas. O comum é utilizarmos o Python pip.
Instale o Scrapy com o comando:
pip install Scrapy
Nosso alvo
![]() |
Screenshot do www.citebem.com.br |
Pra brincadeira ficar séria, vamos criar um projeto e coloca-lo pra funcionar. O site escolhido foi o Citebem(http://www.citebem.com.br). Esse é um site de frases famosas separadas por autores e assuntos. Iremos extrair todas as frases desse site.
Criando o projeto
Para iniciar nosso projeto, basta um comando que o scrapy já cria um modelo básico que podemos completar.
scrapy startproject citebem
Isto cria um diretório chamado "citebem". Este será nosso diretório de trabalho. Assim:
cd citebem
Para ver o conteúdo desse diretório, digite:
find .
A saída será algo como:
. ./citebem ./citebem/spiders ./citebem/spiders/__init__.py ./citebem/pipelines.py ./citebem/items.py ./citebem/__init__.py ./citebem/settings.py ./scrapy.cfg
Criando um spider
Agora devemos criar um spider. Esse é o objeto que irá, de verdade, navegar no site alvo. A tarefa também é muito simples, basta dar o comando:
scrapy genspider c1 citebem.com.br
Isto irá criar um novo arquivo chamado "c1.py" no dirétorio "citebem/spiders/". O parâmetro "c1" diz ao comando o nome da classe e arquivos que serão criados. O parâmetro "citebem.com.br" diz qual domínio é nosso alvo.
Localizando as frases
Chegou a hora da gente saber melhor o que quer. Navegando no site alvo, vemos que cada frase está em uma página com o seguinte esquema de url: "/frases/frase/frases-[Algo que identifica a frase]". Vemos, também, que em todas as frases temos o seu texto e o nome do seu autor.
![]() |
Página com frase |
Completando Item .py
A Classe "Item" tem um papel importante no Scrapy. Ela é o nosso gabarito e deve descrever os dados que queremos extrair. Quando criada o arquivo items.py tem o seguinte conteúdo:
# Define here the models for your scraped items # # See documentation in: # http://doc.scrapy.org/en/latest/topics/items.html from scrapy.item import Item, Field class CitebemItem(Item): # define the fields for your item here like: # name = Field() pass
Alteraremos para:
from scrapy.item import Item, Field class CitebemItem(Item): frase = Field() autor = Field()
Isso mostrar que estamos interessados no conteudo da frase e no seu autor.
XPath no Chrome
Depois de conhecer as páginas de onde as informações serão extraidas e de definir quais informações queremos, agora é hora de aprender a encontra-las dentro das páginas.
O Scrapy utiliza seletores de conteúdo em XPath. A idéia do XPath é endereçar o conteúdo. O melhor da brincadeira é que nem precisamos aprender muita coisa de XPath. A dica é utilizar o Google Chrome.
Dentro do Google Chrome, em uma página que queremos obter os conteudos devemos seguir alguns passos:
Dentro do Google Chrome, em uma página que queremos obter os conteudos devemos seguir alguns passos:
- clique com o botão direito do mouse sobre o conteudo que queremos o endereço XPath;
- no menu que aparece, clique em "Inspect Element";
- Ira aparecer o informações mostrando a estrutura da página;
Inspect mostrando estrutura da página - Localize novamente o conteúdo que desejamos (no caso, a frase);
- clique com o botão direito sobre o conteúdo dentro da estrutura da página exibida;
- agora clique em "Copy XPath"
- pronto o seletor/endereço XPath está na sua área de transferência e basta um Ctrl-v para resgatá-lo.
Testando XPath no Scrapy Shell
O Scrapy fornece mais uma ferramenta muito prática, uma shell. Para usar devemos digitar:
Agora podemos testar nossos seletores XPath. Abaixo segue uma sessão nessa shell:
scrapy shell http://www.citebem.com.br/frases/frase/frases-550
>>> sel.xpath('//*[@id="main"]/div[1]/div[2]/blockquote/p') [A vida \xe9 maravilhosa se n\xe3o se tem me'>] >>> sel.xpath('//*[@id="main"]/div[1]/div[2]/blockquote/p').extract() [u'A vida \xe9 maravilhosa se n\xe3o se tem medo dela.
'] >>> sel.xpath('//*[@id="main"]/div[1]/div[2]/blockquote/p/text()').extract() [u'A vida \xe9 maravilhosa se n\xe3o se tem medo dela.'] >>> sel.xpath('//*[@id="main"]/div[1]/div[2]/blockquote/p/text()').extract()[0] u'A vida \xe9 maravilhosa se n\xe3o se tem medo dela.'
Pronto, agora temos a linha de código python que obtem a frase de uma página.
Os dois trechos de códigos destacados, dizem:
Esta linha ordena ao scrapy que execute o spider c1. Uma saída extensa deve ser mostrada. Nas linhas finais vemos um relátorio com estatísticas da execução. Um informação deve chamar a atenção "'item_scraped_count': 2,". Somente duas frases são extraidas do site. Algo ainda não está funcionando como queremos.
A nova regra diz pra seguir todos os links que casam com "autores/", mas não deve processar as páginas nestas URLs.
Testando novamente o spider, vemos que as frases estarão sendo processadas corretamente.
Espero que estas dicas sejam úteis. T+.
Codificando o spider
Temos agora que alterar o c1.py.
from scrapy.selector import Selector from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor from scrapy.contrib.spiders import CrawlSpider, Rule from citebem.items import CitebemItem class C1Spider(CrawlSpider): name = 'c1' allowed_domains = ['citebem.com.br'] start_urls = ['http://www.citebem.com.br/'] rules = ( Rule(SgmlLinkExtractor(allow=r'frases/'), callback='parse_item', follow=True), ) def parse_item(self, response): sel = Selector(response) i = CitebemItem() i['frase'] = sel.xpath('//*[@id="main"]/div[1]/div[2]/blockquote/p/text()').extract()[0] i['autor'] = sel.xpath('//*[@id="main"]/div[1]/div[2]/blockquote/small/a/text()').extract()[0] return i
Os dois trechos de códigos destacados, dizem:
- A regra para o spider, nesta regra é dito que as URLs que casam com "frases/" devem ser seguidas e processadas com o método "parse_item"
- O objeto CitebemItem é preenchido com os conteudos extraídos da página.
scrapy crawl c1
Colocando regras pra autores
O Scrapy é muito esperto e pode seguir os links encontrados nas páginas buscadas para percorrer um site. Mas precisamos informar como faze-lo. A única regra que usamos diz pra seguir URLs que casam com "/frases" e extrair o conteúdo delas com o método "parse_item". Se olharmos para a página principal do CiteBem, de fato, ela só tem dois links que casam com a regra. A solução seria criar uma nova regra. O código do c1 ficará assim:
from scrapy.selector import Selector
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.contrib.spiders import CrawlSpider, Rule
from citebem.items import CitebemItem
class C1Spider(CrawlSpider):
name = 'c1'
allowed_domains = ['citebem.com.br']
start_urls = ['http://www.citebem.com.br/']
rules = (
Rule(SgmlLinkExtractor(allow=r'frases/'), callback='parse_item', follow=True),
Rule(SgmlLinkExtractor(allow=r'autores/'), follow=True),
)
def parse_item(self, response):
sel = Selector(response)
i = CitebemItem()
i['frase'] = sel.xpath('//*[@id="main"]/div[1]/div[2]/blockquote/p/text()').extract()[0]
i['autor'] = sel.xpath('//*[@id="main"]/div[1]/div[2]/blockquote/small/a/text()').extract()[0]
return i
A nova regra diz pra seguir todos os links que casam com "autores/", mas não deve processar as páginas nestas URLs.
Testando novamente o spider, vemos que as frases estarão sendo processadas corretamente.
Extraindo CSV
Pra fechar com chave de ouro vamos utilizar o que fizemos para criar um arquivo .cvs contendo as frases extraídas. Basta alterar um pouca o último comando utilizado. Digite:scrapy crawl c1 -o frases.csv -t csv
Espero que estas dicas sejam úteis. T+.