Ir para o conteúdo

Ambiente de desenvolvimento

Criação do projeto Scrapy e instalação das dependências

Considerando que você tem o Python instalado no seu computador, podemos começar a criar nosso projeto Scrapy.

  • Crie um diretório de trabalho
$ Execução no terminal!
mkdir pybr24
cd pybr24
  • Criando e ativando a virtualenv
$ Execução no terminal!
python3 -m venv .venv
source .venv/bin/activate
$ Execução no terminal!
python3 -m venv .venv
myenv\Scripts\activate
  • Instalando o Scrapy na virtulenv
$ Execução no terminal!
pip install scrapy # (1)!
scrapy # (2)!
  1. Instalando o Scrapy
  2. Verificando a instalação do Scrapy

A resposta do comando no terminal deve ser parecida com essa:

Resposta do comando `scrapy`
Scrapy 2.11.2 - no active project

Usage:
  scrapy <command> [options] [args]

Available commands:
  bench         Run quick benchmark test
  fetch         Fetch a URL using the Scrapy downloader
  genspider     Generate new spider using pre-defined templates
  runspider     Run a self-contained spider (without creating a project)
  settings      Get settings values
  shell         Interactive scraping console
  startproject  Create new project
  version       Print Scrapy version
  view          Open URL in browser, as seen by Scrapy

  [ more ]      More commands available when run from project directory

Use "scrapy <command> -h" to see more info about a command

No terminal aparece uma lista de comandos do Scrapy e descrição para ajudar a entender o que cada um faz. Agora temos certeza que ocorreu tudo bem com a instalação do Scrapy. Vamos criar nosso projeto para extrair dados do Shop ecommerce.

$ Execução no terminal!
scrapy startproject tutorial # (1)!
  1. Criando um projeto Scrapy de nome tutorial

A resposta do comando no terminal deve ser parecida com essa:

Resposta do comando `scrapy startproject tutorial`
New Scrapy project 'tutorial', using template directory '/Users/lidymonteiro/Projetos/pybr24/.venv/lib/python3.12/site-packages/scrapy/templates/project', created in:
    /Users/lidymonteiro/Projetos/pybr24/tutorial

You can start your first spider with:
    cd tutorial
    scrapy genspider example example.com

Esse comando cria um projeto Scrapy de nome tutorial em uma pasta/diretório e dá orientações de como podemos criar a primeira spider.

Vamos analisar a estrutura criada pelo Scrapy para o projeto.

Resposta do comando `tree`
.
└── tutorial # (1)!
    ├── scrapy.cfg # (2)!
    └── tutorial # (3)!
        ├── __init__.py 
        ├── items.py # (4)!
        ├── middlewares.py # (5)!
        ├── pipelines.py # (6)!
        ├── settings.py # (7)!
        └── spiders # (8)!
            └── __init__.py

4 directories, 7 files
  1. Diretório do projeto
  2. Arquivo de configuração para deploy
  3. Módulo Python do projeto. É daqui que você importará seu código
  4. Arquivo de definição dos itens do projeto
  5. Arquivo de middlewares do projeto
  6. Arquivo de pipelines do projeto
  7. Arquivo de configurações do projeto
  8. Diretório onde você colocará seus spiders

Para conseguirmos extrair os dados do Shop Ecommerce precisamos criar uma spider específico. Ele será uma classe Python que definirá como o Scrapy navegará pela página de produtos do site, iniciando a partir da URL https://www.scrapingcourse.com/ecommerce/.

Criando uma spider no Scrapy

$ Execução no terminal!
cd tutorial # (1)!
scrapy genspider shopecommerce https://www.scrapingcourse.com/ecommerce/ # (2)!
  1. Ir para o diretório do projeto
  2. Gerando uma spider chamada shopecommerce a partir da URL de produtos do site

Vamos analisar a estrutura criada pelo Scrapy para a spider.

Resposta do comando `tree`
.
├── scrapy.cfg
└── tutorial
    ├── __init__.py
    ├── __pycache__
       ├── __init__.cpython-312.pyc
       └── settings.cpython-312.pyc
    ├── items.py
    ├── middlewares.py
    ├── pipelines.py
    ├── settings.py
    └── spiders
        ├── __init__.py
        ├── __pycache__
           └── __init__.cpython-312.pyc
        └── shopecommerce.py

5 directories, 11 files

O comando genspider criou uma spider chamada shopecommerce, representada pelo arquivo shopecommerce.py dentro do diretório spiders do projeto. Esse arquivo contém um template básico de spider, já configurado com a URL inicial que fornecemos.

Código padrão gerado pelo Scrapy
import scrapy


class ShopecommerceSpider(scrapy.Spider): # (1)!
    name = "shopecommerce" # (2)!
    allowed_domains = ["www.scrapingcourse.com"] # (3)!
    start_urls = ["https://www.scrapingcourse.com/ecommerce/"] # (4)!

    def parse(self, response): # (5)!
        pass
  1. Define uma classe Python chamada ShopecommerceSpider que herda da classe scrapy.Spider. Essa classe é o ponto de partida para criar um spider no Scrapy.

  2. name: Define o nome do spider e é usado para identificar o spider durante a execução. Ele deve ser único no projeto de modo que você não pode definir o mesmo nome para Spiders diferentes.

  3. allowed_domains: Configuração usada no Scrapy para especificar os domínios que o spider está autorizado a visitar.

  4. start_urls: Lista de URLs iniciais a partir das quais o spider começará a rastrear.

  5. parse(): Método principal do spider, onde a lógica de extração é implementada.

Vamos executar a spider que acabamos de criar e analisar a saída no terminal.

$ Execução no terminal!
scrapy crawl shopecommerce
Resposta do comando `scrapy crawl shopecommerce`
[scrapy.utils.log] INFO: Scrapy 2.11.2 started (bot: tutorial)
[scrapy.utils.log] INFO: Versions: lxml 5.3.0.0, libxml2 2.12.9, cssselect 1.2.0, parsel 1.9.1, w3lib 2.2.1, Twisted 24.7.0, Python 3.12.5 (main, Aug  6 2024, 19:08:49) [Clang 15.0.0 (clang-1500.3.9.4)], pyOpenSSL 24.2.1 (OpenSSL 3.3.2 3 Sep 2024), cryptography 43.0.1, Platform macOS-14.6.1-arm64-arm-64bit
[scrapy.addons] INFO: Enabled addons:
[]
[asyncio] DEBUG: Using selector: KqueueSelector
[scrapy.utils.log] DEBUG: Using reactor: twisted.internet.asyncioreactor.AsyncioSelectorReactor
[scrapy.utils.log] DEBUG: Using asyncio event loop: asyncio.unix_events._UnixSelectorEventLoop
[scrapy.extensions.telnet] INFO: Telnet Password: cfee42ce19182cdc
[scrapy.middleware] INFO: Enabled extensions:
['scrapy.extensions.corestats.CoreStats',
 'scrapy.extensions.telnet.TelnetConsole',
 'scrapy.extensions.memusage.MemoryUsage',
 'scrapy.extensions.logstats.LogStats']
[scrapy.crawler] INFO: Overridden settings:
{'BOT_NAME': 'tutorial',
 'FEED_EXPORT_ENCODING': 'utf-8',
 'NEWSPIDER_MODULE': 'tutorial.spiders',
 'REQUEST_FINGERPRINTER_IMPLEMENTATION': '2.7',
 'ROBOTSTXT_OBEY': True,
 'SPIDER_MODULES': ['tutorial.spiders'],
 'TWISTED_REACTOR': 'twisted.internet.asyncioreactor.AsyncioSelectorReactor'}
[scrapy.middleware] INFO: Enabled downloader middlewares:
['scrapy.downloadermiddlewares.offsite.OffsiteMiddleware',
 'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware',
 'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
 'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware',
 'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware',
 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware',
 'scrapy.downloadermiddlewares.retry.RetryMiddleware',
 'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware',
 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware',
 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware',
 'scrapy.downloadermiddlewares.cookies.CookiesMiddleware',
 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware',
 'scrapy.downloadermiddlewares.stats.DownloaderStats']
[scrapy.middleware] INFO: Enabled spider middlewares:
['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware',
 'scrapy.spidermiddlewares.referer.RefererMiddleware',
 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware',
 'scrapy.spidermiddlewares.depth.DepthMiddleware']
[scrapy.middleware] INFO: Enabled item pipelines:
[]
[scrapy.core.engine] INFO: Spider opened
[scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
[scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023
[urllib3.connectionpool] DEBUG: Starting new HTTPS connection (1): publicsuffix.org:443
[urllib3.connectionpool] DEBUG: https://publicsuffix.org:443 "GET /list/public_suffix_list.dat HTTP/11" 200 86684
[scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.scrapingcourse.com/robots.txt> (referer: None)
[scrapy.downloadermiddlewares.robotstxt] DEBUG: Forbidden by robots.txt: <GET https://www.scrapingcourse.com/ecommerce/>
[scrapy.core.engine] INFO: Closing spider (finished)
[scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/exception_count': 1,
 'downloader/exception_type_count/scrapy.exceptions.IgnoreRequest': 1,
 'downloader/request_bytes': 233,
 'downloader/request_count': 1,
 'downloader/request_method_count/GET': 1,
 'downloader/response_bytes': 1093,
 'downloader/response_count': 1,
 'downloader/response_status_count/200': 1,
 'elapsed_time_seconds': 1.463958,
 'finish_reason': 'finished',
 'finish_time': datetime.datetime(2024, 10, 14, 0, 54, 16, 236617, tzinfo=datetime.timezone.utc),
 'log_count/DEBUG': 7,
 'log_count/INFO': 10,
 'memusage/max': 70418432,
 'memusage/startup': 70418432,
 'response_received_count': 1,
 'robotstxt/forbidden': 1,
 'robotstxt/request_count': 1,
 'robotstxt/response_count': 1,
 'robotstxt/response_status_count/200': 1,
 'scheduler/dequeued': 1,
 'scheduler/dequeued/memory': 1,
 'scheduler/enqueued': 1,
 'scheduler/enqueued/memory': 1,
 'start_time': datetime.datetime(2024, 10, 14, 0, 54, 14, 772659, tzinfo=datetime.timezone.utc)}
[scrapy.core.engine] INFO: Spider closed (finished)

O log do Scrapy descreve o processo de execução de uma spider e alguns eventos importantes que ocorreram durante a execução.

Uma informação que chama bastante atenção está entre a linha 43 e 50. Vamos analisar:

Resposta do comando `scrapy crawl shopecommerce`
1
2
3
4
5
6
7
8
[scrapy.core.engine] INFO: Spider opened
[scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
[scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023
[urllib3.connectionpool] DEBUG: Starting new HTTPS connection (1): publicsuffix.org:443
[urllib3.connectionpool] DEBUG: https://publicsuffix.org:443 "GET /list/public_suffix_list.dat HTTP/11" 200 86684
[scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.scrapingcourse.com/robots.txt> (referer: None) # (1)!
[scrapy.downloadermiddlewares.robotstxt] DEBUG: Forbidden by robots.txt: <GET https://www.scrapingcourse.com/ecommerce/> # (2)!
[scrapy.core.engine] INFO: Closing spider (finished)
  1. O Scrapy tenta acessar o arquivo robots.txt do domínio scrapingcourse.com. O status da requisição é 200 OK, o que indica que o arquivo foi baixado com sucesso.
  2. A URL https://www.scrapingcourse.com/ecommerce/ foi bloqueada pelo arquivo robots.txt. O middleware RobotsTxtMiddleware impediu que a spider acessasse a página, resultando no erro "Forbidden by robots.txt".

O log mostra que a spider foi impedida de acessar o site da Shop Ecommerce por causa do arquivo robots.txt que proibiu o rastreamento. Isso encerrou a execução rapidamente, e a spider foi finalizada sem acessar o site.

  • Linha 6: O Scrapy tenta acessar o arquivo robots.txt do domínio scrapingcourse.com. O status da requisição é 200 OK, o que indica que o arquivo foi baixado com sucesso.

  • Linha 7: A URL https://www.scrapingcourse.com/ecommerce/ foi bloqueada pelo arquivo robots.txt. O middleware RobotsTxtMiddleware impediu que a spider acessasse a página, resultando no erro "Forbidden by robots.txt".

E agora? 🤔 O que faremos para contornar esse bloqueio? 🫣