Selenium Webdriver/Python Timeout für site.get einbauen, wenn Seite nicht lädt

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Angry Onion
User
Beiträge: 2
Registriert: Mittwoch 5. Oktober 2016, 13:32

Guten Tag,

ich beschäftige mich recht neu mit Python und bin auch hier im Forum zum ersten Mal, ich hoffe man kann mir hier helfen.
Es geht um folgendes Problem:
Mit meinem Python-Code erzeuge ich regelmäßig Screenshots von Webseiten mittels Selenium/PhantomJS.
Dazu nutze ich folgenden Code:

Code: Alles auswählen

# Download von Website mit Selenium und PhantomJS
# headless Webbrowser PhyntomJS
site = webdriver.PhantomJS()
# Website in PhantomJS oeffnen
site.get(self.url)
# Screenshot sichern
site.save_screenshot('pictures/' + self.title + '_new.png')
# Webbrowser schliessen
site.quit
Das Problem ist, das sich manche Seiten ab und an nicht öffnen lassen (oder so?).
Dann kommt das Skript bis zu dem site.get(url) und bleibt dann an der Stelle stehen (oder führt dauerhaft diesen Befehl aus).
Jedenfalls wird es dann nicht sauber beendet, sondern läuft die ganze Zeit weiter.

Kann ich in Python oder mit der Selenium-API irgendwie eine Timeout-Funktion einbauen, sodass er nach 10 Sek. abbricht, wenn die Seite bis dahin nicht geöffnet ist, bzw der Befehl bis dahin nicht fertig ausgeführt ist?

Muss das Skript dann mit strg-c beenden und dann ploppt folgende Fehlermeldung auf:

Code: Alles auswählen

^CTraceback (most recent call last):
  File "results.py", line 76, in <module>
    result = course.check()
  File "/home/peter/results/course.py", line 77, in check
    self.capture()
  File "/home/peter/results/course.py", line 37, in capture
    site.get(self.url)
  File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/remote/webdriver.py", line 248, in get
    self.execute(Command.GET, {'url': url})
  File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/remote/webdriver.py", line 234, in execute
    response = self.command_executor.execute(driver_command, params)
  File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/remote/remote_connection.py", line 401, in execute
    return self._request(command_info[0], url, body=data)
  File "/usr/local/lib/python3.4/dist-packages/selenium/webdriver/remote/remote_connection.py", line 471, in _request
    resp = opener.open(request, timeout=self._timeout)
  File "/usr/lib/python3.4/urllib/request.py", line 455, in open
    response = self._open(req, data)
  File "/usr/lib/python3.4/urllib/request.py", line 473, in _open
    '_open', req)
  File "/usr/lib/python3.4/urllib/request.py", line 433, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.4/urllib/request.py", line 1202, in http_open
    return self.do_open(http.client.HTTPConnection, req)
  File "/usr/lib/python3.4/urllib/request.py", line 1177, in do_open
    r = h.getresponse()
  File "/usr/lib/python3.4/http/client.py", line 1172, in getresponse
    response.begin()
  File "/usr/lib/python3.4/http/client.py", line 351, in begin
    version, status, reason = self._read_status()
  File "/usr/lib/python3.4/http/client.py", line 313, in _read_status
    line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
  File "/usr/lib/python3.4/socket.py", line 371, in readinto
    return self._sock.recv_into(b)
KeyboardInterrupt
Hat das irgendwas damit zu tun oder kommt diese Fehlermeldung nur wegen des Abbruches mittel Strg-c?

Vielen Dank im Voraus :)
Zuletzt geändert von Anonymous am Mittwoch 5. Oktober 2016, 15:08, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@Angry Onion: Der `KeyboardInterrupt` ist das Abbrechen mit Strg-C. Bei der Selenium-Frage kann ich leider nicht weiterhelfen.

Das ``site.quit`` am Ende hat keinen Effekt. Dazu müsste man die Methode nicht nur referenzieren, sondern auch aufrufen: ``site.quit()``.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Das Problem scheint nicht an der Website zu liegen sondern an der PhantomJS-Instanz die gestartet wird. Python macht nie einen Request zu der Website, das macht PhantomJS, was allerdings Python macht ist mit der PhantomJS-Instanz zu kommunizieren (webdriver funktioniert über http) und dort hängt es aus unerfindlichen Gründen. Generell solltest du nicht jedesmal einen neuen PhantomJS-Driver initialisiseren, das ist sehr resourcen-aufwendig, lieber einen i-wo in der Instanz merken und immer mit diesem die Website neu laden, ein weiteres Problem was ich mit PhantomJS und Selenium hatte, ist dass sich der PhantomJS Prozess manchmal nicht beendet hat und zum Zombie wurde, das könnte dein Problem sein (eine halb-tote PhantomJS-Instanz und Python versucht mit dieser zu kommunizieren), dass die quit() nicht aufrufst (siehe BlackJack) macht das Ganze nicht besser.

Da die internen Requests über die urllib gehen, kannst du in dieser einen Timeout setzen. Du solltest dir aber lieber anschauen warum die Kommunikation mit PhantomJS fehlschlägt und dort das Problem beheben.
the more they change the more they stay the same
Angry Onion
User
Beiträge: 2
Registriert: Mittwoch 5. Oktober 2016, 13:32

Vielen Dank für die schnellen Antworten. :)
BlackJack hat geschrieben: Das ``site.quit`` am Ende hat keinen Effekt. Dazu müsste man die Methode nicht nur referenzieren, sondern auch aufrufen: ``site.quit()``.
Aiiii, ja klar, danke!
Dav1d hat geschrieben:Du solltest dir aber lieber anschauen warum die Kommunikation mit PhantomJS fehlschlägt und dort das Problem beheben.
Mhhh, das würde ich gerne machen, aber ich habe keine Ahnung wie ich da ran gehen soll.
Wie gesagt, bei allen anderen Websites trat der Fehler nicht auf (die Seiten wurden alle sehr häufig geladen) und nur bei der einen Website tritt der Fehler immer wieder auf.
Wie kann ich denn der Ursache auf den Grund gehen, wenn ich doch keine Fehlermeldung oder sonst was erhalte, sondern sich immer nur das Programm aufhängt(?) ?

Hab echt kein Plan wie man da weiter vorgehen könnte.
Antworten