Existe uma maneira de usar o PhantomJS em Python?

203

Eu quero usar o PhantomJS em Python . Pesquisei esse problema no Google, mas não consegui encontrar soluções adequadas.

Acho que os.popen() pode ser uma boa escolha. Mas não pude passar alguns argumentos para isso.

Usar subprocess.Popen()pode ser uma solução adequada por enquanto. Quero saber se há uma solução melhor ou não.

Existe uma maneira de usar o PhantomJS em Python?

folheto
fonte
Minha resposta abaixo mostra como fazer isso. Basta olhar para a sua pergunta e é exatamente isso que o Selenium faz, subprocess.popenmas com alguns recursos estendidos para tornar a API perfeita.
Pykler
@flyer: Você provavelmente deve considerar alterar a resposta aceita, veja abaixo. Obrigado.
dotancohen

Respostas:

373

A maneira mais fácil de usar o PhantomJS em python é via Selenium. O método mais simples de instalação é

  1. Instalar o NodeJS
  2. Usando o gerenciador de pacotes do Node, instale phantomjs: npm -g install phantomjs-prebuilt
  3. instale o selenium (no seu virtualenv, se você estiver usando isso)

Após a instalação, você pode usar o phantom tão simples quanto:

from selenium import webdriver

driver = webdriver.PhantomJS() # or add to your PATH
driver.set_window_size(1024, 768) # optional
driver.get('https://google.com/')
driver.save_screenshot('screen.png') # save a screenshot to disk
sbtn = driver.find_element_by_css_selector('button.gbqfba')
sbtn.click()

Se a variável de ambiente do caminho do sistema não estiver configurada corretamente, você precisará especificar o caminho exato como argumento para webdriver.PhantomJS(). Substitua isto:

driver = webdriver.PhantomJS() # or add to your PATH

... com o seguinte:

driver = webdriver.PhantomJS(executable_path='/usr/local/lib/node_modules/phantomjs/lib/phantom/bin/phantomjs')

Referências:

Pykler
fonte
40
Isso funcionou lindamente e provavelmente me salvou dias. Obrigado. Se alguém quiser que toda a página renderizada volte como fonte, é isso driver.page_source.
scharfmn
4
Isso funciona lindamente e estou agradavelmente surpreendido porque phantomjs.org/faq.html diz "não é um módulo Node.js." - mas o wrapper npm em npmjs.org/package/phantomjs faz com que se comporte para esse fim. No meu caso, eu queria fazer isso: bodyStr= driver.find_element_by_tag_name("body").get_attribute("innerHTML")e ... funcionou!
MarkHu
8
Concordo que o fantasma tem dependências malucas, e na verdade não consegui colocá-lo em funcionamento mesmo depois de instalar milhões de bibliotecas relacionadas ao X11. O fantasma é uma história de horror.
Pykler 13/05
5
@phabtar Você precisa passar o caminho para o phantomjs como o primeiro argumento para o PhantomJS ... ou corrigir o syspath do Windows para poder ver o phantomjs.
Pykler 23/07
2
Pergunta idiota: por que eu tenho que instalar o node-js? não há outra maneira de obter pahantomJs?
Eildosa
80

O PhantomJS recentemente abandonou completamente o suporte ao Python . No entanto, o PhantomJS agora incorpora o Ghost Driver .

Um novo projeto, desde então, subiu para preencher o vazio: ghost.py. Você provavelmente deseja usar isso:

from ghost import Ghost
ghost = Ghost()

with ghost.start() as session:
    page, extra_resources = ghost.open("http://jeanphi.me")
    assert page.http_status==200 and 'jeanphix' in ghost.content
Martijn Pieters
fonte
21
Embora o suporte tenha sido descartado, descobri que instalar o npm (gerenciador de pacotes de nós) e usá-lo para instalar os phantomjs mais recentes (com suporte a webdriver) e instalar selênio em python ... muito mais fácil do que tentar fazer o PyQT ou o PySide funcionar corretamente. O que é legal no fantasma é realmente decapitado e não requer bibliotecas relacionadas à UI / X11 para funcionar.
Pykler 29/03
12
Eu adicionei uma resposta abaixo explicando a minha solução preferida depois de tentar uso ghost.py e odiando minha vida
Pykler
8
Pykler "odiar minha vida" não é um eufemismo. Se alguém mudasse a "resposta correta" para esta pergunta para a de Pykler, eu teria economizado o esforço de um dia.
usar o seguinte comando
2
@YPCrumble: infelizmente, apenas o OP pode fazer isso; altere a resposta aceita.
Martijn Pieters
3
Depois de tentar várias abordagens diferentes nesta manhã, a solução @Pykler acabou funcionando da maneira mais suave.
andyzinsser
40

Agora, desde que o GhostDriver vem junto com o PhantomJS, tornou-se ainda mais conveniente usá-lo através do Selenium.

Tentei a instalação de Node do PhantomJS, conforme sugerido por Pykler, mas na prática achei mais lento que a instalação independente do PhantomJS. Acho que a instalação autônoma não forneceu esses recursos anteriormente, mas a partir da v1.9, ela o faz muito.

  1. Instale o PhantomJS ( http://phantomjs.org/download.html ) (se você estiver no Linux, as instruções a seguir ajudarão https://stackoverflow.com/a/14267295/382630 )
  2. Instale o Selenium usando o pip.

Agora você pode usar assim

import selenium.webdriver
driver = selenium.webdriver.PhantomJS()
driver.get('http://google.com')
# do some processing

driver.quit()
Pankaj
fonte
3
agradecimentos especiais por apontar para a resposta SO referente à instalação do PhantomJS no Ubuntu, isso me ajudou.
Dennis Golomazov
Uma maneira rápida de instalar o Selenium que acabei de aprender é: no Windows, digite: C: \ Python34 \ Scripts \ pip.exe instale o Selenium.
Ntk4 21/09/16
8

Aqui está como eu testo javascript usando PhantomJS e Django:

mobile / test_no_js_errors.js :

var page = require('webpage').create(),
    system = require('system'),
    url = system.args[1],
    status_code;

page.onError = function (msg, trace) {
    console.log(msg);
    trace.forEach(function(item) {
        console.log('  ', item.file, ':', item.line);
    });
};

page.onResourceReceived = function(resource) {
    if (resource.url == url) {
        status_code = resource.status;
    }
};

page.open(url, function (status) {
    if (status == "fail" || status_code != 200) {
        console.log("Error: " + status_code + " for url: " + url);
        phantom.exit(1);
    }
    phantom.exit(0);
});

mobile / tests.py :

import subprocess
from django.test import LiveServerTestCase

class MobileTest(LiveServerTestCase):
    def test_mobile_js(self):
        args = ["phantomjs", "mobile/test_no_js_errors.js", self.live_server_url]
        result = subprocess.check_output(args)
        self.assertEqual(result, "")  # No result means no error

Execute testes :

manage.py test mobile

Emil Stenström
fonte
Obrigado. Eu costumava subprocess.Popen para chamar o script PhantomJS e funcionou :)
insecto
Você vê como isso é limitado, certo? Tudo o que você está fazendo está fazendo uma chamada de shell para executar PhantomJS - você não está realmente usando uma interface de "bom" através do qual você pode lidar correctamente com exceções, bloqueando, etc.
kamelkev
@kamelkev: Eu vejo como isso é limitado. A vantagem é que esse método me permite usar os recursos de inicialização do Django para configurar um banco de dados de teste com o conteúdo correto para cada teste. E sim, poderia ser combinado com as outras respostas para obter o melhor dos dois mundos.
Emil Stenström
6

A resposta de @Pykler é ótima, mas o requisito do Nó está desatualizado. Os comentários nessa resposta sugerem a resposta mais simples, que eu coloquei aqui para economizar tempo de outras pessoas:

  1. Instale o PhantomJS

    Como @ Vivin-Paliath aponta, é um projeto independente, não faz parte do Node.

    Mac:

    brew install phantomjs

    Ubuntu:

    sudo apt-get install phantomjs

    etc

  2. Configure um virtualenv(se você ainda não tiver):

    virtualenv mypy  # doesn't have to be "mypy". Can be anything.
    . mypy/bin/activate

    Se sua máquina possui o Python 2 e o 3, você pode precisar executar virtualenv-3.6 mypyou algo semelhante.

  3. Instale o selênio:

    pip install selenium
  4. Experimente um teste simples, como este emprestado dos documentos :

    from selenium import webdriver
    from selenium.webdriver.common.keys import Keys
    
    driver = webdriver.PhantomJS()
    driver.get("http://www.python.org")
    assert "Python" in driver.title
    elem = driver.find_element_by_name("q")
    elem.clear()
    elem.send_keys("pycon")
    elem.send_keys(Keys.RETURN)
    assert "No results found." not in driver.page_source
    driver.close()
Andrew E
fonte
Como instalar PhantomJSno Windows? Parece não funcionar usando o pipcomando
MD. Khairul Basar
1
O Pip é um instalador de pacotes python, portanto, funciona com selênio, disponível como um pacote python. O PhantomJS não é um pacote python, portanto não funcionará com o pip. Eu fiz um google rápido para "PhantomJS install windows" e existem bons hits.
Andrew E
5

é isso que eu faço, python3.3. Eu estava processando enormes listas de sites, portanto, a falha no tempo limite era vital para que o trabalho fosse executado em toda a lista.

command = "phantomjs --ignore-ssl-errors=true "+<your js file for phantom>
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)

# make sure phantomjs has time to download/process the page
# but if we get nothing after 30 sec, just move on
try:
    output, errors = process.communicate(timeout=30)
except Exception as e:
    print("\t\tException: %s" % e)
    process.kill()

# output will be weird, decode to utf-8 to save heartache
phantom_output = ''
for out_line in output.splitlines():
    phantom_output += out_line.decode('utf-8')
tlib
fonte
Obrigado, fui capaz de alterá-lo a gosto para o meu propósito.
iChux
5

Se estiver usando o Anaconda, instale com:

conda install PhantomJS

no seu script:

from selenium import webdriver
driver=webdriver.PhantomJS()

funciona perfeitamente.

clg4
fonte
A partir de agora, canais padrão não contêm PhantomJS para linux64
Eugene Pakhomov
caramba, eu amo condda <3 que foi tão fácil. estou no osx.
O.rka
1

Caso esteja usando o Buildout , você pode automatizar facilmente os processos de instalação descritos pelo Pykler usando a receita gp.recipe.node .

[nodejs]
recipe = gp.recipe.node
version = 0.10.32
npms = phantomjs
scripts = phantomjs

Essa parte instala o node.js como binário (pelo menos no meu sistema) e depois usa o npm para instalar o PhantomJS. Finalmente, ele cria um ponto de entrada bin/phantomjs, com o qual você pode chamar o driver da web PhantomJS. (Para instalar o Selenium, você precisa especificá-lo nos requisitos do seu ovo ou na configuração do Buildout.)

driver = webdriver.PhantomJS('bin/phantomjs')
Denis Drescher
fonte
1
outra maneira de automatizar processo de instalação com buildout é só uso gp.recipe.phantomjs, que configura phantomjsecasperjs
gakhov