Coletando dados de todo o site
Para coletar dados de todo o site, é necessário:
- Capturar dados de todas as páginas
- Enviar solicitações manualmante:
yield scrapy.Request(url, callback)- Resumo do uso de
yield: - Enviar itens para o pipeline usando
yield item - Enviar solicitações manuais usando
yield scrapy.Request(url, callback) - Enviar solicitações POST manualmente:
yield scrapy.FormRequest(url, formdata, callback)ondeformdataé um dicionário com os parâmetros da solicitação
import scrapy
from exemplo.items import ExemploItem
class SiteSpider(scrapy.Spider):
name = 'site'
start_urls = ['https://www.exemplo.com/']
url_template = 'https://www.exemplo.com/pagina=%d'
def parse(self, response):
itens = response.xpath('//div[@class="itens"]/li')
for item in itens:
titulo = item.xpath('.//h2/text()').get()
autor = item.xpath('.//span[@class="autor"]/text()').get()
visualizacoes = item.xpath('.//span[@class="views"]/text()').get()
novo_item = ExemploItem()
novo_item['titulo'] = titulo
novo_item['autor'] = autor
novo_item['visualizacoes'] = visualizacoes
yield novo_item
page_number = 2
while page_number <= 10:
new_url = self.url_template % page_number
yield scrapy.Request(url=new_url, callback=self.parse_pagina)
page_number += 1
def parse_pagina(self, response):
print(response.text)
Cinco componentes principais do Scrapy
- Motor (Engine)
- Gerencia o fluxo de dados e inicia as transações
- Scheduler
- Aceita as solicitações do motor, as armazena em uma fila e define a ordem de processamento
- Downloader
- Realiza a Download de conteúdo da web
- Spiders
- Extraem os dados relevantes das páginas
- Pipeline
- Processa os itens coletados, validnado, limpando e armazenando os dados
Trabalhando com parâmetros de solicitação
- Objetivo: Permitir coletas mais profundas
- Uso: Quando os dados necessários não estão na mesma página
- Mecanismo:
- Enviar parâmetros usando
yield scrapy.Request(url, callback, meta) - Receber parâmetros no callback usando
response.meta
import scrapy
from filmes.items import FilmeItem
class FilmeSpider(scrapy.Spider):
name = 'filmes'
start_urls = ['https://www.cinemas.com/filmes']
url_template = 'https://www.cinemas.com/filmes/pagina-%d'
pagina_atual = 1
def parse(self, response):
print(f'Coletando dados da página {self.pagina_atual}')
filmes = response.xpath('//div[@class="filme-lista"]/div')
for filme in filmes:
item = FilmeItem()
item['titulo'] = filme.xpath('.//h3/a/text()').get()
detail_url = filme.xpath('.//a/@href').get()
yield scrapy.Request(detail_url, callback=self.parse_detalhe, meta={'item': item})
if self.pagina_atual < 5:
self.pagina_atual += 1
new_url = self.url_template % self.pagina_atual
yield scrapy.Request(new_url, callback=self.parse)
def parse_detalhe(self, response):
item = response.meta['item']
descricao = response.xpath('//div[@class="descricao"]/text()').get()
item['descricao'] = descricao
yield item
Melhorando a eficiência do Scrapy
- Configurações no arquivo settings.py:
- Aumentar o número de requisições simultâneas:
CONCURRENT_REQUESTS = 100 - Reduzir o nível de logs:
LOG_LEVEL = 'INFO' - Desativar cookies:
COOKIES_ENABLED = False - Desativar retentaitvas:
RETRY_ENABLED = False - Definir timeout de download:
DOWNLOAD_TIMEOUT = 10
Pool de User-Agents
user_agents_pool = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:36.0) Gecko/20140701 Firefox/36.0',
'Opera/9.80 (Windows NT 6.2; Win64; x64) Presto/2.12.388 Version/12.18',
# Adicione mais User-Agents conforme necessário
]
Middleware no Scrapy
O middleware do Scrapy permite:
- Modificar headers de requisição
- Alterar URLs
- Definir proxies
import random
from scrapy import signals
class MeuMiddleware:
def process_request(self, request, spider):
request.headers['User-Agent'] = random.choice(user_agents_pool)
print(f'User-Agent usado: {request.headers["User-Agent"]}')
proxy = 'http://example.com:8080'
request.meta['proxy'] = proxy
print(f'Proxy definido: {proxy}')
return None
def process_response(self, request, response, spider):
return response
def process_exception(self, request, exception, spider):
print(f'Exceção ocorrida em: {request.url}')
return request
Exemplo prático: Coletando notícias do site de notícias
Análise:
- Cada seção carrega suas notícias dinamicamente
Configurações no settings.py:
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
ROBOTSTXT_OBEY = False
LOG_LEVEL = 'ERROR'
DOWNLOADER_MIDDLEWARES = {
'noticias.middleware.NoticiaMiddleware': 543,
}
ITEM_PIPELINES = {
'noticias.pipeline.NoticiaPipeline': 300,
}
Pipeline para armazenar em banco de dados:
import pymysql
class NoticiaPipeline:
def open_spider(self, spider):
self.conexao = pymysql.connect(
host='localhost',
port=3306,
user='root',
password='123456',
db='scrapy_noticias',
charset='utf8'
)
self.cursor = self.conexao.cursor()
def process_item(self, item, spider):
sql = """
INSERT INTO noticias (titulo, conteudo)
VALUES (%s, %s)
"""
try:
self.cursor.execute(sql, (item['titulo'], item['conteudo']))
self.conexao.commit()
except Exception as e:
print(f'Erro ao inserir dados: {e}')
self.conexao.rollback()
return item
def close_spider(self, spider):
self.cursor.close()
self.conexao.close()