Ir para o conteúdo

Respeitando as regras da Web

Introdução ao robots.txt

O robots.txt é como um manual de instruções que você coloca no seu site para orientar os robôs de busca sobre quais páginas eles podem ou não visitar. Assim, você pode proteger áreas privadas do seu site, como páginas de login ou arquivos confidenciais. Imagine que é como colocar uma placa na porta da sala de um escritório, dizendo "Não perturbe".

Introdução a user-agent

O user-agent é como um cartão de visita para os robôs. Quando um robô visita o seu site, ele se identifica enviando um user-agent, que contém informações sobre ele, como o seu nome e o serviço que ele representa. Isso permite que você personalize as regras do robots.txt para diferentes tipos de robôs.

Interação entre robots.txt e user-agent

A combinação do robots.txt e do user-agent é poderosa. Imagine que você queira permitir que o Googlebot explore todo o seu site, mas bloquear um robô específico que você sabe que causa problemas. Você pode adicionar uma regra no seu robots.txt que diga: "Permita o acesso a todas as páginas para o Googlebot, mas bloqueie o acesso a todas as páginas para o robô X".

Estratégias para contornar o bloqueio

O primeiro passo é analisar o arquivo robots.txt do site que você deseja realizar a raspagem de dados. No caso do Shop Ecommerce o robot.txt tem as seguintes regras:

Código do arquivo robot.txt
    User-agent: * # (1)!
    Disallow: /ecommerce/* # (2)!
  1. O asterisco (*) indica que a regra se aplica a todos os agentes de usuário (ou bots). Isso significa que qualquer bot que visite o site, independentemente de sua identidade, deve seguir as regras especificadas.
  2. A diretiva Disallow especifica quais partes do site não podem ser acessadas pelo bot. No caso dessa regra, está sendo indicado que nenhuma URL que comece com /ecommerce/ pode ser acessada.

A combinação das regras especificadas indicam que todos os bots estão proibidos de acessar qualquer URL que comece com /ecommerce/.

Os administradores do site desejam controlar e proteger o acesso a todas as páginas do site ou reduzir a carga no servidor.

Há formas conservadores e menos invasivas de contornar bloqueios, como por exemplo a configuração de user-agent e respeito de regras como acesso as páginas autorizadas.

Você pode explorar outros robots.txt como da Google, OLX e Magazine Luiza.

No caso do site Shop Ecommerce é preciso notar que o mesmo foi criado para fins didáticos e de aprendizagem de Web Scraping. Assim, seu bloqueio é extremo para treinarmos habilidades e estratégias. De forma geral, os sites reais mantém atualizado os robots.txt para garantir que os robôs de busca indexem as páginas corretas e seguindo regras.

Como analisado no robots.txt do Shop Ecommerce, apenas configurar user-agent e respeitar as regras do robots.txt não seria suficiente para conseguirmos acessar e extrair os dados do site.

Portanto, iremos ajustar as configurações do Scrapy de forma gradual e testar (executar a spider) para validarmos até onde precisamos enganar o site para termos o acesso permitido.

Configurando o Scrapy

O arquivo settings.py permite personalização do comportamento dos componentes do Scrapy, incluíndo os próprios spiders. Neste momento, iremos focar nas configurações que se relacionam com a forma como o Scrapy interage com os sites, como simular diferentes navegadores e como a spider vai agir com as regras do robots.txt encontrado no site.

Configurando o user-agent no Scrapy

Ajustaremos configurações do User-Agent para simular diferentes navegadores e assim contornar possíveis bloqueios. Primeiro, vamos analisar qual o user-agent atual do nosso projeto interagindo pelo shell do Scrapy.

$ Execução no terminal!
scrapy shell # (1)!
  1. Inicia uma sessão interativa do shell do Scrapy. Uma ferramenta poderosa para testar e depurar a extração de dados de páginas da web.
scrapy shell
[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: c2d0b4ac8d27a967
[scrapy.middleware] INFO: Enabled extensions:
['scrapy.extensions.corestats.CoreStats',
'scrapy.extensions.telnet.TelnetConsole',
'scrapy.extensions.memusage.MemoryUsage']
[scrapy.crawler] INFO: Overridden settings:
{'BOT_NAME': 'tutorial',
'DUPEFILTER_CLASS': 'scrapy.dupefilters.BaseDupeFilter',
'FEED_EXPORT_ENCODING': 'utf-8',
'LOGSTATS_INTERVAL': 0,
'NEWSPIDER_MODULE': 'tutorial.spiders',
'REQUEST_FINGERPRINTER_IMPLEMENTATION': '2.7',
'ROBOTSTXT_OBEY': True,
'SPIDER_MODULES': ['tutorial.spiders'],
'TWISTED_REACTOR': 'twisted.internet.asyncioreactor.AsyncioSelectorReactor',
'USER_AGENT': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:108.0) '
            'Gecko/20100101 Firefox/108.0'}
[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.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023
[s] Available Scrapy objects:
[s]   scrapy     scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s]   crawler    <scrapy.crawler.Crawler object at 0x108531c10>
[s]   item       {}
[s]   settings   <scrapy.settings.Settings object at 0x10902d700>
[s] Useful shortcuts:
[s]   fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s]   fetch(req)                  Fetch a scrapy.Request and update local objects 
[s]   shelp()           Shell help (print this help)
[s]   view(response)    View response in a browser
>>>

Agora iremos consultar o user-agent que é enviado quando acessamos o site Shop Ecommerce através da spider.

>>> Execução no shell do Scrapy
settings.get('USER_AGENT') # (1)!
  1. Inicia uma sessão interativa do shell do Scrapy. Uma ferramenta poderosa para testar e depurar a extração de dados de páginas da web.
scrapy shell
'Scrapy/2.11.2 (+https://scrapy.org)'

Ops! Como estamos utilizando as configurações padrão do Scrapy, o user-agent enviado pela spider é o padrão do framework, incluindo a versão do Scrapy utilizada. Dessa forma, o site alvo pode identificar facilmente que a requisição provém de um crawler. Assim, os sites têm a capacidade de bloquear nossas ações de acesso e raspagem de dados.

Vamos contornar essa situação configurando o user-agent do projeto para que a spider se identifique como um usuário comum. Ao simular um acesso via navegador, aumentamos as chances de obter os dados desejados, já que a requisição será semelhante à de um acesso humano.

No arquivo settings.py vamos habilitar USER_AGENT e colocar um valor real.

Simula o comportamento de um navegador Firefox
USER_AGENT = (
    "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0"
)

Esse user-agent diz ao site que a requisição está sendo feita por um navegador Firefox na versão 108.0, através de um sistema operacional Ubuntu Linux de 64 bits.

Vamos executar a spider novamente e analisar se ainda estamos sendo bloqueados.

$ Execução no terminal!
scrapy crawl shopecommerce
Resposta do comando `scrapy crawl shopecommerce`
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/>

Como esperado, no contexto deste site, o robots.txt bloqueia qualquer user-agent, e essa medida não foi suficiente para permitir que nosso crawler acessasse o Shop Ecommerce. No entanto, é uma boa prática configurar o user-agent em todo projeto de Scrapy e web scraping.

Ao configurar o user-agent para simular um navegador Chrome, por exemplo, podemos contornar algumas restrições do site que bloqueiam requests de bots. Ao utilizar proxies, podemos distribuir as requisições por diferentes IPs, dificultando o bloqueio da nossa aplicação.

Configuração do robots.txt no Scrapy

Por padrão, o Scrapy respeita as regras definidas no arquivo robots.txt de cada site, verificando-o antes de acessar qualquer página e só faz requisições permitidas por esse arquivo.

Vamos ajustar a configuração do projeto para permitir ao Scrapy ignorar as regras do robots.txt no arquivo settings.py.

ROBOTSTXT_OBEY = False

Nosso objetivo é extrair os dados sem causar danos ao site. Portanto, iremos fazer outras configurações para mitigar sobrecarga no servidor e simular um comportamento de usuário humano.

Vamos adicionar atraso nas requisições e ajustar dinamicamente a frequência de requisições de acordo com a capacidade de resposta do servidor utilizando a extensão autothrottle do Scrapy.

Ajusta parâmetros de configuração
DOWNLOAD_DELAY = 3 # (1)!
AUTOTHROTTLE_ENABLED = True  # (2)!
AUTOTHROTTLE_START_DELAY = 5 # (3)!
AUTOTHROTTLE_MAX_DELAY = 60  # (4)!
AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0 # (5)!
  1. Define um atraso fixo (em segundos) entre cada requisição ao mesmo domínio/site.
  2. Habilita extensão autothrottle do Scrapy que ajusta automaticamente a taxa de requisições com base na resposta do servidor, podendo aumentar ou diminuir o atraso entre as requisições a depender da demanda.
  3. Delay inicial de 5 segundos
  4. Delay máximo de 60 segundos
  5. Média de requisições simultâneas

Se as configurações realizadas não fossem suficientes para para contornar o bloqueio de acesso da spider ao site, uma alternativa seria adicionar middlewares personalizados para realizar tarefas específicas, como rotacionar user-agent e os proxies ou lidar com erros de forma mais robusta.

Vamos a mais um teste de execução da nossa spider:

$ Execução no terminal!
scrapy crawl shopecommerce
Resposta do comando `scrapy crawl shopecommerce`
DEBUG: Crawled (200) <GET https://www.scrapingcourse.com/ecommerce/> (referer: None)
[scrapy.core.engine] INFO: Closing spider (finished)

O trecho do log indica que a spider fez uma requisição bem-sucedida para a URL especificada (status 200). Não há erros ou problemas reportados até aqui.

Uhuuu! Agora estamos com tudo pronto para começar a extrair os dados do Shop Ecommerce e desenvolver a lógica da spider.