2016-03-29 1 views
3

Ich benutze dryscrape/webkit_server für scraping Javascript-Websites.Dryscrape/webkit_server Speicherleck

Die Speicherauslastung des Prozesses webkit_server scheint mit jedem Aufruf von session.visit() zu steigen. Es passiert mir mit dem folgenden Skript:

import dryscrape 

for url in urls: 
    session = dryscrape.Session() 
    session.set_timeout(10) 
    session.set_attribute('auto_load_images', False) 
    session.visit(url) 
    response = session.body() 

Ich bin über ca. 300 URLs und nach 70-80 URLs Webkit_Server benötigt ca. 3 GB Speicherplatz. Es ist jedoch nicht wirklich der Speicher, der das Problem für mich darstellt, aber es scheint, dass dryscrape/webkit_server mit jeder Iteration langsamer wird. Nach den genannten 70-80 Iterationen ist dryscrape so langsam, dass es einen Timeout-Fehler auslöst (set timeout = 10 sec) und ich das Python-Skript abbrechen muss. Ein Neustart des webkit_servers (z. B. nach jeweils 30 Iterationen) könnte helfen und würde den Speicher leeren, jedoch bin ich mir nicht sicher, ob die "Speicherlecks" wirklich dafür verantwortlich sind, dass das trockene Kratzen immer langsamer wird.

Kann jemand den webkit_server neu starten, damit ich das testen konnte?

Ich habe keine akzeptable Problemumgehung für dieses Problem gefunden, aber ich möchte auch nicht zu einer anderen Lösung (selen/phantomjs, ghost.py) wechseln, da ich einfach dryscrape wegen seiner Einfachheit liebe. Dryscrape funktioniert super übrigens. wenn man nicht zu viele URLs in einer Sitzung iteriert.

Dieses Problem wird auch

https://github.com/niklasb/dryscrape/issues/41

und hier

Webkit_server (called from python's dryscrape) uses more and more memory with each page visited. How do I reduce the memory used?

+0

Solange dryscrape einen Python-Code hat, könnten Sie '@ profile'-Dekoratoren werfen und [mprof] (https://pypi.python.org/pypi/memory_profiler/0.33) oder [kernprof] (https://github.com/rkern/line_profiler). Sie könnten es auf Ihrem eigenen Code ausführen, aber das wird wahrscheinlich nicht annähernd so hilfreich sein. –

+0

Danke, Wayne! – Baili

Antwort

3

Ich hatte das gleiche Problem mit Speicherlecks. Gelöst durch Zurücksetzen der Sitzung nach jeder Seitenansicht!

Vereinfachter Arbeitsablauf würde so aussehen.

Einrichten Server:

dryscrape.start_xvfb() 
sess = dryscrape.Session() 

Dann durch URL der iterieren und Reset-Sitzung nach jeder URL

for url in urls: 
    sess.set_header('user-agent', 'Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36') 
    sess.set_attribute('auto_load_images', False) 
    sess.set_timeout(30) 
    sess.visit(url) 
    response = sess.body() 
    sess.reset() 

aktualisiert

Ich habe immer noch das Problem mit Speicherverlust und besser begegnet Antwort ist die von @nico zur Verfügung gestellte.

Ich habe am Ende alle dryscrape aufgegeben und jetzt Selenium und PhantomJS verwendet. Es gibt immer noch Speicherlecks, aber sie sind überschaubar.

2

Hallo, hier diskutiert

Sorry für diese alte Post ausgrub aber was ich zu lösen tat das Problem (nach dem googeln und nur diesen Beitrag finden) war das laufen trockne in einem separaten Prozess und töte Xvfb nach jedem Lauf.

Also mein dryscrape Skript ist:

dryscrape.start_xvfb() 
session = dryscrape.Session() 
session.set_attribute('auto_load_images', False) 
session.visit(sys.argv[1]) 
print session.body().encode('utf-8') 

Und es läuft:

p = subprocess.Popen(["python", "dryscrape.py", url], 
        stdout=subprocess.PIPE) 
result = p.stdout.read() 
print "Killing all Xvfb" 
os.system("sudo killall Xvfb") 

Ich weiß, es ist nicht der beste Weg, und der Speicherverlust festgelegt werden soll, aber das funktioniert.

+1

Idealerweise sollte dryscrape etwas wie dryscape.stop_xvfb() zur Verfügung stellen, aber auch ohne es scheint Ihre Lösung in Ordnung zu sein. Ich werde es versuchen und sehen, ob es für meinen Anwendungsfall funktioniert! –

5

Das Speicherleck, das Sie haben, kann auch mit der Tatsache zusammenhängen, dass der webkit_process nie wirklich abgetötet wird (und dass Sie bei jeder Iteration eine neue dryscrape.Session erzeugen, die im Hintergrund einen webkit_server-Prozess hervorbringt, der nie kommt getötet). So wird es bei jedem Neustart immer einen neuen Prozess erzeugen. Antwort @Kenneth kann funktionieren, aber jede Lösung, die eine Befehlszeile erfordert, ist skizzenhaft. Eine bessere Lösung wäre es, die Sitzung einmal am Anfang zu erklären und den webkit_server Prozess von Python am Ende zu töten:

import webkit_server 
import dryscrape 

server = webkit_server.Server() 
server_conn = webkit_server.ServerConnection(server=server) 
driver = dryscrape.driver.webkit.Driver(connection=server_conn) 
sess = dryscrape.Session(driver=driver) 
# set session settings as needed here 

for url in urls: 
    sess.visit(url) 
    response = session.body() 
    sess.reset() 

server.kill() # the crucial line! 

Ehrlich gesagt, ist dies ein Manko in der dryscrape Bibliothek. Der Befehl kill sollte von der dryscrape-Sitzung aus zugänglich sein.

+3

sollte dies die akzeptierte Antwort sein. Danke, Mann – eusid