Voltar ao blogue
Guias
Sorin-Gabriel MaricaLast updated on Mar 31, 20267 min read

Extrair e analisar dados da Web com Python e BeautifulSoup

Extrair e analisar dados da Web com Python e BeautifulSoup

Os scrapers da Web são ferramentas valiosas que ajudam a extrair informações específicas de um site. Em teoria, seria possível fazer isso manualmente, mas o web scraping permite processar grandes quantidades de dados de forma mais eficiente e produtiva.

Uma das linguagens de programação mais populares para web scraping é o Python. Esta linguagem inclui a biblioteca BeautifulSoup, que simplifica o processo. Juntas, esta dupla torna o web scraping muito mais fácil do que noutras linguagens.

Na minha opinião pessoal, usar o BeautifulSoup é a maneira mais fácil de construir um web scraper simples a partir do zero. Se quiser saber mais sobre isto, continue a ler, pois vou mostrar-lhe como criar o seu próprio web scraper usando Python e BeautifulSoup.

Uma visão geral do BeautifulSoup

O BeautifulSoup, conforme indicado na sua documentação, é uma biblioteca Python para extrair dados de ficheiros HTML e XML. Assim, pode usar Python para extrair o conteúdo HTML de um site e, em seguida, usar o BeautifulSoup para analisar esse HTML e obter apenas as informações relevantes.

A principal vantagem de usar o BeautifulSoup é a sintaxe simples que oferece. Com esta biblioteca, pode navegar na árvore DOM, procurar elementos específicos ou modificar o conteúdo HTML. Todas estas vantagens tornaram-na a biblioteca Python mais popular para analisar documentos HTML e XML.

Instalação

Para instalar o BeautifulSoup, deve consultar o guia aqui, uma vez que a instalação varia consoante o sistema que utiliza. Neste artigo, estou a utilizar um sistema Linux e basta executar o seguinte comando:

pip install beautifulsoup4

Se utilizar o Python 3, poderá ter de instalar a biblioteca utilizando o seguinte comando:

pip3 install beautifulsoup4

Tenha em mente que a minha máquina já tem o Python 3 instalado. Se é novo no Python, pode encontrar um guia sobre como instalá-lo aqui. Além disso, deve consultar o nosso guia definitivo para criar um scraper web com Python para obter ainda mais informações sobre o tema.

Criar um scraper com o BeautifulSoup

Agora, se tudo correu bem, estamos prontos para começar a criar o nosso próprio scraper. Para este artigo, optei por recuperar os 100 melhores filmes de todos os tempos do RottenTomatoes e guardar tudo nos formatos JSON e CSV.

Recuperar o código-fonte da página

Para aquecer e familiarizar-nos com o BeautifulSoup, vamos primeiro recuperar o HTML completo da página e guardá-lo num novo ficheiro chamado «page.txt».

Se quiser ver o código-fonte HTML de qualquer página, pode fazê-lo no Google Chrome premindo CTRL+U. Isto abrirá um novo separador e verá algo semelhante a isto:

Para obter o mesmo código-fonte com o BeautifulSoup e o Python, podemos usar o seguinte código:

import requests
from bs4 import BeautifulSoup

scraped_url = 'https://www.rottentomatoes.com/top/bestofrt/'
page = requests.get(scraped_url)

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

file = open('page.txt', mode='w', encoding='utf-8')
file.write(soup.prettify())

Neste código, fazemos uma solicitação à página do RottenTomatoes e, em seguida, adicionamos todo o conteúdo da página a um objeto BeautifulSoup. A única utilização do BeautifulSoup neste exemplo é a função final chamada “prettify()”, que formata o código HTML para facilitar a leitura.

Para compreender melhor a função, para este código HTML “<div><span>Test&lt;/span></div>”, a função prettify irá adicionar as tabulações e transformá-lo neste código formatado:

<div>

   <span>

       Test

   </span>

</div>

O resultado final do código é a criação de um ficheiro chamado page.txt que contém todo o código-fonte da nossa página:

Deve ter em conta que este é o código-fonte da página antes de qualquer código Javascript ser executado. Por vezes, os sites podem optar por alterar o conteúdo da página dinamicamente. Nesses casos, o código-fonte da página terá um aspeto diferente do conteúdo real apresentado ao utilizador. Se precisar que o seu scraper execute Javascript, pode ler o nosso guia sobre como criar um scraper web com Selenium, ou pode utilizar o WebScrapingAPI, o nosso produto que trata desta questão por si.

Obter os dados da web

Se olhar para o código-fonte da página anterior, verá que é possível encontrar os nomes dos filmes e a sua classificação. Felizmente para nós, o RottenTomatoes não carrega a lista de filmes dinamicamente, pelo que podemos avançar e extrair as informações necessárias.

Primeiro, inspecionamos a página e verificamos como o HTML está estruturado. Para isso, pode clicar com o botão direito do rato no título de um filme e selecionar a opção «Inspecionar Elemento». Deverá aparecer a seguinte janela:

Usei a linha vermelha para destacar as informações úteis desta imagem. Pode ver que a página apresenta os filmes mais populares numa tabela e que existem quatro células em cada linha da tabela (elemento <tr>).

A primeira célula contém a posição do filme, a segunda tem informações sobre as classificações (elemento com a classe tMeterScore), a terceira inclui o título do filme e a última célula dá-nos o número de críticas.

Conhecendo esta estrutura, podemos agora começar a extrair as informações de que precisamos.

import requests
from bs4 import BeautifulSoup
 
links_base = 'https://www.rottentomatoes.com'
scraped_url = 'https://www.rottentomatoes.com/top/bestofrt/'
page = requests.get(scraped_url)
 
soup = BeautifulSoup(page.content, 'html.parser')
 
table = soup.find("table", class_="table") # We extract just the table code from the entire page
rows = table.findAll("tr") # This will extract each table row, in an array
 
movies = []
 
for index, row in enumerate(rows):
    if index > 0: # We skip the first row since this row only contains the column names
        link = row.find("a") # We get the link from the table row
        rating = row.find(class_="tMeterScore") # We get the element with the class tMeterScore from the table row
        movies.append({
            "link": links_base + link.get('href'), # The href attribute of the link
            "title": link.string.strip(), # The strip function removes blank spaces at the beginning and the end of a string
            "rating": rating.string.strip().replace("&nbsp;", ""), # We remove &nbsp; from the string and the blank spaces
        })
        
print(movies)

Ao executar este código, deverá obter um resultado como este:

Neste exemplo, estamos a extrair o conteúdo da tabela e a percorrer as linhas da tabela. Uma vez que a primeira linha contém apenas os nomes das colunas, vamos ignorá-la.

Nas restantes linhas, continuamos o processo extraindo o elemento âncora (<a>) e o elemento span com a classe “tMeterScore”. Com eles, podemos agora recuperar a informação necessária.

O título do filme está dentro do elemento âncora, o link é o atributo “href” da âncora e a classificação está dentro do elemento span com a classe “tMeterScore”. Basta criar um novo dicionário para cada linha e anexá-lo à nossa lista de filmes.

Guardar os dados da web

Até agora, o scraper recuperou e formatou os dados, mas apenas os exibimos no terminal. Em alternativa, podemos guardar a informação no nosso computador como JSON ou CSV. O código completo do scraper (incluindo a criação de um ficheiro local) é:

import requests
from bs4 import BeautifulSoup
import csv
import json
 
links_base = 'https://www.rottentomatoes.com'
scraped_url = 'https://www.rottentomatoes.com/top/bestofrt/'
page = requests.get(scraped_url)
 
soup = BeautifulSoup(page.content, 'html.parser')
 
table = soup.find("table", class_="table") # We extract just the table code from the entire page
rows = table.findAll("tr") # This will extract each table row from the table, in an array
 
movies = []
 
for index, row in enumerate(rows):
    if index > 0: # We skip the first row since this row only contains the column names
        link = row.find("a") # We get the link from the table row
        rating = row.find(class_="tMeterScore") # We get the element with the class tMeterScore from the table row
        movies.append({
            "link": links_base + link.get('href'), # The href attribute of the link
            "title": link.string.strip(), # The strip function removes blank spaces at the beginning and the end of a string
            "rating": rating.string.strip().replace("&nbsp;", ""), # We remove &nbsp; from the string and the blank spaces
        })
        
file = open('movies.json', mode='w', encoding='utf-8')
file.write(json.dumps(movies))
 
writer = csv.writer(open("movies.csv", 'w'))
for movie in movies:
    writer.writerow(movie.values())

Scraping ainda mais

Agora que tem toda a informação, pode optar por ir mais longe na extração. Lembre-se de que cada filme tem um link. Pode continuar a extrair as páginas dos filmes e obter ainda mais informações sobre eles.

Por exemplo, se verificar a página do filme It Happened One Night (1934), poderá ver que ainda é possível extrair informações úteis, tais como a pontuação do público, a duração do filme, o género e assim por diante.

No entanto, fazer todos estes pedidos num curto espaço de tempo parece muito invulgar e pode levar a validações CAPTCHA ou mesmo a bloqueios de IP. Para evitar isso, deve usar proxies rotativos para que o tráfego enviado pareça natural e provenha de vários IPs.

Outras funcionalidades do BeautifulSoup

Embora o nosso scraper do RottenTomatoes esteja completo, o BeautifulSoup ainda tem muito para oferecer. Sempre que trabalhar num projeto, deve manter o link da documentação aberto para que possa procurar rapidamente uma solução quando estiver com dificuldades.

Por exemplo, o BeautifulSoup permite navegar pela árvore DOM da página:

from bs4 import BeautifulSoup

soup = BeautifulSoup("<head><title>Title</title></head><body><div><p>Some text <span>Span</span></p></div></body>", 'html.parser')

print(soup.head.title) # Will print "<title>Title</title>"
print(soup.body.div.p.span) # Will print "<span>Span</span>"

Esta funcionalidade pode ajudá-lo quando precisar de selecionar um elemento que não possa ser identificado pelos seus atributos. Nesse caso, a única forma de o encontrar é através da estrutura do DOM.

Outra coisa interessante sobre o BeautifulSoup é que pode modificar o código-fonte da página:

from bs4 import BeautifulSoup

soup = BeautifulSoup("<head><title>Title</title></head><body><div><p>Some text <span>Span</span></p></div></body>", 'html.parser')

soup.head.title.string = "New Title"
print(soup)
# The line above will print "<head><title>New Title</title></head><body><div><p>Some text <span>Span</span></p></div></body>"

Isto pode ser inestimável se quiser criar um serviço que permita aos utilizadores otimizar as suas páginas. Por exemplo, pode usar o script para extrair um site, obter o CSS, minimizá-lo e substituí-lo no código-fonte HTML. As possibilidades são infinitas!

Faça sempre o scraping de forma inteligente

Quero mesmo que te lembres disto: usar Python e o BeautifulSoup para web scraping é uma excelente ideia. Torna o processo muito mais fácil em comparação com outras linguagens de programação.

O scraper que criámos para recuperar os filmes mais bem classificados de todos os tempos do RottenTomatoes pode ser codificado em apenas alguns minutos, e pode até usá-lo juntamente com o scraper do IMDB do nosso guia definitivo para scraping com PHP.

No entanto, alguns sites são mais acessíveis aos scrapers do que outros. Embora o projeto deste artigo seja simples e divertido, alguns são tudo menos isso. Às vezes, os sites fazem tudo o que está ao seu alcance para impedir que o seu conteúdo seja extraído.

Em certas situações, a única forma de extrair conteúdo é mascarando o seu trabalho com vários IPs e um navegador real. Para este tipo de situação, criámos o WebScrapingAPI, uma solução poderosa que oferece proxies rotativos, renderização em Javascript e permite-lhe extrair qualquer site que desejar com o mínimo de dores de cabeça!

Não acredite apenas na minha palavra, experimente você mesmo! Pode iniciar o seu período de teste gratuito agora mesmo e obter 5000 chamadas de API sem ter de fornecer quaisquer dados confidenciais, como os detalhes do seu cartão de crédito.

Sobre o autor
Sorin-Gabriel Marica, Desenvolvedor Full-Stack @ WebScrapingAPI
Sorin-Gabriel MaricaDesenvolvedor Full-Stack

Sorin Marica é engenheiro Full Stack e DevOps na WebScrapingAPI, onde desenvolve funcionalidades do produto e mantém a infraestrutura que garante o bom funcionamento 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.