Ir para o conteúdo

Introdução ao Desenvolvimento de Sistemas de Software/Web Scraping

De Wikiversidade

Web Scraping

[editar | editar código]

Web scraping (em português, 'raspagem da web') é uma forma de mineração de dados que permite a extração de dados de sites da web, convertendo-os em informação estruturada para posterior análise. O tipo mais básico de coleta é o download manual das páginas ou copiando e colando o conteúdo, e isso pode ser feito por qualquer pessoa. Contudo, a web scraping geralmente é feita por meio de um software que simula a navegação humana por diversos sites, extraindo informações específicas. É um campo em evolução que compartilha um objetivo comum com a visão da web semântica, uma iniciativa ambiciosa que ainda requer avanços no processamento de texto, compreensão semântica, inteligência artificial e interação homem-computador. Web scraping é muito semelhante à indexação web (utilizado pela maioria dos motores de busca), mas a motivação final é muito diferente. A indexação web é usada para ajudar a tornar os motores de busca mais eficientes; já a web scraping pode ser usada por diferentes razões, tais como comparação de preços online, monitoramento meteorológico, pesquisas de mercado, coleta de dados governamentais, monitoramento de dados e, em alguns casos, roubo de informação.

Quando fazer Web Scraping?

[editar | editar código]

É uma boa solução diante da necessidade de coletar volumes grandes de dados de sites que não disponibilizam uma API ou uma forma bem estruturada de acesso aos dados desejados. Usos mais comuns incluem:

  • Monitoramento de preços, tanto por sites que centralizam preços de múltiplos e-commerces como por sites que vendem produtos equivalentes e querem fazer análise de concorrência.
  • Análises de tendências e sentimentos em redes sociais e fóruns para verificar padrões, podendo ser útil no caso de se querer saber a opinião popular sobre algum assunto ou produto.
  • Adquirir dados para treinar modelos de aprendizado de máquina.

Restrições éticas, legais e boas práticas de Web Scraping

[editar | editar código]

Ao realizar Web Scraping, é essencial considerar tanto as questões técnicas quanto as implicações éticas e legais envolvidas. Muitos sites possuem políticas claras de acesso às informações, seja em seus Termos de Uso, seja em arquivos específicos como o `robots.txt`, geralmente localizado em `https://www.exemplo.com/robots.txt`. Este arquivo define quais agentes automatizados (bots) podem acessar determinadas áreas do site e sob quais condições.

Além do respeito ao `robots.txt`, outras práticas responsáveis devem ser adotadas:

  • Respeitar dados pessoais e sensíveis: a coleta de dados que possam identificar pessoas (como nomes, emails, endereços, CPF) está sujeita à LGPD (Lei Geral de Proteção de Dados - Brasil) e ao GDPR (Europa). Esses dados devem ser evitados a menos que haja autorização expressa ou base legal clara.
  • Respeitar os Termos de Uso e políticas de dados do site: mesmo que tecnicamente seja possível coletar informações públicas, alguns sites restringem seu uso para fins específicos (como acadêmico ou pessoal) ou proíbem expressamente o uso automatizado.

Boas práticas técnicas e operacionais

[editar | editar código]

Para evitar impactos indesejados aos servidores e garantir que o scraping seja realizado de forma ética e sustentável:

  • Respeitar o `robots.txt`: antes de iniciar o scraping, verifique o `robots.txt` do site para entender as permissões e restrições.
  • Identificar-se com `User-Agent` próprio: sempre informe um `User-Agent` customizado que identifique seu scraper (por exemplo, `MeuScraperEeducacional`), evitando usar agentes genéricos como o do navegador padrão, isso irá evitar bloqueios.
  • Rate limiting e backoff exponencial: limite o número de requisições por segundo (por exemplo, 1 requisição a cada 2 segundos) e utilize tempos aleatórios entre as requisições. Uma má utilização desse tipo de prevenção irá ocasionar em erro como: (HTTP 429 - Too Many Requests), nesse caso a melhor solução é implementar uma espera crescente (backoff exponencial) antes de tentar novamente.
  • Cache local de páginas: sempre que possível, armazene cópias locais das páginas ou resultados para evitar requisições repetitivas e desnecessárias.
  • Monitoramento da estrutura do site: sites frequentemente alteram seu HTML, URLs ou APIs internas. Automatize testes ou alertas para identificar mudanças que possam quebrar seu scraper.
  • Tratamento robusto de erros e exceções: implemente tratamento de falhas (timeouts, páginas em branco, erros 404, etc.) para garantir que o scraper não sobrecarregue servidores em loops infinitos e para garantir o funcionamento correto do scrapper.
  • Evitar coleta de dados protegidos ou em áreas restritas (login, paywall, etc.) sem autorização ou licença.

Dica prática: priorize APIs públicas

[editar | editar código]

Sempre que disponível, prefira utilizar APIs públicas ou oficiais do site ao invés de scraping direto de HTML, já que APIs:

  • Costumam ser mais estáveis.
  • São documentadas.
  • Possuem regras claras de uso e limites de requisições.

Como fazer usando Python

[editar | editar código]

Dependências

[editar | editar código]

Uma das possibilidades para fazer Web Scraping é com python, através da biblioteca BeautifulSoap. Primeiro, é necessário instalar o Python e as dependências. Insira no terminal:

sudo apt update && sudo apt install python3

Se já tiver o Python, pode confirmar com:

 python3 --version 

Depois de instalar o Python, instale as demais dependências com:

sudo apt install libpq-dev python3-dev build-essential
pip install requests beautifulsoup4 psycopg2 

Desenvolvendo o primeiro script de busca

[editar | editar código]

Para este exemplo, vamos supor que queremos mapear os nomes dos filmes da mostra atual do CINUSP. Para isso, entramos na página da mostra e acessamos a opção Inspecionar elemento. Assim, é possível visualizar o código fonte html. No html, deve-se verificar qual é o formato da informação buscada, que neste caso é h6. Com isso, já podemos escrever um script inicial:

import requests
from bs4 import BeautifulSoup

# Fazer o request para a página:
url = 'https://cinusp.webhostusp.sti.usp.br/mostra/2025/04/a_linha_de_fronteira_se_rompeu/filmes'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')

titulos = soup.find_all('h6')  # Formato do valor que queremos
for titulo in titulos:
    print(titulo.get_text(strip=True))

Veja a saída ao executar:

$ python3 first-web-scraping.py

A Negra De...
Apocalypse Now
Cópia Fiel
Filhos da Esperança
India Song
Ninotchka
Noites Paraguayas
Notícias de Casa
O Abraço da Serpente
Relações de Classe
Sem Chão
Viagem à Itália
Ó, Sol
[editar | editar código]

Fazer dessa maneira inicial, embora já diminua consideravelmente o trabalho de extrair as informações manualmente, ainda exige que copiemos o link de cada mostra manualmente para obter os dados. Agora, vamos generalizar um pouco mais o script para permitir que ele acesse todas as mostras. Para isso, devemos analisar o site em busca de padrões. No caso do CINUSP, verificamos que o padrão é o link das páginas de mostras conterem o texto /mostra/ e que o link fica, na página de mostras, dentro da main-class, referenciado em um href dentro de divisões chamadas de row. Além disso, a lista dos filmes tem exatamente o mesmo link da mostra, basta incluir /filmes ao final. Usando essas informações, podemos ajustar nosso código:

import requests
from bs4 import BeautifulSoup

BASE_URL = "https://cinusp.webhostusp.sti.usp.br"

def get_links_das_5_mostras():
    response = requests.get("https://cinusp.webhostusp.sti.usp.br/mostras")
    response.raise_for_status()
    soup = BeautifulSoup(response.text, 'html.parser')

    # Como foi mapeado, as mostras ficam na main-section:
    main_section = soup.find('section', class_='main-section')
    if not main_section:
        raise Exception("Seção principal não encontrada!")

    # Encontrando o link de cada mostra:
    i = 0
    mostra_links = []
    for div in main_section.find_all('div', class_='bg_mostra_img'):
        a_tag = div.find('a', href=True)
        if i == 0:
            i += 1
            continue
        if i >= 6:
            break
        if a_tag:
            href = a_tag['href']
            # Para garantir que não pegamos um href errado ou um link repetido:
            if href.startswith('/mostra/') and href not in mostra_links:
                mostra_links.append(BASE_URL + href + "/filmes")
                i += 1

    # Aqui, quero apenas as mostras deste ano:
    return mostra_links[:5]

def extrair_titulos_filmes(url_mostra_filmes):
    response = requests.get(url_mostra_filmes)
    response.raise_for_status()
    soup = BeautifulSoup(response.text, 'html.parser')

    # Filmes estão marcados com <h6>, como fizemos antes:
    filmes = soup.find_all('h6')
    return [f.get_text(strip=True) for f in filmes]

def main():
    urls = get_links_das_5_mostras()
    for url in urls:
        print(f"\n Filmes da mostra: {url}")
        titulos = extrair_titulos_filmes(url)
        if not titulos:
            print("Nenhum filme encontrado.")
        for titulo in titulos:
            print("-", titulo)

if __name__ == "__main__":
    main()

Ao executar esse código, temos a lista dos filmes exibidos em 2025. Podemos ir modelando o código para o objetivo que quisermos. Por exemplo, é possível aceitar somente URLs com certos padrões para restringir um intervalo de anos específicos. Basta observar onde o site original registra essa informação. Observe que foi necessário saber os nomes das seções e classes do código original para usar os métodos find() e find_all() e encontrar exatamente o que buscávamos.

Extraindo dados mais complexos

[editar | editar código]

Extrair os títulos parece uma coisa mais óbvia, mas podemos também extrair imagens. No caso do site que estamos usando como exemplo, o CINUSP, as imagens são armazenadas em links do staticflickr. Novamente, o procedimento é análogo, precisamos procurar no código onde exatamente ficam armazenadas as imagens. A partir disso, modificamos a função do código anterior para devolver um dicionário que contém os títulos e imagens de cada filme. Incluímos um novo import para facilitar lidar com os URLs.

from urllib.parse import urljoin

def extrair_filmes_com_imagens(url_mostra_filmes):
    response = requests.get(url_mostra_filmes)
    response.raise_for_status()
    soup = BeautifulSoup(response.text, 'html.parser')

    filmes = []
    # classe que abrange todas as informações que queremos: column small-12 large-6 filme_info
    blocos_filme = soup.find_all('div', class_='column small-12 large-6 filme_info')

    for bloco in blocos_filme:
        # Pegando título: <h6> dentro da classe column small-12
        titulo_div = bloco.find('div', class_='column small-12')
        titulo_tag = titulo_div.find('h6') if titulo_div else None
        titulo = titulo_tag.get_text(strip=True) if titulo_tag else 'Sem título'

        # Pegando imagem: <img> dentro da classe column small-5 hide-for-large-up
        imagem_div = bloco.find('div', class_='column small-5 hide-for-large-up')
        img_tag = imagem_div.find('img') if imagem_div else None
        imagem_url = urljoin("https://cinusp.webhostusp.sti.usp.br/mostras", img_tag['src']) if img_tag and 'src' in img_tag.attrs else None

        filmes.append({'titulo': titulo, 'imagem': imagem_url})

    return filmes

Rodando essa função com as devidas modificações na main, conseguimos obter:

Mostra: https://cinusp.webhostusp.sti.usp.br/mostra/2025/04/a_linha_de_fronteira_se_rompeu/filmes
- A Negra De...
   Imagem: https://live.staticflickr.com/65535/54476178269_084838c295_b.jpg
- Apocalypse Now
   Imagem: https://live.staticflickr.com/65535/54476263213_ecb55255f9_b.jpg

Onde encontramos exatamente as imagens que queríamos:

Ferramentas além de BeautifulSoup

[editar | editar código]
  • Selenium

Controla navegadores reais (Chrome, Firefox), ideal para páginas que usam JavaScript. Permite clicar, rolar, preencher formulários e extrair conteúdos dinâmicos. Uso: páginas dinâmicas ou que exigem login.

  • Scrapy

Framework completo para scraping em larga escala, com paralelismo, pipelines, middlewares e integração com bancos de dados. Uso: projetos robustos e automação de grande volume.

  • Playwright (ou Puppeteer)

Automação moderna de navegadores headless, ideal para páginas complexas e SPAs. Suporta interações avançadas, capturas e scraping dinâmico. Uso: páginas com JavaScript pesado, animações ou múltiplas etapas.

  • lxml

Biblioteca rápida para parsing de HTML/XML, podendo ser usada com BeautifulSoup. Uso: parsing de grandes volumes com foco em melhora de desempenho.

Referências

[editar | editar código]
  1. Web Scraping Consultado em 14/05/2025