2015-04-05 20 views
18

Der Versuch, eine Website zu scrappen, ohne eine aktuelle Browser-Instanz in einem Python-Skript (mit Selenium) starten zu müssen. Ich kann dies mit Chrome oder Firefox tun - ich habe es ausprobiert und es funktioniert - aber ich möchte PhantomJS verwenden, so dass es kopflos ist.PhantomJS gibt leere Webseite zurück (Python, Selenium)

Der Code sieht wie folgt aus:

import sys 
import traceback 
import time 

from selenium import webdriver 
from selenium.webdriver.common.keys import Keys 
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities 

dcap = dict(DesiredCapabilities.PHANTOMJS) 
dcap["phantomjs.page.settings.userAgent"] = (
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/53 " 
    "(KHTML, like Gecko) Chrome/15.0.87" 
) 

try: 
    # Choose our browser 
    browser = webdriver.PhantomJS(desired_capabilities=dcap) 
    #browser = webdriver.PhantomJS() 
    #browser = webdriver.Firefox() 
    #browser = webdriver.Chrome(executable_path="/usr/local/bin/chromedriver") 

    # Go to the login page 
    browser.get("https://www.whatever.com") 

    # For debug, see what we got back 
    html_source = browser.page_source 
    with open('out.html', 'w') as f: 
     f.write(html_source) 

    # PROCESS THE PAGE (code removed) 

except Exception, e: 
    browser.save_screenshot('screenshot.png') 
    traceback.print_exc(file=sys.stdout) 

finally: 
    browser.close() 

Der Ausgang ist nur:

<html><head></head><body></body></html> 

Aber wenn ich die Chrome oder Firefox-Optionen verwenden, es funktioniert gut. Ich dachte, vielleicht würde die Website Junk auf der Grundlage des User-Agent zurückgeben, also habe ich versucht, das zu fälschen. Kein Unterschied.

Was fehlt mir?

AKTUALISIERT: Ich werde versuchen, das untenstehende Snippet mit aktualisiert zu halten, bis es funktioniert. Was ist unten, was ich gerade versuche?

import sys 
import traceback 
import time 
import re 

from selenium import webdriver 
from selenium.webdriver.support.wait import WebDriverWait 
from selenium.webdriver.common.by import By 
from selenium.webdriver.common.keys import Keys 
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities 
from selenium.webdriver.support import expected_conditions as EC 

dcap = dict(DesiredCapabilities.PHANTOMJS) 
dcap["phantomjs.page.settings.userAgent"] = (
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/53 (KHTML, like Gecko) Chrome/15.0.87") 

try: 
    # Set up our browser 
    browser = webdriver.PhantomJS(desired_capabilities=dcap, service_args=['--ignore-ssl-errors=true']) 
    #browser = webdriver.Chrome(executable_path="/usr/local/bin/chromedriver") 

    # Go to the login page 
    print "getting web page..." 
    browser.get("https://www.website.com") 

    # Need to wait for the page to load 
    timeout = 10 
    print "waiting %s seconds..." % timeout 
    wait = WebDriverWait(browser, timeout) 
    element = wait.until(EC.element_to_be_clickable((By.ID,'the_id'))) 
    print "done waiting. Response:" 

    # Rest of code snipped. Fails as "wait" above. 

Antwort

3

Sie müssen Warten auf die Seite d Loa. Normalerweise wird dies unter Verwendung eines Explicit Wait bis Warten auf ein Schlüsselelement durchgeführt, das auf einer Seite vorhanden oder sichtbar ist. Zum Beispiel:

from selenium.webdriver.support.wait import WebDriverWait 
from selenium.webdriver.common.by import By 
from selenium.webdriver.support import expected_conditions as EC 


# ... 
browser.get("https://www.whatever.com") 

wait = WebDriverWait(driver, 10) 
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.content"))) 

html_source = browser.page_source 
# ... 

Hier werden wir bis zu 10 Sekunden für ein div Element mit class="content" warten, um sichtbar zu werden, bevor Sie die Seite Quelle zu bekommen.


Zusätzlich können Sie müssen SSL-Fehler ignorieren:

browser = webdriver.PhantomJS(desired_capabilities=dcap, service_args=['--ignore-ssl-errors=true']) 

Obwohl, ich bin ziemlich sicher, dies auf die Ablenkeinfragen in PhantomJS zusammenhängt. Es ist ein offenes Ticket in phantomjs Bugtracker:

+0

Okay, ich werde das versuchen .... aber wie nützlich ist der Befehl "Get", wenn es nicht wartet, bis "Seite geladen" abgeschlossen ist, bevor es zurückkehrt ?? Scheint so, als müsste das eingebaut sein. Gibt es einen nicht zeitgesteuerten Wartebefehl, den du benutzen kannst, der auf das "page loaded" -Ereignis wartet (oder wie es heißt)? – cbp2

+0

@ cbp2 nein, Selen würde nicht auf ausstehende asynchrone Anforderungen oder asynchrone Codeausführung im Browser warten. Die Verwendung einer expliziten Wartezeit sollte das Problem lösen. – alecxe

+0

Wir nähern uns, aber immer noch keine Zigarre.Ich fügte die Wartezeit hinzu, wartete aber darauf, dass eine ID vorhanden war - Zeitüberschreitung, obwohl ich weiß, dass die ID dort sein sollte. Code-Ausgabe und Screenshot sind noch leer. 'Traceback (jüngste Aufforderung zuletzt): File "scrape_CS.py", Zeile 35, in Element = wait.until (EC.element_to_be_clickable ((By.ID, 'loginField'))) Datei„/ Benutzer/carey/anaconda/lib/python2.7/site-packages/selen/webdriver/support/wait.py ", Zeile 75, bis TimeoutException auslösen (Nachricht, Bildschirm, Stacktrace) TimeoutException: Nachricht: Screenshot: über den Bildschirm verfügbar – cbp2

25

ich das gleiche Problem und keine Menge an Code mit Blick auf den Fahrer warten machen half.
Das Problem ist die SSL-Verschlüsselung auf den https-Websites, deren Ignorieren wird den Trick tun.

Rufen Sie den PhantomJS Treiber als:

driver = webdriver.PhantomJS(service_args=['--ignore-ssl-errors=true', '--ssl-protocol=TLSv1']) 

Dies das Problem für mich gelöst.

+0

Dies funktionierte für mich, wobei der Unterschied von der anderen Antwort der '' --ssl-protocol = TLSv1'' Teil war. Weißt du, warum das so funktioniert hat? – rwolst

+1

Ich bin heute auch auf diese Ausgabe gestoßen. Meine Seiten funktioniert nicht und Das ssl-Protokoll zurückkehr = TLSv1 es gelöst. Toller Fund. –

+1

@ meoww- Hahaha, froh, dass es funktioniert hat! –

Verwandte Themen