Czy istnieje sposób użycia PhantomJS w Pythonie?

203

Chcę używać PhantomJS w Pythonie . Przejrzałem ten problem, ale nie mogłem znaleźć odpowiednich rozwiązań.

Uważam, że os.popen() może być dobrym wyborem. Ale nie mogłem przekazać kilku argumentów.

Korzystanie subprocess.Popen()może być na razie właściwym rozwiązaniem. Chcę wiedzieć, czy istnieje lepsze rozwiązanie, czy nie.

Czy istnieje sposób użycia PhantomJS w Pythonie?

ulotka
źródło
Moja odpowiedź poniżej mówi, jak to zrobić. Wystarczy spojrzeć na twoje pytanie i tak właśnie robi Selenium, subprocess.popenale z kilkoma rozszerzonymi funkcjami, dzięki którym interfejs API jest płynny.
Pykler,
@flyer: Prawdopodobnie powinieneś rozważyć zmianę zaakceptowanej odpowiedzi, patrz poniżej. Dziękuję Ci.
dotancohen

Odpowiedzi:

373

Najłatwiejszym sposobem użycia PhantomJS w pythonie jest użycie Selenium. Najprostsza metoda instalacji to

  1. Zainstaluj NodeJS
  2. Za pomocą menedżera pakietów Node zainstaluj phantomjs: npm -g install phantomjs-prebuilt
  3. zainstaluj selen (w virtualenv, jeśli go używasz)

Po instalacji możesz użyć fantomu tak prostego jak:

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

Jeśli zmienna środowiskowa ścieżki systemowej nie jest ustawiona poprawnie, musisz podać dokładną ścieżkę jako argument webdriver.PhantomJS(). Zamień to:

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

... z następującymi:

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

Bibliografia:

Pykler
źródło
40
To działało pięknie i prawdopodobnie uratowało mi dni. Dziękuję Ci. Jeśli ktoś chce z powrotem całą renderowaną stronę jako źródło, jest to driver.page_source.
scharfmn
4
Działa to pięknie i jestem mile zaskoczony, ponieważ phantomjs.org/faq.html mówi „nie moduł Node.js” - ale opakowanie npm na npmjs.org/package/phantomjs sprawia, że ​​zachowuje się w tym celu. W moim przypadku chciałem to zrobić: bodyStr= driver.find_element_by_tag_name("body").get_attribute("innerHTML")i ... zadziałało!
MarkHu
8
Zgadzam się, że duch ma szalone zależności i faktycznie nie udało mi się go uruchomić nawet po zainstalowaniu milionów bibliotek związanych z X11. Ghost to horror.
Pykler
5
@phabtar Musisz przekazać ścieżkę do phantomjs jako pierwszy argument do PhantomJS ... lub naprawić syspath dla systemu Windows, aby móc zobaczyć phantomjs.
Pykler
2
Głupie pytanie: dlaczego muszę instalować node-js? czy nie ma innego sposobu na zdobycie pahantomJs?
Eildosa
80

PhantomJS niedawno zrezygnował całkowicie z obsługi języka Python . Jednak PhantomJS zawiera teraz Ghost Driver .

Nowy projekt, ponieważ podszedł, aby wypełnić pustkę: ghost.py. Prawdopodobnie chcesz tego użyć:

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
źródło
21
Mimo że wsparcie zostało porzucone, odkryłem, że instalacja npm (menedżera pakietów węzłów) i użycie go do zainstalowania najnowszych phantomjs (z obsługą webdriver) i zainstalowanie selenu w pythonie ... jest łatwiejsze niż próba uzyskania PyQT lub PySide do poprawnego działania. To, co jest miłe w fantomie, jest naprawdę bezgłowe i nie wymaga do działania żadnych bibliotek związanych z UI / X11.
Pykler
12
Poniżej dodałem odpowiedź wyjaśniającą moje preferowane rozwiązanie po próbie użycia ghost.py i nienawidzeniu mojego życia
Pykler
8
„Nienawidzę mojego życia” Pyklera nie jest niedopowiedzeniem. Gdyby ktoś zmienił „poprawną odpowiedź” na to pytanie na Pyklera, zaoszczędziłbym cały dzień.
YPCrumble 29.09.2013
2
@YPCrumble: niestety, tylko OP może to zrobić; zmień przyjętą odpowiedź.
Martijn Pieters
3
Po wypróbowaniu kilku różnych metod dziś rano rozwiązanie @Pykler zakończyło się najbardziej płynnym działaniem.
andyzinsser
40

Teraz, gdy GhostDriver jest dostarczany w pakiecie z PhantomJS, korzystanie z niego za pośrednictwem Selenium stało się jeszcze wygodniejsze.

Próbowałem instalacji PhantomJS w węźle, jak sugeruje Pykler, ale w praktyce okazało się, że jest wolniejsza niż samodzielna instalacja PhantomJS. Wydaje mi się, że samodzielna instalacja nie zapewniała tych funkcji wcześniej, ale od wersji 1.9 bardzo to robi.

  1. Zainstaluj PhantomJS ( http://phantomjs.org/download.html ) (Jeśli korzystasz z Linuksa, poniższe instrukcje pomogą https://stackoverflow.com/a/14267295/382630 )
  2. Zainstaluj Selenium za pomocą pip.

Teraz możesz używać w ten sposób

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

driver.quit()
Pankaj
źródło
3
Specjalne podziękowania za wskazanie SO odpowiedzi dotyczącej instalacji PhantomJS na Ubuntu, pomogło mi.
Dennis Golomazov
szybkim sposobem instalacji Selenium, którego właśnie się nauczyłem, jest, w systemie Windows, wpisz: C: \ Python34 \ Scripts \ pip.exe zainstaluj Selenium.
ntk4
8

Oto jak testuję JavaScript w PhantomJS i 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

Uruchom testy :

manage.py test mobile

Emil Stenström
źródło
Dzięki. Użyłem podprocesu . Otwórz, aby wywołać skrypt phantomjs i zadziałało :)
ulotka
Widzisz, jak to jest ograniczone, prawda? Wszystko, co robisz, to wywoływanie powłoki w celu wykonania phantomjs - tak naprawdę nie używasz „właściwego” interfejsu, przez który możesz odpowiednio obsługiwać wyjątki, blokowanie itp.
kamelkev
@kamelkev: Widzę, jak to jest ograniczone. Plusem jest to, że ta metoda pozwala mi korzystać z funkcji ładowania Django w celu skonfigurowania testowej bazy danych z poprawną zawartością dla każdego testu. I tak, można to połączyć z innymi odpowiedziami, aby uzyskać to, co najlepsze z obu światów.
Emil Stenström
6

Odpowiedź przez @Pykler jest wielki, ale wymóg Węzeł jest nieaktualne. Komentarze w tej odpowiedzi sugerują prostszą odpowiedź, którą tu umieściłem, aby zaoszczędzić czas innym:

  1. Zainstaluj PhantomJS

    Jak wskazuje @ Vivin-Paliath, jest to samodzielny projekt, nie będący częścią Node.

    Prochowiec:

    brew install phantomjs

    Ubuntu:

    sudo apt-get install phantomjs

    itp

  2. Skonfiguruj virtualenv(jeśli jeszcze tego nie zrobiłeś):

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

    Jeśli twój komputer ma zarówno Python 2, jak i 3, może być konieczne uruchomienie virtualenv-3.6 mypylub podobne.

  3. Zainstaluj selen:

    pip install selenium
  4. Wypróbuj prosty test, taki jak ten zapożyczony z dokumentów :

    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.
źródło
Jak zainstalować PhantomJSw systemie Windows? Nie działa przy użyciu pippolecenia.
MD. Khairul Basar,
1
Pip to instalator pakietów python, więc działa z selenem, który jest dostępny jako pakiet python. PhantomJS nie jest pakietem Pythona, więc nie będzie działać z pipem. Zrobiłem szybkie google dla „Instaluj okna PhantomJS” i są dobre hity.
Andrew E
5

to właśnie robię, python3.3. Przetwarzałem ogromne listy witryn, więc przekroczenie limitu czasu było niezbędne, aby zadanie przebiegło przez całą listę.

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
źródło
Dzięki, mogłem to zmienić do smaku do moich celów.
iChux,
5

Jeśli używasz Anacondy, zainstaluj z:

conda install PhantomJS

w twoim skrypcie:

from selenium import webdriver
driver=webdriver.PhantomJS()

działa świetnie.

clg4
źródło
Na razie domyślne kanały nie zawierają PhantomJS dla linux64
Eugene Pakhomov
cholera, uwielbiam conda <3, to było takie proste. Jestem na OSX.
O.rka
1

Jeśli korzystasz z Buildout , możesz łatwo zautomatyzować procesy instalacji opisane przez Pykler przy użyciu receptury gp.recipe.node .

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

Ta część instaluje node.js jako plik binarny (przynajmniej w moim systemie), a następnie używa npm do zainstalowania PhantomJS. Wreszcie tworzy punkt wejścia bin/phantomjs, za pomocą którego można wywołać webdriver PhantomJS. (Aby zainstalować Selenium, musisz określić go w wymaganiach dotyczących jaj lub w konfiguracji Buildout).

driver = webdriver.PhantomJS('bin/phantomjs')
Denis Drescher
źródło
1
innym sposobem na zautomatyzowanie procesu instalacji za pomocą kompilacji jest po prostu użycie gp.recipe.phantomjs, która konfiguruje phantomjsicasperjs
gakhov