Uma visão geral do Selénio
Tal como o site oficial do Selenium indica, o Selenium é um conjunto de ferramentas para automatizar os navegadores Web que foi introduzido pela primeira vez como uma ferramenta para testes entre navegadores.
A API criada pela equipa do Selenium utiliza o protocolo WebDriver para assumir o controlo de um navegador Web, como o Chrome ou o Firefox, e executar diferentes tarefas, como:
- Preenchimento de formulários
- Deslocação
- Tirar capturas de ecrã
- Clicar em botões
Agora deve estar a perguntar-se como é que tudo isto se traduz em web scraping. É simples, de facto.
A extração de dados pode, por vezes, ser uma verdadeira dor de cabeça. Hoje em dia, os sítios Web estão a ser construídos como aplicações de página única, mesmo quando não há necessidade disso. Estão a aparecer CAPTCHAs com mais frequência do que o necessário e até a bloquear IPs de utilizadores regulares.
Em suma, a deteção de bots é uma funcionalidade muito frustrante que parece um bug.
O Selenium pode ajudar nestes casos, compreendendo e executando o código Javascript e automatizando muitos processos tediosos da recolha de dados da Web, como percorrer a página, apanhar elementos HTML ou exportar dados recolhidos.
Instalação
Para mostrar o verdadeiro poder do Selenium e do Python, vamos extrair algumas informações do subreddit /r/learnprogramming. Além de extrair dados, também mostrarei como o login pode ser implementado. Agora que já entendemos a ferramenta principal e o site que vamos usar, vamos ver quais outros requisitos precisamos ter instalados:
1. Python. Iremos utilizar Python 3.0. No entanto, pode utilizar Python 2.0 fazendo pequenos ajustes. Pode descarregá-lo e instalá-lo a partir daqui.
2. Pacote Selenium. Pode instalar o pacote Selenium utilizando o seguinte comando:
pip3 install selenium
3. Pacote Pandas. Será utilizado para extrair e armazenar os dados recolhidos num ficheiro .csv. Execute o seguinte comando para o instalar no seu dispositivo.
pip3 install pandas
4. Pacote BeautifulSoup. Utilizado para analisar documentos HTML e XML. Basta executar esta linha:
pip3 install beautifulsoup
5. Google Chrome. Consulte esta hiperligação para saber mais sobre como descarregá-lo e instalá-lo.
6. Controlador do Chrome. Ajudar-nos-á a configurar o controlador Web para o Selenium. Siga este link para descarregar e instalar a versão mais recente do chromedriver. Não se esqueça de guardar o caminho onde o instalou.
Iniciar o browser
Vamos começar. Crie um novo arquivo scraper.py e importe o pacote Selenium copiando a seguinte linha:
from selenium import webdriver
Vamos agora criar uma nova instância do Google Chrome escrevendo:
driver = webdriver.Chrome(LOCATION)
Substitua LOCATION pelo caminho onde o driver do Chrome pode ser encontrado no seu computador. Consulte a documentação do Selenium para encontrar o PATH mais exato para o controlador Web, com base no sistema operativo que está a utilizar.
O passo final é aceder ao Web site do qual pretendemos extrair dados. No nosso caso, trata-se de https://www.reddit.com/r/learnprogramming/top/?t=month. Copie a seguinte linha no ficheiro python recém-criado:
driver.get("https://www.reddit.com/r/learnprogramming/top/?t=month")
Executando o seguinte comando numa janela de terminal:
python3 scraper.py
Devemos agora ter uma nova instância do Google Chrome aberta que especifica "O Chrome está a ser controlado por software de teste automatizado" no topo da nossa página.
Localização de dados específicos
Como já deve ter percebido, neste tutorial vamos fazer scrape do subreddit /r/learnprogramming. Vamos guardar o título, o autor e o número de votos positivos dos posts e armazená-los num novo ficheiro .csv. Vamos ver onde estão situados na página HTML e como podemos extraí-los.
Depois que o Google Chrome finalmente carregou a página, vamos clicar com o botão direito do mouse em qualquer post e clicar em "Inspecionar". Podemos encontrar o contentor HTML da publicação sob o nome de classe _1oQyIsiPHYt6nx7VOmd1sz.

Também é possível executar o Google Chrome sem uma interface gráfica do utilizador e registar o conteúdo HTML da página, adicionando algumas linhas de código. Definiremos a opção sem cabeça como verdadeira para o driver do Chrome (para remover a interface gráfica) e um tamanho de janela de 1080 pixels (para obter o código HTML correto para nosso caso de uso).
As duas últimas linhas de código saem do Chrome logo após terminarem de registar o HTML da página.
O novo ficheiro scraper.py terá o seguinte aspeto:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.headless = True
options.add_argument("--window-size=1920,1080")
driver = webdriver.Chrome("./chromedriver")
driver.get("https://www.reddit.com/r/learnprogramming/top/?t=month")
print(driver.page_source)
driver.quit()Elemento Web
Um WebElement é um objeto do Selenium que representa um elemento HTML. Como você verá no tutorial a seguir, podemos executar muitas ações nesses elementos. Algumas delas são:
- Clicar nele utilizando o método .click()
- Fornecer texto a um elemento de entrada específico chamando o método .send_keys()
- Ler o texto de um elemento utilizando element.text
- Verificar se um elemento é apresentado na página chamando-lhe .is_displayed()
Um exemplo do Selenium em ação
Agora que temos o nosso projeto configurado, podemos finalmente começar a raspar.
Iniciar sessão
Vamos mostrar o poder do Selenium fazendo login na nossa conta do Reddit e extraindo os dados apresentados anteriormente. Vamos começar fazendo o Selenium clicar no botão de login na parte superior da página. Depois de inspecionar o HTML da página, podemos ver que o nome da classe do botão de login é _2tU8R9NTqhvBrhoNAXWWcP.
login_button = driver.find_element_by_class_name('_2tU8R9NTqhvBrhoNAXWWcP')
login_button.click()

Isto abrirá o modal de início de sessão, onde podemos ver as entradas de utilizador e palavra-passe que temos de preencher. Vamos continuar com as linhas seguintes:
driver.switch_to_frame(driver.find_element_by_class_name('_25r3t_lrPF3M6zD2YkWvZU'))
driver.find_element_by_id("loginUsername").send_keys('USERNAME')
driver.find_element_by_id("loginPassword").send_keys('PASSWORD')
driver.find_element_by_xpath("//button[@type='submit']").click()
Se inspeccionarmos o elemento modal, podemos ver que o seu contentor é um iframe. É por isso que temos de mudar para a frame na primeira parte do código, uma vez que selecionar os inputs sem ela resultará num erro.
A seguir, obtemos os elementos de entrada e fornecemos-lhes as credenciais adequadas antes de premir o botão de submeter. Isto vai levar-nos de volta à página /r/learnprogramming, mas agora estamos registados e prontos para votar!
Tirar uma captura de ecrã
Tirar uma captura de ecrã utilizando o Selenium e o Python é bastante fácil. Tudo o que tem de fazer é escrever o seguinte comando no ficheiro scraper.py depois de declarar o web driver.
driver.save_screenshot('screenshot.png')
É útil saber que pode definir o tamanho da janela do Google Chrome adicionando as seguintes linhas de código:
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--window-size=1920,1080")
É assim que a captura de ecrã ficará no nosso caso:

Extração de dados
Como dissemos anteriormente, precisamos de obter o título, o autor e o número de votos positivos dos posts. Vamos começar importando os pacotes BeautifulSoup e Pandas e criando três arrays vazios para cada tipo de informação que precisamos.
from bs4 import BeautifulSoup
import pandas as pd
titles = []
upvotes = []
authors = []
Vamos utilizar o BeautifulSoup para analisar o documento HTML, escrevendo as seguintes linhas:
content = driver.page_source
soup = BeautifulSoup(content, features="html.parser")
Depois de inspecionar com êxito o documento HTML e escolher os selectores corretos, vamos agora obter os títulos, os votos positivos e os autores e atribuí-los à matriz correta:
for element in soup.findAll('div', attrs={'class': '_1oQyIsiPHYt6nx7VOmd1sz'}):
title = element.find('h3', attrs={'class': '_eYtD2XCVieq6emjKBH3m'})
upvote = element.find('div', attrs={'class': '_3a2ZHWaih05DgAOtvu6cIo'})
author = element.find('a', attrs={'class': '_23wugcdiaj44hdfugIAlnX'})
titles.append(title.text)
upvotes.append(upvote.text)
authors.append(author.text)
Por fim, armazenaremos as informações num ficheiro CSV utilizando o pacote Pandas que importámos anteriormente.
df = pd.DataFrame({'Post title': titles, 'Author': authors, 'Number of upvotes': upvotes})
df.to_csv('posts.csv', index=False, encoding='utf-8')
É isso mesmo! Vejamos o ficheiro exportado:

Parece ter todas as informações de que necessitamos.
Dica de bónus: Por vezes, precisamos de mais dados do que aqueles que o sítio Web fornece no primeiro carregamento. Na maioria das vezes, a ação de obtenção de dados é activada quando o utilizador faz scroll para baixo. Se for necessário rolar para baixo para obter mais dados, você pode usar o método .execute_script() desta forma:
scrollDown = "window.scrollBy(0,2000);"
driver.execute_script(scrollDown)
Considerações finais
Espero que tenhas gostado de criar o web scraper tanto quanto eu. Programar nem sempre é divertido, mas construir pequenos scripts como este faz-me lembrar de quando eu estava a começar, e torna o processo muito mais divertido.
Ainda assim, o script que conseguimos construir neste tutorial não pode fazer muito trabalho duro. Faltam-lhe algumas funcionalidades essenciais que fazem com que o web scraping seja perfeito. A ligação através de proxies móveis ou residenciais e a resolução de CAPTCHAs são apenas algumas delas.
Se está à procura de uma forma mais profissional de extrair dados, veja o que o WebScrapingAPI pode fazer e veja por si próprio se existe uma correspondência. Existe um pacote gratuito, pelo que o único investimento são 30 minutos da sua atenção.
Obrigado por dedicar algum tempo a ler isto. Boa raspagem!




