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</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(" ", ""), # We remove 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(" ", ""), # We remove 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.




