¿Hay alguna manera de usar PhantomJS en Python?

203

Quiero usar PhantomJS en Python . Busqué en Google este problema pero no pude encontrar las soluciones adecuadas.

Creo que os.popen() puede ser una buena opción. Pero no pude pasarle algunos argumentos.

Usar subprocess.Popen()puede ser una solución adecuada por ahora. Quiero saber si hay una mejor solución o no.

¿Hay alguna manera de usar PhantomJS en Python?

volantes
fuente
Mi respuesta a continuación te dice cómo hacerlo. Simplemente mirando su pregunta y en realidad eso es exactamente lo que hace Selenium, subprocess.popenpero con algunas características extendidas para que la API sea perfecta.
Pykler
@flyer: Probablemente deberías considerar cambiar la respuesta aceptada, ver más abajo. Gracias.
dotancohen

Respuestas:

373

La forma más fácil de usar PhantomJS en Python es a través de Selenium. El método de instalación más simple es

  1. Instalar NodeJS
  2. Usando el administrador de paquetes de Node, instale phantomjs: npm -g install phantomjs-prebuilt
  3. instale selenium (en su virtualenv, si lo está usando)

Después de la instalación, puede usar fantasma tan simple como:

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()

Si la variable de entorno de la ruta del sistema no está configurada correctamente, deberá especificar la ruta exacta como argumento webdriver.PhantomJS(). Reemplace esto:

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

... con lo siguiente:

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

Referencias

Pykler
fuente
40
Esto funcionó maravillosamente y probablemente me salvó días. Gracias. Si uno quiere que toda la página renderizada vuelva como fuente, es driver.page_source.
scharfmn
44
Esto funciona maravillosamente, y estoy gratamente sorprendido porque phantomjs.org/faq.html dice "no es un módulo Node.js", pero el envoltorio npm en npmjs.org/package/phantomjs hace que se comporte para este propósito. En mi caso, quería hacer esto: bodyStr= driver.find_element_by_tag_name("body").get_attribute("innerHTML")y ... ¡funcionó!
MarkHu
8
Estoy de acuerdo en que Ghost tiene dependencias locas, y en realidad no pude ponerlo en funcionamiento incluso después de instalar millones de bibliotecas relacionadas con X11. Fantasma es una historia de terror.
Pykler
55
@phabtar Debes pasar el camino a phantomjs como primer argumento para PhantomJS ... o arreglar tu syspath de Windows para poder ver phantomjs.
Pykler
2
Pregunta tonta: ¿por qué tengo que instalar node-js? ¿No hay otra forma de obtener fantasmas?
Eildosa
80

PhantomJS recientemente abandonó el soporte de Python por completo. Sin embargo, PhantomJS ahora incorpora Ghost Driver .

Ya que un nuevo proyecto ha intensificado para llenar el vacío: ghost.py. Probablemente quieras usar eso en su lugar:

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
fuente
21
Aunque se eliminó el soporte, descubrí que instalar npm (administrador de paquetes de nodos) y usarlo para instalar los últimos phantomjs (con soporte para webdriver) e instalar selenio en python ... mucho más fácil que intentar que PyQT o PySide funcionen correctamente. Lo bueno de phantom es que realmente no tiene cabeza y no requiere libs relacionadas con UI / X11 para funcionar.
Pykler
12
Agregué una respuesta a continuación explicando mi solución preferida después de intentar usar ghost.py y odiar mi vida
Pykler
8
"Odiar mi vida" de Pykler no es un eufemismo. Si alguien cambiara la "respuesta correcta" para esta pregunta a Pykler, habría ahorrado un día de esfuerzo.
YPCrumble
2
@YPCrumble: desafortunadamente, solo el OP puede hacer eso; cambiar la respuesta aceptada
Martijn Pieters
3
Después de probar varios enfoques diferentes esta mañana, la solución @Pykler terminó funcionando de la mejor manera.
andyzinsser
40

Ahora que el GhostDriver viene incluido con el PhantomJS, se ha vuelto aún más conveniente usarlo a través de Selenium.

Probé la instalación del Nodo de PhantomJS, como lo sugirió Pykler, pero en la práctica me pareció más lento que la instalación independiente de PhantomJS. Supongo que la instalación independiente no proporcionó estas características antes, pero a partir de v1.9, lo hace mucho.

  1. Instale PhantomJS ( http://phantomjs.org/download.html ) (Si está en Linux, seguir las instrucciones lo ayudará a https://stackoverflow.com/a/14267295/382630 )
  2. Instale Selenium usando pip.

Ahora puedes usar así

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

driver.quit()
Pankaj
fuente
3
Un agradecimiento especial por señalar la respuesta SO con respecto a la instalación de PhantomJS en Ubuntu, me ayudó.
Dennis Golomazov
una forma rápida de instalar Selenium que acabo de aprender es, en Windows, escriba: C: \ Python34 \ Scripts \ pip.exe install Selenium.
ntk4
8

Así es como pruebo javascript usando PhantomJS y 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

Ejecutar pruebas :

manage.py test mobile

Emil Stenström
fuente
Gracias. Utilicé subprocess.Popen para llamar al script phantomjs y funcionó :)
folleto
Ya ves cómo esto es limitado ¿verdad? Todo lo que está haciendo es hacer una llamada shell para ejecutar PhantomJS - no se está utilizando realmente una interfaz de "adecuada" a través del cual es posible manejar apropiadamente excepciones, bloqueo, etc.
kamelkev
@kamelkev: veo cómo esto es limitado. Lo bueno es que este método me permite usar las funciones de arranque de Django para configurar una base de datos de prueba con el contenido correcto para cada prueba. Y sí, podría combinarse con las otras respuestas para obtener lo mejor de ambos mundos.
Emil Stenström
6

La respuesta de @Pykler es excelente, pero el requisito de Node está desactualizado. Los comentarios en esa respuesta sugieren la respuesta más simple, que he puesto aquí para ahorrar tiempo a otros:

  1. Instalar PhantomJS

    Como señala @ Vivin-Paliath, es un proyecto independiente, no parte de Node.

    Mac:

    brew install phantomjs

    Ubuntu:

    sudo apt-get install phantomjs

    etc.

  2. Configure un virtualenv(si aún no lo ha hecho):

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

    Si su máquina tiene Python 2 y 3, es posible que necesite ejecutar virtualenv-3.6 mypyo similar.

  3. Instalar selenio:

    pip install selenium
  4. Pruebe una prueba simple, como esta prestada de los 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
fuente
¿Cómo instalar PhantomJSen Windows? No parece funcionar usando el pipcomando.
MD. Khairul Basar
1
Pip es un instalador de paquetes de Python, por lo que funciona con selenio, que está disponible como paquete de Python. PhantomJS no es un paquete de Python, por lo que no funcionará con pip. Hice un google rápido para "instalar ventanas de PhantomJS" y hay buenos resultados.
Andrew E
5

esto es lo que hago, python3.3. Estaba procesando grandes listas de sitios, por lo que el incumplimiento del tiempo de espera era vital para que el trabajo se ejecutara en toda la 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
fuente
Gracias, pude alterarlo al gusto para mi propósito.
iChux
5

Si usa Anaconda, instálelo con:

conda install PhantomJS

en tu guión:

from selenium import webdriver
driver=webdriver.PhantomJS()

funciona perfectamente.

clg4
fuente
A partir de ahora, los canales predeterminados no contienen PhantomJS para linux64
Eugene Pakhomov
maldición, me encanta conda <3 que fue tan fácil. Estoy en OSX.
O.rka
1

En caso de que esté utilizando Buildout , puede automatizar fácilmente los procesos de instalación que Pykler describe utilizando la receta gp.recipe.node .

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

Esa parte instala node.js como binario (al menos en mi sistema) y luego usa npm para instalar PhantomJS. Finalmente crea un punto de entrada bin/phantomjs, con el que puede llamar al controlador web PhantomJS. (Para instalar Selenium, debe especificarlo en sus requisitos de huevo o en la configuración de Buildout).

driver = webdriver.PhantomJS('bin/phantomjs')
Denis Drescher
fuente
1
Otra forma de automatizar el proceso de instalación con la compilación es solo el uso gp.recipe.phantomjs, que configura phantomjsycasperjs
gakhov