Voltar ao blogue
Guias
Ștefan RăcilăLast updated on Mar 31, 20268 min read

Como criar um rastreador da Web usando Python - Guia para principiantes

Como criar um rastreador da Web usando Python - Guia para principiantes

O rastreamento da Web é o processo de visitar automaticamente páginas da Web e extrair informações úteis delas. Um rastreador da Web, também conhecido como spider ou bot, é um programa que realiza essa tarefa. Neste artigo, iremos discutir como criar um rastreador da Web utilizando a linguagem de programação Python. Mais especificamente, iremos criar dois rastreadores da Web.

Vamos construir um web crawler simples a partir do zero em Python, utilizando as bibliotecas Requests e BeautifulSoup. Depois disso, falaremos sobre as vantagens de utilizar uma estrutura de web crawling como o Scrapy. E, por último, construiremos um crawler de exemplo com o Scrapy para recolher dados de todos os produtos para bebés da Amazon. Veremos também como o Scrapy se adapta a sites com vários milhões de páginas.

Pré-requisitos

Antes de seguir este artigo, terá de ter um conhecimento básico de Python e tê-lo instalado no seu computador. Além disso, terá de instalar os módulos Requests e BeautifulSoup. Isto pode ser feito executando o seguinte comando no seu prompt de comando ou terminal:

$ pip install requests bs4

Para a segunda parte deste artigo, onde iremos construir um exemplo de rastreador web utilizando o Scrapy, terá de instalar o framework Scrapy. Os criadores deste framework recomendam vivamente que instale o Scrapy num ambiente virtual dedicado, para evitar conflitos com os pacotes do seu sistema.

Sugiro que instale o virtualenv e o virtualenvwrapper para criar um ambiente Python isolado. Tenha em atenção que existe uma versão do virtualenvwrapper para Windows chamada virtualenvwrapper-win.

Também terá de instalar o pipx através do pip para instalar o virtualenv.

$ python -m pip install --user pipx

$ python -m pipx ensurepath

Depois de criar um ambiente Python isolado, pode instalar o Scrapy com o seguinte comando.

$ pip install Scrapy

Pode encontrar o guia de instalação do Scrapy aqui.

O que é um rastreador da Web?

O rastreamento da Web e a extração de dados da Web são conceitos relacionados, mas distintos. A extração de dados da Web é o processo geral de extrair dados de um site. O rastreamento da Web é a tarefa específica de navegar automaticamente pelas páginas da Web para encontrar os URLs que precisam de ser extraídos.

Um rastreador web começa com uma lista de URLs para navegar, conhecida como semente. À medida que navega por cada URL, procura links no HTML e filtra-os com base em critérios específicos. Quaisquer novos links encontrados são adicionados a uma fila para processamento futuro. O HTML extraído ou as informações especificadas são então encaminhados para outro pipeline para processamento adicional.

Ao criar um web crawler, é importante ter em mente que nem todas as páginas de um site serão visitadas. O número de páginas visitadas depende do orçamento do crawler, da profundidade do rastreamento ou do tempo alocado para a execução.

Muitos sites têm um ficheiro robots.txt que indica quais as partes do site que podem ser rastreadas e quais devem ser evitadas. Além disso, alguns sites têm um sitemap.xml que é mais explícito do que o robots.txt e instrui especificamente os bots sobre quais as páginas que devem ser rastreadas, além de fornecer metadados adicionais para cada URL.

Os rastreadores da Web são comumente usados para uma variedade de finalidades:

  • As ferramentas de análise de SEO recolhem metadados, tais como o tempo de resposta e o estado da resposta, para além do HTML, para detetar páginas e links quebrados entre diferentes domínios, com o objetivo de recolher backlinks.
  • As ferramentas de monitorização de preços rastreiam sites de comércio eletrónico para encontrar páginas de produtos e extrair metadados, especificamente preços. As páginas de produtos são então revisitadas periodicamente.
  • Os motores de busca, como o Googlebot, o Bingbot e o Yandex Bot, recolhem todo o HTML de uma parte significativa da web e utilizam os dados para a tornar pesquisável.

Mais adiante neste artigo, iremos comparar duas abordagens diferentes para construir um rastreador web em Python. A primeira abordagem consiste em utilizar a biblioteca Requests para efetuar pedidos HTTP e a BeautifulSoup para analisar conteúdo HTML. A segunda abordagem consiste em utilizar uma estrutura de rastreamento web. Iremos utilizar o Scrapy.

Utilização das bibliotecas Requests e BeautifulSoup

O módulo requests em Python é uma ferramenta poderosa para efetuar pedidos HTTP. Para o utilizar no rastreamento da Web, pode começar por importar o módulo e efetuar um pedido a um URL específico. Por exemplo:

url = 'https://amazon.com/s?k=baby+products'

response = requests.get(url)

Assim que tiver a resposta, pode extrair todos os links do conteúdo HTML utilizando o BeautifulSoup. Por exemplo:

import json

from urllib.parse import urljoin

from bs4 import BeautifulSoup

html = response.text

links = []

soup = BeautifulSoup(html, 'html.parser')

for link in soup.find_all('a'):

    path = link.get('href')

    if path and path.startswith('/'):

        path = urljoin(url, path)

   

    links.append(path)

print(json.dumps(links, sort_keys = True, indent = 2))

Pode então percorrer os links e fazer pedidos para eles, repetindo o processo até ter visitado todas as páginas que deseja rastrear. Esta é uma função recursiva que funciona exatamente assim:

import requests

from urllib.parse import urljoin

from bs4 import BeautifulSoup

import logging

logging.basicConfig(

    format='%(asctime)s %(levelname)s:%(message)s',

    level=logging.INFO)

url = 'https://amazon.com/s?k=baby+products'

visited = []

def crawl(url):

    logging.info(f'Crawling: {url}')

    visited.append(url)

    html = ''

    try:

        html = requests.get(url).text

    except Exception:

        logging.exception(f'Failed to crawl: {url}')

        return

        

    soup = BeautifulSoup(html, 'html.parser')

    # here you can extract and store useful data from the page

    for link in soup.find_all('a'):

        path = link.get('href')

        if path and path.startswith('/'):

            path = urljoin(url, path)

        

        if path not in visited:

            crawl(path)

crawl(url)

A função regista uma linha para cada URL visitada.

2023-01-16 09:20:51,681 INFO:Crawling: https://amazon.com/s?k=baby+products

2023-01-16 09:20:53,053 INFO:Crawling: https://amazon.com/ref=cs_503_logo

2023-01-16 09:20:54,195 INFO:Crawling: https://amazon.com/ref=cs_503_link

2023-01-16 09:20:55,131 INFO:Crawling: https://amazon.com/dogsofamazon/ref=cs_503_d

2023-01-16 09:20:56,549 INFO:Crawling: https://www.amazon.com/ref=nodl_?nodl_android

2023-01-16 09:20:57,071 INFO:Crawling: https://www.amazon.com/ref=cs_503_logo

2023-01-16 09:20:57,690 INFO:Crawling: https://www.amazon.com/ref=cs_503_link

2023-01-16 09:20:57,943 INFO:Crawling: https://www.amazon.com/dogsofamazon/ref=cs_503_d

2023-01-16 09:20:58,413 INFO:Crawling: https://www.amazon.com.au/ref=nodl_&nodl_android

2023-01-16 09:20:59,555 INFO:Crawling: None

2023-01-16 09:20:59,557 ERROR:Failed to crawl: None

Embora o código para um rastreador web básico possa parecer simples, existem muitos desafios que devem ser superados para rastrear com sucesso um site inteiro. Estes incluem questões como:

  • A lógica do URL de download carece de um mecanismo de repetição e a fila de URLs não é muito eficiente com um número elevado de URLs.
  • O rastreador não se identifica e ignora o ficheiro robots.txt.
  • O rastreador é lento e não suporta paralelismo. Cada URL demora cerca de um segundo a rastrear, e o rastreador aguarda uma resposta antes de avançar para a URL seguinte.
  • A lógica de extração de links não suporta a padronização de URLs através da remoção de parâmetros de string de consulta, não lida com URLs de âncora/fragmento relativas (como href="#anchor") e não suporta a filtragem de URLs por domínio ou a exclusão de pedidos para ficheiros estáticos.

Na próxima secção, veremos como o Scrapy resolve estas questões e facilita a extensão da funcionalidade do rastreador web para casos de uso personalizados.

Como criar um rastreador web em Python utilizando a estrutura Scrapy

O Scrapy é uma poderosa estrutura para criar rastreadores da Web em Python. Ele fornece uma maneira integrada de seguir links e extrair informações de páginas da Web. Terá de criar um novo projeto Scrapy e um spider para definir o comportamento do seu rastreador.

Antes de começar a rastrear um site como a Amazon, é importante verificar o ficheiro robots.txt do site para ver quais os caminhos de URL permitidos. O Scrapy lê automaticamente este ficheiro e segue-o quando a configuração ROBOTSTXT_OBEY está definida como true, o que é o padrão para projetos criados usando o comando Scrapy `startproject`.

Para criar um novo projeto Scrapy, é necessário executar o seguinte comando:

$ scrapy startproject amazon_crawler

Este comando irá gerar um projeto com a seguinte estrutura:

amazon_crawler/

├── scrapy.cfg

└── amazon_crawler

    ├── __init__.py

    ├── items.py

    ├── middlewares.py

    ├── pipelines.py

    ├── settings.py

    └── spiders

        ├── __init__.py

Para criar um spider, utilize o comando `genspider` da CLI do Scrapy. O comando tem a seguinte definição:

$ scrapy genspider [options] <name> <domain>

Para gerar um spider para este crawler, podemos executar:

$ cd amazon_crawler

$ scrapy genspider baby_products amazon.com

Deve criar um ficheiro chamado `baby_products.py` dentro da pasta chamada `spiders` e gerar este código:

import scrapy

class BabyProductsSpider(scrapy.Spider):

    name = 'wikipedia'

    allowed_domains = ['en.wikipedia.com']

    start_urls = ['http://en.wikipedia.com/']

    def parse(self, response):

        pass

O Scrapy também oferece uma variedade de classes de spider pré-construídas, tais como CrawlSpider, XMLFeedSpider, CSVFeedSpider e SitemapSpider. A classe CrawlSpider, que é construída sobre a classe base Spider, inclui um atributo extra "rules" para definir como navegar por um site. Cada regra utiliza um LinkExtractor para determinar quais links devem ser extraídos de cada página.

Para o nosso caso de uso, devemos herdar a nossa classe Spider da CrawlSpider. Também precisaremos de criar uma regra LinkExtractor que indique ao rastreador para extrair links apenas da paginação da Amazon. Lembre-se de que o nosso objetivo era recolher dados de todos os produtos para bebés da Amazon, por isso não queremos, na verdade, seguir todos os links que encontrarmos na página.

Depois, precisamos de criar mais dois métodos na nossa classe, `parse_item` e `parse_product`. `parse_item` será passado como uma função de callback para a nossa regra LinkExtractor e será chamado com cada link extraído. `parse_product` irá analisar cada produto… ¯\_(ツ)_/¯

from scrapy.spiders import CrawlSpider, Rule

from scrapy.linkextractors import LinkExtractor

from bs4 import BeautifulSoup

class BabyProductsSpider(CrawlSpider):

    name = 'baby_products'

    allowed_domains = ['amazon.com']

    start_urls = ['https://amazon.com/s?k=baby+products']

    rules = (

        Rule(

            LinkExtractor(

                restrict_css='.s-pagination-strip'

            ),

            callback='parse_item',

            follow=True),

        )

    def parse_item(self, response):

        soup = BeautifulSoup(response.text, 'html.parser')

        products = soup.select('div[data-component-type="s-search-result"]')

        data = []

        for product in products:

            parsed_product = self.parse_product(product)

            if (parsed_product != 'error'):

                data.append(parsed_product)

        return {

            'url': response.url,

            'data': data

        }

    def parse_product(self, product):

        try:

            link = product.select_one('a.a-text-normal')

            price = product.select_one('span.a-price > span.a-offscreen').text

            return {

                'product_url': link['href'],

                'name': link.text,

                'price': price

            }

        except:

            return 'error'

Para iniciar o rastreador, pode executar:

$ scrapy crawl baby_products

Irá ver muitos registos na consola (pode especificar um ficheiro de registo com `--logfile [log_file_name]`).

Usei a Pesquisa da Amazon como exemplo para demonstrar os conceitos básicos da criação de um rastilhador web em Python. No entanto, o rastilhador não encontra muitos links para seguir e não está adaptado a um caso de uso específico para os dados. Se pretende extrair dados específicos da Pesquisa da Amazon, pode considerar a utilização da nossa API de Dados de Produtos da Amazon. Criámos analisadores personalizados para a Pesquisa da Amazon, páginas de Produtos e Categorias, e estes devolvem dados no formato JSON, prontos a serem utilizados na sua aplicação.

Por que é melhor usar um serviço profissional de scraping do que um rastreador

Embora o rastreamento da web possa ser uma ferramenta útil para extrair dados da Internet, também pode ser demorado e complexo de configurar. Além disso, o scraping da web pode violar os termos de serviço de alguns sites e resultar no bloqueio do seu IP ou mesmo em ações legais contra si.

Por outro lado, os serviços profissionais de scraping utilizam técnicas e tecnologias avançadas para contornar medidas anti-scraping e extrair dados sem serem detetados. Também tratam da manutenção e do dimensionamento da infraestrutura de scraping, permitindo-lhe concentrar-se na análise e utilização dos dados. Além disso, proporcionam um nível mais elevado de precisão e exaustividade dos dados, uma vez que são capazes de lidar com casos de utilização de extração de dados mais avançados e de realizar trabalhos de scraping em grande escala.

Resumo

Em conclusão, embora o rastreamento da web possa ser uma ferramenta útil para extrair dados da Internet, também pode ser demorado e complexo de configurar. Além disso, o rastreamento da web pode violar os termos de serviço de alguns sites e resultar no bloqueio do seu IP ou até mesmo em ações legais contra si. Portanto, para trabalhos de scraping mais avançados e em grande escala, é melhor utilizar um serviço profissional de scraping.

Se procura uma alternativa ao rastreamento por conta própria, considere utilizar o WebScrapingAPI. O WebScrapingAPI é um serviço profissional de scraping da Web que lhe permite extrair facilmente dados de sites sem a necessidade de criar e manter o seu próprio scraper.

É uma solução rápida, fiável e económica, adequada para empresas de todas as dimensões.

Porque não experimenta hoje mesmo? É gratuito e temos um período de teste de 14 dias sem necessidade de cartão de crédito.

Sobre o autor
Ștefan Răcilă, Desenvolvedor Full Stack @ WebScrapingAPI
Ștefan RăcilăDesenvolvedor Full Stack

Stefan Racila é engenheiro de DevOps e Full Stack na WebScrapingAPI, onde desenvolve funcionalidades do produto e mantém a infraestrutura que garante a fiabilidade da plataforma.

Comece a construir

Pronto para expandir a sua recolha de dados?

Junte-se a mais de 2.000 empresas que utilizam a WebScrapingAPI para extrair dados da Web à escala empresarial, sem quaisquer custos de infraestrutura.