Saltar para o conteúdo
Comece grátis
Voltar ao blogue

Alternativas ao PhantomJS: O que utilizar agora e como fazer a migração

Sorin-Gabriel MaricaÚltima atualização em 21 min read
Alternativas ao PhantomJS: O que utilizar agora e como fazer a migração
Resumo: A melhor alternativa ao PhantomJS depende do que o seu script antigo fazia, porque o desenvolvimento do PhantomJS foi suspenso em março de 2018. Utilize o Playwright para a maioria dos projetos novos, o Puppeteer para a migração mais curta em Node.js quando só precisa do Chrome, e o Selenium se os seus testes já correm numa grelha WebDriver. Se a página for renderizada no servidor, basta um cliente HTTP e um analisador.

A melhor alternativa ao PhantomJS depende do que o seu script antigo fazia. Para a maioria dos novos projetos, utilize o Playwright. Se estiver a utilizar o Node.js e precisar apenas do Chrome, o Puppeteer é a opção mais simples. Se os seus testes já forem executados numa rede WebDriver, mude para o Selenium com o Chrome ou o Firefox em modo headless. Se a página for renderizada pelo servidor, poderá nem precisar de um navegador. Basta um cliente HTTP e um analisador.

Precisa de uma alternativa porque o desenvolvimento do PhantomJS foi suspenso em março de 2018 e o seu repositório no GitHub está agora arquivado. Este guia confirma as datas, associa cada tarefa antiga a uma ferramenta, mapeia as chamadas do PhantomJS linha a linha para o Playwright e o Puppeteer e mostra como remover os pacotes remanescentes que mantêm o PhantomJS nas suas compilações.

Pontos-chave

  • O desenvolvimento do PhantomJS foi suspenso em março de 2018. A última versão é a 2.1.1 (janeiro de 2016) e o repositório passou a ser de leitura única em maio de 2023.
  • O CasperJS e o Zombie.js também estão arquivados, pelo que não constituem alternativas.
  • O Playwright é o substituto geral mais próximo, e o seu motor WebKit é o que mais se assemelha à renderização do PhantomJS.
  • A maioria das chamadas do PhantomJS tem equivalentes diretos: page.open torna-se page.goto, e page.render torna-se page.screenshot ou page.pdf.
  • Se os dados estiverem no HTML inicial, um cliente HTTP é mais rápido do que qualquer navegador.

O PhantomJS foi descontinuado?

Sim. O desenvolvimento do PhantomJS foi suspenso em março de 2018, depois de o seu principal mantenedor se ter afastado em 2017. A última versão estável é a 2.1.1, de janeiro de 2016, e o repositório do GitHub foi arquivado como de leitura apenas em maio de 2023. Uma vulnerabilidade conhecida relacionada com a leitura de ficheiros, a CVE-2019-17221, não tem nenhuma versão corrigida.

O PhantomJS era um navegador sem interface gráfica programável, construído com base no QtWebKit e controlado por JavaScript. Ariya Hidayat lançou-o em 2011 e, durante anos, foi a forma padrão de extrair dados de páginas JavaScript, capturar capturas de ecrã, renderizar PDFs e executar testes de front-end em CI sem um ecrã. Posteriormente, o Chrome lançou o seu próprio modo sem interface gráfica, e a razão para manter uma compilação separada do WebKit deixou de existir.

Data

Evento

Fonte

Janeiro de 2011

Primeiro lançamento público

Histórico do projeto (primeiro commit em dezembro de 2010)

23 de janeiro de 2016

Anunciado o PhantomJS 2.1. A versão 2.1.1 seguiu-se a 24 de janeiro de 2016 e continua a ser a última versão estável

Lançamentos em phantomjs.org, tag no GitHub

Abr. de 2017

O mantenedor Vitaly Slobodin afasta-se, pouco depois do lançamento do Chrome «headless» no Chrome 59

Lista de correio do PhantomJS

3 de março de 2018

A issue n.º 15344 anuncia «Arquivamento do projeto: suspensão do desenvolvimento»

Tópico no GitHub

2019

CVE-2019-17221: leitura arbitrária de ficheiros através de file:// URLs em page.open(), pontuação CVSS 3.1 de 7,5 (Alta), sem correção

NVD

30 de maio de 2023

Repositório do GitHub arquivado (somente leitura)

Banner do repositório do GitHub

Na prática, «descontinuado» significa quatro coisas. Não são lançadas correções de segurança, pelo que o CVE acima permanece em aberto. Não são introduzidas novas funcionalidades da plataforma web, porque o motor é uma compilação do WebKit de 2016 que não inclui anos de alterações em CSS e JavaScript. Os wrappers do npm estão obsoletos. O Selenium removeu o suporte ao PhantomJS, pelo que os conjuntos de testes baseados nele não podem ser atualizados. Os binários antigos ainda iniciam e carregam páginas simples, mas não têm manutenção e não são seguros para páginas que não controla.

O CasperJS foi descontinuado?

Sim. O repositório do CasperJS no GitHub foi arquivado em junho de 2020 e indica que já não é mantido ativamente. A sua última versão, 1.1.4-2, foi lançada em novembro de 2017. O CasperJS era uma camada de scripts que funcionava no PhantomJS ou no SlimerJS, pelo que não pode substituir o PhantomJS. Em vez disso, transfira os scripts do CasperJS para o Playwright ou para o Puppeteer.

Os scripts do CasperJS são uma sequência de passos de navegação, o que facilita a sua portabilidade. Cada then passo torna-se uma chamada de espera, e os localizadores do Playwright aguardam os elementos por si próprios, pelo que a maioria das esperas explícitas desaparece:

CasperJS

Playwright (Node)

casper.start(url) / casper.thenOpen(url)

await page.goto(url)

casper.thenClick(sel)

await page.locator(sel).click()

casper.waitForSelector(sel, fn)

await page.locator(sel).waitFor()

casper.capture('shot.png')

await page.screenshot({ path: 'shot.png' })

O Zombie.js também foi arquivado. A sua última versão, a 6.1.4, foi lançada em novembro de 2018. Nunca foi um navegador verdadeiro: simulava um DOM dentro do Node.js, pelo que não consegue renderizar páginas nem capturar capturas de ecrã. Os testes escritos para ele adaptam-se melhor ao executor de testes do Playwright.

O SlimerJS, o projeto baseado no Gecko que partilhava a API do PhantomJS, está inativo há anos. Nenhuma destas três ferramentas tem lugar num novo projeto.

O que deve substituir o PhantomJS?

Escolha de acordo com o que o seu script do PhantomJS fazia. Utilize o Playwright para scraping, capturas de ecrã e testes em vários navegadores. Utilize o Puppeteer para automação do Chrome exclusivamente no Node e para PDFs. Utilize o Selenium WebDriver se os seus testes já forem executados numa rede WebDriver. Se os dados estiverem no HTML inicial da página, ignore o navegador e utilize um cliente HTTP.

A maioria das equipas utilizava o PhantomJS para realizar uma de um conjunto de tarefas. Encontre a sua na coluna da esquerda:

O que o seu script do PhantomJS fazia

Utilize agora

Porquê

Extraiu dados de páginas renderizadas em JavaScript

Playwright ou Puppeteer

Uma versão atual do Chromium, com espera integrada, e page.evaluate funciona da mesma forma

Páginas renderizadas pelo servidor extraídas

Um cliente HTTP e um analisador de HTML

Não é necessário um navegador, pelo que é mais rápido e mais barato de executar

Capturas de ecrã

Playwright ou Puppeteer page.screenshot()

Capturas de ecrã de página inteira e de elementos estão integradas

PDFs gerados

Puppeteer page.pdf() ou Playwright page.pdf() (apenas Chromium)

A funcionalidade «Imprimir para PDF» substitui page.render('file.pdf')

Execução de testes unitários no Karma

O lançador «Chrome Headless» do Karma a curto prazo; um executor de testes moderno a longo prazo

O próprio Karma está obsoleto

Executou testes do Selenium através do GhostDriver

Selenium com o Chrome ou o Firefox em modo headless

O Selenium 4 removeu o suporte ao PhantomJS

Era necessária especificamente a renderização WebKit

Playwright WebKit

O motor mais semelhante ao QtWebKit do PhantomJS

Executava testes em Java sem um navegador real

HtmlUnit

Um navegador mantido, sem interface gráfica, para Java

Nenhuma ferramenta isolada substituiu o PhantomJS. Os navegadores modernos passaram a dispor de um verdadeiro modo «headless» e são agora controlados por um conjunto de bibliotecas. É por isso que uma decisão caso a caso, script a script, funciona melhor do que uma escolha a nível de toda a equipa.

Quais são as alternativas ao PhantomJS que ainda são mantidas?

O Playwright, o Puppeteer e o Selenium são mantidos ativamente e cobrem praticamente todos os casos de utilização do PhantomJS. O Headless Chrome também pode ser executado sozinho a partir da linha de comandos. O HtmlUnit é mantido para testes em Java sem um navegador real. O Splash ainda existe para utilizadores do Scrapy, mas raramente é lançado. O CasperJS, o Zombie.js e o próprio PhantomJS estão arquivados.

Ferramenta

Estado

Protocolo

Linguagens

Motores

Ideal para

Playwright

Ativo

Protocolo Chrome DevTools para o Chromium; protocolos próprios do Playwright para o Firefox e o WebKit

JavaScript/TypeScript, Python, Java, .NET

Chromium, Firefox, WebKit

A maior parte do trabalho recente, testes entre navegadores, paridade com o WebKit

Puppeteer

Ativo

Protocolo Chrome DevTools; WebDriver BiDi para o Firefox

JavaScript/TypeScript

Chrome, Firefox

Node.js Automatização do Chrome, PDFs

Selenium WebDriver

Ativo

W3C WebDriver, WebDriver BiDi

Java, Python, C#, Ruby, JavaScript

Todos os principais navegadores

Conjuntos de testes existentes, redes de testes, várias linguagens

Headless Chrome (CLI)

Ativo

Opções de linha de comandos; Protocolo Chrome DevTools

Qualquer (shell)

Chrome

Capturas de ecrã pontuais, PDFs, dumps do DOM

HtmlUnit

Ativo (5.6.0, outubro de 2026)

Em processo

Java

Motor próprio, sem renderização

Testes Java sem navegador

Splash

Baixa atividade (última atualização de código em agosto de 2024)

API HTTP e scripts Lua

Qualquer (via HTTP)

Baseado em WebKit

Configurações existentes do Scrapy

CasperJS, Zombie.js, PhantomJS

Arquivado

n/a

n/a

n/a

Migrar para outra plataforma

Playwright

O Playwright é mantido pela Microsoft e controla o Chromium, o Firefox e o WebKit através de uma única API. Os seus localizadores aguardam que os elementos estejam ligados, visíveis e estáveis antes de agirem, o que elimina a maior parte do código de temporização que os scripts do PhantomJS continham. Cada contexto de navegador é isolado, com os seus próprios cookies e armazenamento, pelo que é possível executar várias sessões num único processo do navegador. Inclui também um executor de testes com rastreio, capturas de ecrã em caso de falha e trabalhadores paralelos.

Para os utilizadores do PhantomJS, o motor WebKit é o detalhe fundamental. Se precisar de reproduzir capturas de ecrã antigas do PhantomJS ou verificar como uma página é renderizada num motor semelhante ao do Safari, inicie webkit em vez de chromium e mantenha o resto do script inalterado.

As equipas de Python obtêm a mesma API através de pip install playwright seguido de playwright install, e as equipas de Java podem adicionar o com.microsoft.playwright pacote Maven. O nosso guia de web scraping do Playwright aborda seletores, paginação e exportação de dados, e a documentação do Playwright lista todas as APIs utilizadas abaixo.

Puppeteer

O Puppeteer é mantido pela equipa do Chrome e foi inicialmente desenvolvido para o Node.js. É a adaptação mais simples do PhantomJS para JavaScript, porque o objeto de página assíncrono e page.evaluate parece familiar, e um script típico mantém a sua estrutura. Lida bem com capturas de ecrã e geração de PDF, e agora controla o Firefox através do WebDriver BiDi, para além do Chrome.

A principal diferença entre o PhantomJS e o Puppeteer reside no motor. O Puppeteer controla uma versão atual do Chrome, enquanto o PhantomJS executa uma compilação do WebKit de 2016. As páginas que apresentam erros no PhantomJS devido a JavaScript ou CSS modernos são normalmente renderizadas corretamente no Puppeteer, sem necessidade de tratamento especial.

Para um guia completo sobre seletores, navegação e extração de dados, leia o nosso guia sobre scraping com o Puppeteer e o Node.js. A documentação do Puppeteer aborda as opções de execução, incluindo o headless: 'shell' modo descrito abaixo.

Selenium WebDriver

O Selenium implementa a norma WebDriver do W3C, com ligações oficiais para Java, Python, C#, Ruby e JavaScript. É compatível com todos os principais navegadores, é escalável através do Selenium Grid e está a adicionar o WebDriver BiDi para eventos bidirecionais, tais como registos da consola e atividade de rede. Ao contrário do Puppeteer, não depende do Protocolo Chrome DevTools para os seus comandos principais. É a escolha natural para equipas de Java e Ruby que utilizavam o PhantomJS e para conjuntos de testes que executavam o PhantomJS através do GhostDriver.

As ligações Python tornaram o PhantomJS obsoleto na versão 3.8.1 e eliminaram-no na 4.0 Alpha 6, pelo que webdriver.PhantomJS() já não existe. Troque pelo Chrome ou pelo Firefox com a opção «headless», e os seus localizadores e asserções continuarão a funcionar. Em Java, isso significa new ChromeOptions().addArguments("--headless=new").

Se estiver a começar do zero em Python, consulte o nosso guia para criar um scraper Selenium em Python. A documentação do Selenium aborda drivers, tempos de espera e configuração do Grid.

O Chrome «headless» por si só

O Chrome funciona em modo headless desde a versão 59, em 2017. Desde a versão 112, o modo headless corresponde ao mesmo navegador que o Chrome normal, sem janelas visíveis. A implementação mais antiga e separada continua a existir como um binário autónomo chamado chrome-headless-shell (desde o Chrome 132), que o Puppeteer disponibiliza como headless: 'shell'.

As tarefas pontuais não necessitam de uma biblioteca. Um único comando substitui um pequeno script do PhantomJS:

google-chrome --headless --screenshot=shot.png --window-size=1280,800 https://books.toscrape.com/
google-chrome --headless --print-to-pdf=page.pdf https://books.toscrape.com/
google-chrome --headless --dump-dom https://books.toscrape.com/ > page.html

Os parâmetros estão documentados na documentação do modo «headless» do Chrome. Os leitores de Python podem comparar as opções na nossa visão geral dos navegadores «headless» em Python.

HtmlUnit e Splash

O HtmlUnit é um navegador sem interface gráfica para programas em Java. Executa JavaScript, mas não renderiza píxeis, pelo que é adequado para testes em Java que verificam a lógica das páginas e os formulários, e não para capturas de ecrã. É atualizado ativamente, tendo a versão mais recente, a 5.6.0, sido lançada em outubro de 2026.

O Splash é um serviço de renderização programável com uma API HTTP e scripts Lua, utilizado principalmente através do Scrapy-Splash. Continua a funcionar para as equipas que já o utilizam, mas a atividade de desenvolvimento tem sido reduzida desde 2024. Para novos projetos de scraping, o Playwright é a escolha mais segura.

Se estiver a comparar o Puppeteer com os seus próprios rivais, em vez de substituir o PhantomJS, consulte a nossa comparação de alternativas ao Puppeteer.

Como é que os comandos do PhantomJS correspondem ao Playwright e ao Puppeteer?

A maioria das chamadas do PhantomJS tem um equivalente direto tanto no Playwright como no Puppeteer, pelo que a migração consiste, na sua maioria, numa simples mudança de nome. page.open torna-se page.goto, page.render torna-se page.screenshot ou page.pdf, page.evaluate mantém o seu nome, e os callbacks passam a ser async/await. A verdadeira mudança está na espera. Substitua os tempos de espera fixos por esperas baseadas no seletor ou no estado de carregamento.

PhantomJS

Playwright (Node.js)

Puppeteer

require('webpage').create()

const page = await browser.newPage()

const page = await browser.newPage()

page.open(url, callback)

await page.goto(url)

await page.goto(url)

page.evaluate(fn)

await page.evaluate(fn, arg)

await page.evaluate(fn, ...args)

page.render('shot.png')

await page.screenshot({ path: 'shot.png', fullPage: true })

await page.screenshot({ path: 'shot.png', fullPage: true })

page.render('doc.pdf') com page.paperSize

await page.pdf({ path: 'doc.pdf', format: 'A4' }) (apenas Chromium)

await page.pdf({ path: 'doc.pdf', format: 'A4' })

page.viewportSize = { width, height }

await page.setViewportSize({ width, height })

await page.setViewport({ width, height })

page.settings.userAgent = ua

await browser.newContext({ userAgent: ua })

await page.setUserAgent({ userAgent: ua })

phantom.addCookie(cookie)

await context.addCookies([cookie])

await browser.setCookie(cookie)

page.onConsoleMessage = fn

page.on('console', (msg) => …)

page.on('console', (msg) => …)

page.onResourceRequested = fn

await page.route('**/*', (route) => …)

await page.setRequestInterception(true) mais page.on('request', …)

page.injectJs(file) / page.includeJs(url)

await page.addScriptTag({ path }) ou ({ url })

await page.addScriptTag({ path }) ou ({ url })

page.sendEvent('click', x, y)

await page.locator(sel).click()

await page.click(sel)

setTimeout espera / page.onLoadFinished

await page.locator(sel).waitFor() ou await page.waitForLoadState()

await page.waitForSelector(sel)

--proxy=host:port opção de linha de comando

chromium.launch({ proxy: { server: 'http://host:port' } })

puppeteer.launch({ args: ['--proxy-server=host:port'] })

system.args

process.argv

process.argv

phantom.exit()

await browser.close()

await browser.close()

Foram alteradas duas linhas nas versões recentes do Puppeteer. Os cookies agora residem no navegador ou no contexto do navegador (browser.setCookie), uma vez que os métodos de cookies ao nível da página foram descontinuados. E setUserAgent aceita um objeto de opções. Os tutoriais mais antigos que chamam page.setCookie continuam a funcionar, mas apresentam avisos de obsolescência.

Antes: um script PhantomJS

Este script abre a loja de treino «Books to Scrape», lê o título da página e os primeiros cinco links de livros, guarda uma captura de ecrã e encerra:

// legacy.js (PhantomJS 2.1.1): run with `phantomjs legacy.js`
var page = require('webpage').create();
var url = 'https://books.toscrape.com/';

page.viewportSize = { width: 1280, height: 800 };

page.open(url, function (status) {
  if (status !== 'success') {
    console.log('Failed to load ' + url);
    phantom.exit(1);
  }
  var data = page.evaluate(function () {
    var links = document.querySelectorAll('article.product_pod h3 a');
    return {
      title: document.title.trim(),
      books: Array.prototype.slice.call(links, 0, 5).map(function (a) {
        return { title: a.getAttribute('title'), href: a.href };
      })
    };
  });
  console.log(JSON.stringify(data, null, 2));
  page.render('books.png');
  phantom.exit();
});

Depois: o mesmo script no Playwright

Instale o Playwright com npm install playwright e npx playwright install chromium, depois execute o código como um módulo ES:

// modern.mjs (Playwright for Node.js): run with `node modern.mjs`
import { chromium } from 'playwright';

const url = 'https://books.toscrape.com/';
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1280, height: 800 } });

try {
  await page.goto(url);
  await page.locator('article.product_pod').first().waitFor();

  const data = await page.evaluate(() => ({
    title: document.title.trim(),
    books: [...document.querySelectorAll('article.product_pod h3 a')]
      .slice(0, 5)
      .map((a) => ({ title: a.getAttribute('title'), href: a.href })),
  }));

  console.log(JSON.stringify(data, null, 2));
  await page.screenshot({ path: 'books.png', fullPage: true });
} finally {
  await browser.close();
}

Ambos os scripts apresentam os mesmos dados:

{
  "title": "All products | Books to Scrape - Sandbox",
  "books": [
    {
      "title": "A Light in the Attic",
      "href": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html"
    },
    {
      "title": "Tipping the Velvet",
      "href": "https://books.toscrape.com/catalogue/tipping-the-velvet_999/index.html"
    },
    {
      "title": "Soumission",
      "href": "https://books.toscrape.com/catalogue/soumission_998/index.html"
    },
    {
      "title": "Sharp Objects",
      "href": "https://books.toscrape.com/catalogue/sharp-objects_997/index.html"
    },
    {
      "title": "Sapiens: A Brief History of Humankind",
      "href": "https://books.toscrape.com/catalogue/sapiens-a-brief-history-of-humankind_996/index.html"
    }
  ]
}

A estrutura quase não muda. A função de retorno passa a ser de nível superior await, try/finally substitui as chamadas dispersas phantom.exit() chamadas dispersas, para que o navegador feche sempre, e uma espera explícita nos cartões de produtos substitui a esperança de que page.open seja disparada tarde o suficiente. A função que passa para page.evaluate continua a ser executada dentro da página, pelo que o seu código DOM é transferido tal como está, e pode eliminar as soluções alternativas ES5, tais como Array.prototype.slice.call.

Para utilizar o Puppeteer em vez disso, importa puppeteer, chame puppeteer.launch(), define a janela de visualização com page.setViewport()e substitua a espera do localizador por page.waitForSelector('article.product_pod'). Tudo o resto permanece igual.

Como se faz a migração de um script do PhantomJS passo a passo?

Faça um inventário do que cada script faz e, em seguida, escolha o substituto adequado para cada tarefa. Instale o Playwright ou o Puppeteer e adapte as chamadas utilizando a tabela de mapeamento. Substitua os tempos de espera fixos por esperas de seletor e compare os resultados com capturas de ecrã ou dados antigos. Por fim, remova os binários do PhantomJS e os pacotes wrapper das suas dependências, imagens de CI e ficheiros Dockerfile.

  1. Inventário. Pesquise na base de código por phantomjs, require('webpage'), casper, GhostDriver, e karma-phantomjs-launcher. Verifique também as configurações de CI e os ficheiros Dockerfile, pois o PhantomJS costuma estar oculto numa etapa de compilação, em vez de no código da aplicação.
  2. Classifique cada script por tarefa. Utilize a tabela de seleção rápida acima. Uma tarefa de captura de ecrã e um conjunto de testes do Selenium requerem substituições diferentes, mesmo no mesmo repositório.
  3. Instale a substituição. O Playwright descarrega as suas próprias compilações de navegador com npx playwright install, pelo que a CI necessita dessa etapa ou da imagem Docker oficial. As equipas de Python utilizam pip install playwright e playwright install em vez disso.
  4. Adapte as chamadas. Siga a tabela de mapeamento. Os callbacks passam a ser async/await, e as propriedades dos manipuladores de eventos, tais como page.onConsoleMessage passam a ser page.on(...) ouvintes.
  5. Corrija as esperas. Esta é a fonte mais comum de diferenças após uma migração. Substitua todos os setTimeout e onLoadFinished com uma espera pelo elemento ou estado de carregamento de que realmente necessita.
  6. Compare os resultados. Compare o HTML, os dados extraídos ou as capturas de ecrã com uma execução do PhantomJS. É de esperar que haja algumas diferenças de renderização, uma vez que o novo motor suporta tipos de letra, layout e CSS que o WebKit de 2016 não suportava.
  7. Atualize a CI e os contentores. Instale as bibliotecas de sistema de que o novo navegador necessita e remova o binário do PhantomJS e quaisquer OPENSSL_CONF ou soluções alternativas do fontconfig que tenha adicionado para o mesmo.
  8. Elimine os resíduos. Remova os pacotes e lançadores antigos, conforme explicado a seguir.

O que substitui o karma-phantomjs-launcher, o phantomjs-prebuilt e o GhostDriver?

Substitua o `karma-phantomjs-launcher` pelo lançador Chrome Headless do Karma e, em seguida, planeie a migração para fora do Karma, que já se encontra obsoleto. Remova o phantomjs-prebuilt, que o npm marca como obsoleto, e transfira os seus scripts para o Playwright ou o Puppeteer. Substitua as sessões do GhostDriver pelos controladores do Selenium para o Chrome ou o Firefox no modo headless, uma vez que o Selenium 4 removeu o PhantomJS.

É nestes resquícios que o PhantomJS costuma sobreviver por mais tempo, porque se encontram em ferramentas de teste e de automatização de navegadores que ninguém toca até que uma compilação falhe.

Karma. O repositório karma-phantomjs-launcher foi arquivado após a sua última atividade em 2017. A solução rápida consiste em instalar karma-chrome-launcher e definir browsers: ['ChromeHeadless'] em karma.conf.js. Isso mantém a suíte a funcionar corretamente, mas o Karma é o problema maior. O aviso de descontinuação do Karma indica que já não aceita novas funcionalidades nem correções gerais de erros. O Angular adicionou o Jest e o Web Test Runner como caminhos de migração, e qualquer um deles é adequado para testes unitários que costumavam ser executados no PhantomJS.

Pacotes npm. phantomjs-prebuilt (última versão 2.1.16) está marcado no npm com «este pacote está agora obsoleto», e o phantomjs aponta para ele. Ambos descarregam o binário 2.1.1, que já não é mantido. Remova-os com npm uninstall phantomjs-prebuilt phantomjse, em seguida, verifique o seu ficheiro de bloqueio, pois outras dependências de desenvolvimento por vezes os incluem.

Selenium e GhostDriver. DesiredCapabilities.PHANTOMJS e webdriver.PhantomJS() já não fazem parte do Selenium 4. Em Python, a substituição requer três linhas:

from selenium import webdriver

options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
driver = webdriver.Chrome(options=options)

O Selenium Manager encontra ou descarrega um driver compatível, pelo que já não é necessário fornecer um binário GhostDriver separado. O Firefox funciona da mesma forma com FirefoxOptions e o -headless argumento.

Imagens do Docker. Remova qualquer apt-get install phantomjs ou instalação global do PhantomJS via npm. Utilize a imagem oficial do Playwright ou siga as orientações do Puppeteer relativamente às bibliotecas de sistema de que o Chrome necessita num contentor.

Será que precisa mesmo de um navegador sem interface gráfica?

Na maioria das vezes, não. Muitos scrapers do PhantomJS foram escritos numa altura em que a renderização parecia mais segura, mas se os dados já se encontrarem no HTML inicial da página ou num endpoint JSON, um cliente HTTP acompanhado de um analisador é mais rápido e simples. Verifique primeiro o código-fonte da página e utilize um navegador apenas quando o conteúdo aparecer após a execução do JavaScript.

Uma verificação rápida demora um minuto:

  1. Abra a página e veja o seu código-fonte, não o DOM inspecionado.
  2. Procure no código-fonte um valor que pretenda extrair, como um preço ou o nome de um produto.
  3. Se não estiver lá, abra o separador «Rede» nas ferramentas de programador do seu navegador e procure por pedidos XHR ou fetch que devolvam JSON.

Se o passo 2 encontrar o valor, uma simples solicitação HTTP e um analisador obtêm-no com uma fração do tempo e da memória que um navegador necessita. Se o passo 3 encontrar um ponto de extremidade JSON, chame-o diretamente e ignore também a análise do HTML. A nossa comparação entre o Cheerio e o Puppeteer mostra ambas as abordagens lado a lado no Node.js.

Reserve o navegador para as tarefas que realmente o exigem: percorrer fluxos de cliques, iniciar sessão, deslocamento infinito, capturas de ecrã, PDFs e testes visuais.

Quando deve deixar de executar navegadores por conta própria?

Deixe de hospedar o navegador por conta própria quando a sua manutenção custar mais do que o valor dos scripts. Sinais comuns são falhas e fugas de memória em grande escala, desfasamento de versões do navegador na CI, pedidos bloqueados e a necessidade de verificar páginas a partir de vários países e dispositivos. Uma API gerida executa o navegador e devolve HTML, dados ou capturas de ecrã através de pedidos HTTP simples.

Executar um navegador sem interface gráfica é fácil. Executar centenas é uma tarefa diferente. Tem de gerir limites de simultaneidade, limpar processos do Chrome que nunca terminam, manter as compilações do navegador sincronizadas entre os portáteis dos programadores e a CI, e lidar com sites que bloqueiam o tráfego do centro de dados. Se precisar de ver uma página tal como os visitantes de outro país a vêem, também precisa de infraestrutura nesse país.

A API do Navegador da WebScrapingAPI tira esse trabalho dos seus servidores. Envia-se um URL com tempos de espera, como wait_until ou wait_for_css, e ações na página, como clicar, percorrer, digitar, selecionar e enviar. Ela devolve HTML renderizado, um DOM em JSON, campos extraídos ou uma captura de ecrã em base64. É uma interface REST de pedido-resposta sem sessão de navegador ativa, pelo que não é necessário associar o Puppeteer ou o Playwright a ela. Descreve os passos na solicitação e recebe o resultado.

No que diz respeito às tarefas de captura de ecrã e controlo de qualidade que o PhantomJS costumava realizar, a nossa solução de testes de websites em diversos mercados e dispositivos verifica páginas públicas por país, dispositivo e área de visualização, e guarda capturas de ecrã como prova.

Se precisar apenas de HTML renderizado, compare as APIs de acesso à Web para encontrar a opção mais simples.

FAQ

O PhantomJS ainda é seguro de utilizar?

Não para páginas não confiáveis. O PhantomJS não recebeu correções de segurança desde que o desenvolvimento foi suspenso em 2018, e a vulnerabilidade CVE-2019-17221 permite que uma página leia ficheiros locais page.open() sem que exista uma versão corrigida. Se tiver de o manter por um curto período, execute-o apenas em páginas que controle, num contentor isolado, enquanto efetua a migração.

Ainda posso instalar o PhantomJS a partir do npm?

Pode, mas não deve. O phantomjs-prebuilt pacote está marcado como obsoleto no npm, e os seus binários correspondem à versão 2.1.1, que já não é mantida. Os novos projetos devem instalar o Playwright ou o Puppeteer em vez disso. Ambos descarregam uma versão atual do navegador e contam com mantenedores ativos e documentação.

Qual é melhor para substituir o PhantomJS: o Playwright ou o Puppeteer?

O Playwright é adequado para a maioria das equipas. Suporta o Chromium, o Firefox e o WebKit, possui ligações para Python, Java e .NET e espera automaticamente pelos elementos. O Puppeteer é uma boa opção para projetos Node que necessitem apenas do Chrome ou para a geração de PDFs. Ambos portam scripts do PhantomJS com um esforço semelhante, uma vez que page.evaluate funcionam da mesma forma.

O Selenium ainda suporta o PhantomJS?

Não. O Selenium considerou o PhantomJS obsoleto na versão 3.8.1 e removeu-o no Selenium 4, pelo que webdriver.PhantomJS() as sessões do Selenium e do GhostDriver já não funcionam. Mude esses testes para o Chrome ou o Firefox com a opção «headless». Os seus localizadores e asserções do WebDriver permanecem, na sua maioria, os mesmos, pelo que a adaptação é normalmente mínima.

O que substituiu o PhantomJS no Karma?

O lançador Chrome Headless do Karma é o substituto direto habitual para o karma-phantomjs-launcher. No entanto, o próprio Karma está agora obsoleto. Para uma solução a longo prazo, transfira os testes unitários para um executor mantido, como o Jest ou o Web Test Runner, que o Angular adicionou como percursos de migração.

Qual é a alternativa ao PhantomJS que utiliza o WebKit?

O Playwright. Este inclui uma compilação do WebKit, a par do Chromium e do Firefox, o que o torna a opção de renderização mais semelhante ao motor QtWebKit do PhantomJS. Utilize-o quando precisar de reproduzir capturas de ecrã antigas do PhantomJS ou de testar uma renderização semelhante à do Safari. Para tudo o resto, o Chromium é o padrão comum.

Que alternativa ao PhantomJS deve escolher?

Escolha consoante a tarefa. Utilize o Playwright para a maioria das tarefas de scraping, capturas de ecrã e testes entre navegadores; o Puppeteer para automação do Chrome com Node.js e PDFs; e o Selenium para conjuntos de testes WebDriver existentes em qualquer linguagem. Antes de portar um scraper, verifique se os dados já se encontram no HTML, porque o navegador mais rápido é aquele que não executa. Em seguida, elimine os binários, wrappers e lançadores do PhantomJS para que nada volte a introduzir o motor antigo nas suas compilações.

Evite a manutenção do navegador

Renderize páginas JavaScript sem executar um navegador. Envie um URL para a API do Scraper e receba o HTML renderizado de volta. Comece com 5 000 pedidos gratuitos. A renderização de JavaScript e a segmentação geográfica não têm custos adicionais, e os pedidos falhados não são faturados.

Explora a API do Scraper

Sobre o autor

Sorin-Gabriel Marica, Desenvolvedor Full-Stack @ WebScrapingAPI

Sorin-Gabriel Marica

Desenvolvedor 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.

Web Scraping com AWS Lambda: Guia para Python e Java 2026
Guias

Web Scraping com AWS Lambda: Guia para Python e Java 2026

TL;DR: Resumo: A extração de dados da Web com o AWS Lambda funciona melhor quando cada invocação é curta, delimitada e pode ser repetida de forma independente. Comece com HTTP direto, AWS SAM e S3 e, só depois, adicione SQS, contentores, renderização no navegador, proxies ou uma camada de recuperação gerida, apenas quando a carga de trabalho demonstrar que precisa deles.

Suciu Dan32 min read
Ler artigo
Como utilizar o GoSpider: rastrear, limpar URLs e extrair dados
Guias

Como utilizar o GoSpider: rastrear, limpar URLs e extrair dados

TL;DR: Resumo: O GoSpider é um rastreador de linha de comandos destinado a descobrir URLs, não um extrator completo de dados estruturados. Este guia sobre como utilizar o GoSpider mostra como realizar um rastreio limitado, gerir resultados de forma organizada, fazer a transferência de dados do Colly para CSV e seguir um percurso de diagnóstico para respostas 403 ou páginas que exijam renderização em JavaScript.

Suciu Dan23 min read
Ler artigo
Como fazer o Scrape Redfin: Guia Python para Dados de Propriedade
Guias

Como fazer o Scrape Redfin: Guia Python para Dados de Propriedade

TL;DR: A Redfin expõe pontos de extremidade de API ocultos que retornam JSON estruturado para listagens de propriedades, tornando possível ignorar totalmente a análise HTML frágil. Este guia orienta-o na construção de um scraper Python que extrai dados de aluguer e venda, pesquisa por localização, monitoriza novas listagens através de sitemaps XML e exporta resultados limpos para CSV ou JSON.

Suciu Dan14 min read
Ler artigo

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.