Existe-t-il un moyen d'utiliser PhantomJS en Python?

203

Je veux utiliser PhantomJS en Python . J'ai recherché ce problème sur Google, mais je n'ai pas trouvé de solutions appropriées.

Je trouve que c'est os.popen() peut-être un bon choix. Mais je n'ai pas pu lui transmettre quelques arguments.

L'utilisation subprocess.Popen()peut être une bonne solution pour l'instant. Je veux savoir s'il y a une meilleure solution ou non.

Existe-t-il un moyen d'utiliser PhantomJS en Python?

prospectus
la source
Ma réponse ci-dessous vous indique comment procéder. Il suffit de regarder votre question et c'est exactement ce que fait Selenium, subprocess.popenmais avec quelques fonctionnalités étendues pour rendre l'api transparente.
Pykler
@flyer: Vous devriez probablement envisager de changer la réponse acceptée, voir ci-dessous. Je vous remercie.
dotancohen

Réponses:

373

La façon la plus simple d'utiliser PhantomJS en python est via Selenium. La méthode d'installation la plus simple est

  1. Installer NodeJS
  2. En utilisant le gestionnaire de paquets de Node, installez les fantômes: npm -g install phantomjs-prebuilt
  3. installez le sélénium (dans votre virtualenv, si vous l'utilisez)

Après l'installation, vous pouvez utiliser phantom aussi simplement que:

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 votre variable d'environnement de chemin d'accès système n'est pas définie correctement, vous devrez spécifier le chemin exact comme argument pour webdriver.PhantomJS(). Remplacez ceci:

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

... avec ce qui suit:

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

Références:

Pykler
la source
40
Cela a très bien fonctionné et m'a probablement fait gagner des jours. Je vous remercie. Si l'on veut que la page restituée en entier soit source, c'est driver.page_source.
scharfmn
4
Cela fonctionne à merveille, et je suis agréablement surpris car phantomjs.org/faq.html dit "pas un module Node.js" - mais le wrapper npm à npmjs.org/package/phantomjs le fait se comporter à cette fin. Dans mon cas, je voulais faire ça: bodyStr= driver.find_element_by_tag_name("body").get_attribute("innerHTML")et ... ça a marché!
MarkHu
8
Je suis d'accord que fantôme a des dépendances folles, et je n'ai pas réussi à le faire fonctionner même après avoir installé des millions de bibliothèques liées à X11. Ghost est une histoire d'horreur.
Pykler
5
@phabtar Vous devez passer le chemin vers phantomjs comme premier argument à PhantomJS ... ou corriger votre syspath Windows pour pouvoir voir les phantomjs.
Pykler
2
Question stupide: pourquoi dois-je installer node-js? n'y a-t-il pas d'autre moyen d'obtenir des pahantomJs?
Eildosa
80

PhantomJS a récemment complètement abandonné le support Python . Cependant, PhantomJS intègre désormais Ghost Driver .

Un nouveau projet a depuis intensifié pour combler le vide: ghost.py. Vous voudrez probablement l'utiliser à la place:

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
la source
21
Même si la prise en charge est supprimée, j'ai trouvé que l'installation de npm (gestionnaire de packages de nœuds) et son utilisation pour installer les derniers phantomjs (avec prise en charge du pilote Web) et l'installation de sélénium en python ... beaucoup plus facile que d'essayer de faire fonctionner correctement PyQT ou PySide. Ce qui est bien avec fantôme, c'est qu'il est vraiment sans tête et ne nécessite aucune bibliothèque liée à l'interface utilisateur / X11 pour fonctionner.
Pykler
12
J'ai ajouté une réponse ci-dessous expliquant ma solution préférée après avoir essayé d'utiliser ghost.py et détesté ma vie
Pykler
8
Pykler "déteste ma vie" n'est pas un euphémisme. Si quelqu'un changeait la «bonne réponse» pour cette question à celle de Pykler, j'aurais économisé une journée d'efforts.
YPCrumble
2
@YPCrumble: malheureusement, seul l'OP peut le faire; modifier la réponse acceptée.
Martijn Pieters
3
Après avoir essayé un tas d'approches différentes ce matin, la solution @Pykler a fini par fonctionner le plus facilement.
andyzinsser
40

Depuis que le GhostDriver est livré avec le PhantomJS, il est devenu encore plus pratique de l'utiliser via Selenium.

J'ai essayé l'installation Node de PhantomJS, comme suggéré par Pykler, mais dans la pratique, je l'ai trouvée plus lente que l'installation autonome de PhantomJS. Je suppose que l'installation autonome n'a pas fourni ces fonctionnalités plus tôt, mais à partir de la version 1.9, elle le fait très bien.

  1. Installez PhantomJS ( http://phantomjs.org/download.html ) (Si vous êtes sous Linux, les instructions suivantes aideront https://stackoverflow.com/a/14267295/382630 )
  2. Installez Selenium à l'aide de pip.

Maintenant, vous pouvez utiliser comme ça

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

driver.quit()
Pankaj
la source
3
merci spécial d'avoir pointé la réponse SO concernant l'installation de PhantomJS sur Ubuntu, cela m'a aidé.
Dennis Golomazov
un moyen rapide d'installer Selenium que je viens d'apprendre est, sous Windows, tapez: C: \ Python34 \ Scripts \ pip.exe install Selenium.
ntk4
8

Voici comment je teste javascript en utilisant PhantomJS et 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

Exécutez les tests :

manage.py test mobile

Emil Stenström
la source
Merci. J'ai utilisé subprocess.Popen pour appeler le script phantomjs et cela a fonctionné :)
flyer
Vous voyez comment cela est limité à droite? Tout ce que vous faites est de faire un appel shell pour exécuter phantomjs - vous n'utilisez pas réellement une interface "appropriée" à travers laquelle vous pouvez gérer correctement les exceptions, le blocage, etc.
kamelkev
@kamelkev: Je vois comment cela est limité. L'avantage est que cette méthode me permet d'utiliser les fonctionnalités d'amorçage de Django pour configurer une base de données de test avec le contenu correct pour chaque test. Et oui, il pourrait être combiné avec les autres réponses pour tirer le meilleur parti des deux mondes.
Emil Stenström
6

La réponse de @Pykler est excellente, mais l'exigence de nœud est obsolète. Les commentaires dans cette réponse suggèrent la réponse plus simple, que j'ai mise ici pour gagner du temps aux autres:

  1. Installer PhantomJS

    Comme le souligne @ Vivin-Paliath, il s'agit d'un projet autonome, ne faisant pas partie de Node.

    Mac:

    brew install phantomjs

    Ubuntu:

    sudo apt-get install phantomjs

    etc

  2. Configurez un virtualenv(si vous ne l'avez pas déjà fait):

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

    Si votre machine possède à la fois Python 2 et 3, vous devrez peut-être exécuter virtualenv-3.6 mypyou similaire.

  3. Installez le sélénium:

    pip install selenium
  4. Essayez un test simple, comme celui emprunté à la documentation :

    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
la source
Comment installer PhantomJSsur Windows? Cela ne semble pas fonctionner avec la pipcommande.
MD. Khairul Basar
1
Pip est un installateur de packages python, il fonctionne donc avec le sélénium, qui est disponible en tant que package python. PhantomJS n'est pas un paquet python donc ne fonctionnera pas avec pip. J'ai fait un rapide google pour "PhantomJS install windows" et il y a de bons hits.
Andrew E
5

c'est ce que je fais, python3.3. Je traitais d'énormes listes de sites, donc l'échec du délai d'attente était vital pour que le travail traverse toute la liste.

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
la source
Merci, j'ai pu le modifier à mon goût.
iChux
5

Si vous utilisez Anaconda, installez avec:

conda install PhantomJS

dans votre script:

from selenium import webdriver
driver=webdriver.PhantomJS()

fonctionne parfaitement.

clg4
la source
Pour l'instant, les canaux par défaut ne contiennent pas PhantomJS pour linux64
Eugene Pakhomov
merde, j'aime conda <3 qui était si facile. je suis sur osx.
O.rka
1

Si vous utilisez Buildout , vous pouvez facilement automatiser les processus d'installation décrits par Pykler à l'aide de la recette gp.recipe.node .

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

Cette partie installe node.js en tant que binaire (au moins sur mon système) puis utilise npm pour installer PhantomJS. Enfin, il crée un point d'entrée bin/phantomjs, avec lequel vous pouvez appeler le pilote Web PhantomJS. (Pour installer Selenium, vous devez le spécifier dans vos exigences d'oeuf ou dans la configuration Buildout.)

driver = webdriver.PhantomJS('bin/phantomjs')
Denis Drescher
la source
1
une autre façon d'automatiser le processus d'installation avec buildout c'est juste une utilisation gp.recipe.phantomjs, qui configure phantomjsetcasperjs
gakhov