Durante anos, o Undetected Chromedriver foi um elemento básico da navegação segura e do desvio de antibot. Desde então, o desenvolvedor por trás do Undetected Chromedriver criou o NODRIVER. Com o NODRIVER, você não depende mais do Selenium ou do Webdriver. Basta instalar o pip
e tudo estará pronto para funcionar.
Neste guia, você aprenderá:
- O que é NODRIVER?
- Qual é a diferença em relação a outros navegadores sem cabeça?
- Como usar o NODRIVER?
- Quais são as limitações do NODRIVER?
- Como usar o NODRIVER com um proxy?
- Alternativas sólidas ao NODRIVER
O que é o NODRIVER e por que você deve se importar?
O que é exatamente o NODRIVER?
O NODRIVER é o sucessor totalmente assíncrono do Undetected Chromedriver. Usando as “práticas recomendadas” como padrão para todos os kwargs, ele foi projetado para funcionar imediatamente com apenas uma pequena quantidade de código.
O NODRIVER apresenta os seguintes recursos:
- Desempenho
- Sem dependências externas (nem mesmo o Chromedriver)
- Contorno do Antibot
- Cookies persistentes de sessão
- Nova instância do navegador a cada uso
O que torna o NODRIVER diferente?
O NODRIVER usa uma arquitetura radicalmente diferente do Undetected Chromedriver e até mesmo de outros navegadores sem cabeça. Tradicionalmente, esses outros navegadores dependem do Selenium ou do Chrome DevTools Protocol (CDP).
O NODRIVER usa sua própria implementação personalizada do protocolo DevTools. Na documentação, ele é chamado de “biblioteca de automação chrome (-ish)”. Com o NODRIVER, você não depende do Selenium, nem depende diretamente do CDP. O NODRIVER usa uma implementação personalizada do CDP. Para usar o NODRIVER, tudo o que você precisa é do pip e de um navegador baseado no Chrome.
Raspagem com o NODRIVER
1. Primeiros passos
Antes de começar, você precisa ter certeza de que tem o Python e um navegador instalados. Se estiver lendo este artigo, presumo que já os tenha instalado. Você pode instalar o NODRIVER diretamente com o pip.
pip install nodriver
2. Estrutura básica
Nossa estrutura básica é realmente semelhante à que você obteria com o Playwright ou o Puppeteer. Se estiver interessado em usar o Playwright em Python, você pode ver um guia completo sobre a extração de listagens da Amazon aqui. O NODRIVER tem uma sensação muito semelhante à do Playwright, mas ainda está em desenvolvimento intenso.
Esta é a nossa estrutura básica.
import nodriver
async def main():
#start the browser
browser = await nodriver.start()
base_url = "https://quotes.toscrape.com"
#navigate to a page
page = await browser.get(base_url)
###logic goes here###
#close the browser
await page.close()
if __name__ == '__main__':
#in their docs, they advise directly against asyncio.run()
nodriver.loop().run_until_complete(main())
3. Obtendo uma página
Como você provavelmente notou em nosso esqueleto básico acima, browser.get()
retorna um objeto de página
. Você pode até mesmo abrir várias páginas simultaneamente. Se você estiver disposto a ser criativo, poderá fazer operações altamente simultâneas.
O trecho abaixo é apenas teórico.
#navigate to a page
page_1 = await browser.get(base_url)
page_2 = await browser.get(a_different_url)
####do stuff with the different pages#####
4. Conteúdo dinâmico
Para lidar com o conteúdo dinâmico, você tem duas opções. Você pode usar o método .sleep() para esperar um período de tempo arbitrário ou pode usar .wait_for() para esperar por um seletor específico na página.
#wait an arbitrary amount of time
await tab.sleep(1)
#wait for a specific element
await tab.wait_for("div[data-testid='some-value']")
NOTA: No snippet acima, usei tab
em vez de page
como nome de variável. Elas são intercambiáveis. Ambos são objetos de guia. Você pode saber mais sobre as guias no NODRIVER aqui.
5. Encontrando elementos
O NODRIVER nos fornece uma variedade de métodos para localizar elementos na página. Parece que eles estão lidando com alguns métodos antigos.
Há quatro métodos diferentes baseados em texto para localizar elementos. Dois deles provavelmente desaparecerão no futuro.
#find an element using its text
my_element = page.find("some text here")
#find a list of elements by their text
my_elements = page.find_all("some text here")
#find an element using its text
my_element = page.find_element_by_text("some text here")
#find a list of elements using their text
my_elements = page.find_element_by_text("some text here")
Assim como os métodos acima, há também quatro métodos baseados em seletores para localizar elementos. Dois deles provavelmente desaparecerão. Se os desenvolvedores do NODRIVER quiserem se alinhar claramente com o CDP, os métodos query_selector
provavelmente sobreviverão.
#find a single element using its css selector
my_element = page.select("div[class='your-classname']")
#find a list of elements using a css selector
my_elements = page.select_all("div[class='your-classname']")
#find a single element using its css selector
my_element = page.query_selector("div[class='your-classname']")
#find a list of elements using a css selector
my_elements = page.query_selector_all("div[class='your-classname']")
Como você pode ver acima, não importa como você queira encontrar elementos na página, provavelmente há várias maneiras de fazer isso. Com o tempo, os desenvolvedores por trás do NODRIVER poderão melhorar isso. Dito isso, no momento, seus métodos de análise são como uma motosserra do exército suíço.
6. Extração de seus dados
O NODRIVER oferece alguns métodos para extrair dados. Você pode usar a característica .attributes
para extrair atributos diretamente. Isso não é muito fácil de usar, pois retorna uma matriz, não um objeto JSON.
Aqui está uma solução improvisada que criei para extrair o href
de um objeto de link. É feio, mas funciona. Espero que o método de atributos
seja substituído em breve por algo um pouco mais funcional.
next_button = await page.select("li[class='next'] > a")
#this returns an array
attributes = next_button.attributes
#use array indexing to find the href object and its value
for i in range(len(attributes)):
if attributes[i] == "href":
next_url = attributes[i+1]
OBSERVAÇÃO: a maioria dos outros navegadores sem cabeça contém um método get_attribute()
. No entanto, esse método ainda não está funcionando no NODRIVER.
Veja como extraímos os dados de texto. Como você pode notar, não usamos o await
aqui. Suspeito que isso mudará no futuro para se alinhar com outros navegadores de estilo CDP. Em sua forma atual, o texto
é apenas um atributo, não um método – o await
, na verdade, gera um erro quando usado com atributos. Isso parece contrário ao Puppeteer e ao Playwright, mas esse é o estado atual do NODRIVER – ainda em desenvolvimento intenso.
#find the quote element
quote_element = await quote.query_selector("span[class='text']")
#extract its text
quote_text = quote_element.text
7. Armazenamento de dados
Armazenaremos nossos dados em um pequeno arquivo JSON. Ao extrair citações, cada uma delas tem uma lista de tags, e as listas não se saem muito bem no formato CSV.
import json
with open("quotes.json", "w", encoding="utf-8") as f:
json.dump(scraped_data, f, ensure_ascii=False, indent=4)
8. Colocando tudo junto
Agora, vamos reunir todos esses conceitos em um script funcional. No exemplo abaixo, usamos os conceitos acima para extrair dados do Qutoes to Scrape – um site criado apenas para tutoriais de raspagem. Copie e cole o código abaixo para ter uma ideia de como o NODRIVER realmente funciona.
import nodriver
import json
async def main():
#list to hold scraped data
scraped_data = []
browser = await nodriver.start()
next_url = "/"
base_url = "https://quotes.toscrape.com"
#while we still have urls to scrape
while next_url:
#go to the page
page = await browser.get(f"{base_url}{next_url}")
#find quote divs using a selector
quotes = await page.select_all("div[class='quote']")
#iterate through the quotes
for quote in quotes:
#find the quote element and extract its text
quote_element = await quote.query_selector("span[class='text']")
quote_text = quote_element.text
#find the author and extract the text
author_element = await quote.query_selector("small[class='author']")
author = author_element.text
#find the tag elements
tag_elements = await quote.query_selector_all("a[class='tag']")
tags = []
#iterate through the tags and extract their text
for tag_element in tag_elements:
text = tag_element.text
tags.append(text)
#add our extracted data to the list of scraped data
scraped_data.append({
"quote": quote_text,
"author": author,
"tags": tags
})
#check the page for a "next" button
next_button = await page.select("li[class='next'] > a")
#if it doesn't exist, close the browser and break the loop
if next_button == None:
await page.close()
next_url = None
#if it does, follow this block instead
else:
attributes = next_button.attributes
#loop through the attributes to find your desired attribute, its value is the next index
for i in range(len(attributes)):
if attributes[i] == "href":
next_url = attributes[i+1]
#write the data to a json file
with open("quotes.json", "w", encoding="utf-8") as f:
json.dump(scraped_data, f, ensure_ascii=False, indent=4)
if __name__ == '__main__':
nodriver.loop().run_until_complete(main())
Se você executar o script acima, obterá um arquivo JSON com objetos como o que você vê abaixo.
[
{
"quote": "“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”",
"author": "Albert Einstein",
"tags": [
"change",
"deep-thoughts",
"thinking",
"world"
]
},
{
"quote": "“It is our choices, Harry, that show what we truly are, far more than our abilities.”",
"author": "J.K. Rowling",
"tags": [
"abilities",
"choices"
]
},
Limitações atuais do NODRIVER
Atualmente, o NODRIVER tem algumas limitações sérias que merecem ser observadas. Vamos examiná-las.
Modo sem cabeça
O NODRIVER gera um erro sempre que o executamos no modo headless. Não temos certeza se isso é intencional (como um desvio antibot) ou um problema legítimo.
Interações de páginas
Embora o NODRIVER tenha várias interações de página listadas em seus documentos, a maioria delas funciona parcialmente ou não funciona. Como você pode ver, isso está documentado na captura de tela abaixo, tanto para click_mouse()
quanto para mouse_click()
.
Extração de atributos
O maior problema do NODRIVER é a extração de atributos. Como mencionado anteriormente, isso gera uma matriz e é extremamente arcaico, como você viu em nossa solução alternativa de href
. Aqui está a saída literal do atributo
. Para a raspagem em nível de produção, isso precisa ser resolvido.
Uso de proxy com o NODRIVER
Atualmente, o suporte a proxy do NODRIVER é limitado. Eles fornecem um método create_context()
para conexão proxy.
O trecho abaixo vem diretamente da página de problemas deles. No entanto, depois de horas tentando esse e vários outros métodos, ainda não consegui me conectar.
tab = await browser.create_context("https://www.google.nl", proxy_server='socks5://myuser:mypass@somehost')
# or add new_window=True if you would like a new window
Se você observar a documentação, há uma seção sobre proxies[1]. Embora haja uma seção oficial de proxy, não há documentação real. Presumimos que isso será corrigido em um futuro próximo.
Alternativas viáveis
Embora não esteja pronto para uso em produção no momento, espero que o NODRIVER faça grandes coisas no futuro. Se estiver procurando por algo mais pesado, dê uma olhada nos navegadores abaixo.
- Selênio: Forte desde 2004. O Selenium depende do Chromedriver, mas é testado em batalha e está pronto para a produção. Saiba mais sobre o Selenium web scraping.
- Playwright: O Playwright parece uma versão polida e pronta para uso do que você viu neste tutorial com o NODRIVER. Saiba como usar o Playwright para raspagem da Web.
Conclusão
O NODRIVER é uma ferramenta nova e interessante para automação do navegador, mas o rápido desenvolvimento significa que alguns recursos ainda estão amadurecendo. Para obter uma raspagem da Web confiável e em grande escala, considere o uso de soluções robustas como:
- Proxies residenciais: Conexões de dispositivos reais para contornar bloqueios geográficos.
- Web Unlocker: Proxies gerenciados com solucionador de CAPTCHA integrado.
- Navegador de raspagem: Automação remota do navegador com suporte a proxy e CAPTCHA. A solução perfeita para projetos de raspagem em várias etapas.
- Raspador personalizado: Execute trabalhos de raspagem personalizados sem necessidade de código e com extração de dados assistida por especialistas.
Inscreva-se para uma avaliação gratuita e comece hoje mesmo!
Não é necessário cartão de crédito