Tutorial Scrapy
Autor: Leonardo Cesar Borges | Publicado: 2015-02-27T13:10:00-03:00

Fala pessoal, nesse post vou tentar repassar um pouco do que aprendi estudando Scrapy (Python) nos últimos dias.

O post vai descrever um spider básico que lista em um JSON todos os tópicos criados nas duas primeiras páginas do site guj.com.br.

Ambiente:

- Ubuntu 14.04
- Sublime text

Ferramentas utilizadas:
- Scrapy
- Python
- virtualenv


# Instalando e criando ambiente virutalenv

Para quem não conhece, virtualenv é uma ferramenta que isola seu ambiente. Muito útil para quem trabalha com mais de um projeto na mesma máquina ou para resolver problemas de permissões.

* Instalando virtualenv
$sudo pip install virtualenv

* Criando um novo ambiente
$virtualenv NomeDoAmbiente

* Ativando ambiente
$source ./NomeDoAmbiente/bin/activate







# Instalando scrapy no ambiente virtualenv

$sudo apt-get install libxml2-dev libxslt-dev

$sudo apt-get install python-lxml

$pip install scrapy

* Verificando instalação do scrapy, o comando abaixo deve exibir o caminho para o seu virtualenv
$which scrapy

Caso o comando não exiba o scrapy do virtualenv, você pode forçar a execução do scrapy apontando para bin/scrapy

# Criando novo projeto com scrapy
$scrapy startproject nomedoprojeto







# Criando spider com template basico
$scrapy genspider java guj.com.br


# Adicionando alguns parâmetros ao arquivo de settins.py

#para nao sobre carregar o site

DOWNLOAD_DELAY = 5

# evitar looping de recursividade

REDIRECT_MAX_TIMES = 5

#para evitar acesso remoto

TELNETCONSOLE_ENABLED = False

#definindo os pipelines

ITEM_PIPELINES = {

&nbsp;&nbsp;&nbsp; 'guj.pipelines.GujPipeline': 300,

&nbsp;&nbsp;&nbsp; 'guj.pipelines.JsonWithEncodingPipeline': 800

}


# Abaixo vamos alterar a classe de parser chamada pelo scrapy para extrair título dos posts do Guj

# -*- coding: utf-8 -*-

import scrapy

from guj.items import GujItem

#from scrapy.contrib.spiders import CrawlSpider, Rule

#from scrapy.contrib.linkextractors import LinkExtractor



class JavaSpider(scrapy.Spider):

&nbsp;&nbsp;&nbsp; name = "java"

&nbsp;&nbsp;&nbsp; allowed_domains = ["guj.com.br"]

&nbsp;&nbsp;&nbsp; #navega pelas duas primeiras páginas do guj

&nbsp;&nbsp;&nbsp; start_urls = ['http://www.guj.com.br/?p=%s' % page for page in xrange(0,2)]

&nbsp;&nbsp;&nbsp; #rules = (Rule(LinkExtractor(allow=('/?p=', )), callback='parse_item'),)

&nbsp;&nbsp; 





&nbsp;&nbsp;&nbsp; def parse(self, response):

&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;self.log('url: %s' % response.url)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for a in response.xpath('/html/body/div/section/ol/li/div/div/h3/a/text()'):

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;item = GujItem()

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;item['title'] = a.extract()

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;yield item


# Agora vamos definir os pipelines de tratamento após a captura do Item

# -*- coding: utf-8 -*-



# Define your item pipelines here

#

# Don't forget to add your pipeline to the ITEM_PIPELINES setting

# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html



import json

import codecs



class GujPipeline(object):

&nbsp;&nbsp;&nbsp; def process_item(self, item, spider):

&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;#remove os caracteres \n e \t

&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;item['title'] = item['title'].replace('\n','')

&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;item['title'] = item['title'].replace('\t','')

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return item





class JsonWithEncodingPipeline(object):



&nbsp;&nbsp;&nbsp; def __init__(self):

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.file = codecs.open('scraped_data_utf8.json', 'w', encoding='utf-8')



&nbsp;&nbsp;&nbsp; #pipeline para codificar o JSON extraido do scrapy para UTF-8, pois o scrapy cria

&nbsp;&nbsp;&nbsp; #o json no padrão unicode

&nbsp;&nbsp;&nbsp; def process_item(self, item, spider):

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; line = json.dumps(dict(item), ensure_ascii=False) + "\n"

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.file.write(line)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return item



&nbsp;&nbsp;&nbsp; def spider_closed(self, spider):

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.file.close()




# Rodando nosso scrapy passando o parâmetro -o e o nome do json de destino. O comando deve ser executado na pasta do arquivo scrapy.cfg:
$scrapy crawl java -o items.json


GitHub com o source completo do projeto