umgang mit multithreading - anhand eines webscrapers

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
no_clue_dude
User
Beiträge: 1
Registriert: Sonntag 8. März 2015, 14:01

hi@all,
ich bin neu hier und auch neu was python betrifft.
habe grade meinen ersten webscraper geschrieben und er läuft super.
allerdings stört es mich, dass es mit 1000+ seiten dann doch relativ lange dauert.
nach kurzer suche, wie ich die performance verbessern könnte bin ich aufs multithreading gestoßen.
also habe ich mir tutorials, youtube-videos, code beispiele, etc. angeguckt, wie das ganze umgesetz wird...
aber je mehr ich über threading/multiprocessing/threadpools/etc. gelesen habe, desto verwirrter wurde ich...

eigentlich will ich doch nur einen threadpool schreiben, der eine max. anzahl von threads enthält, welche simultan die websites downloaden.
vielleicht noch einen parser-thread, der die geladenen seiten durchparsed und die ergebnisse in einer liste speichert, welche dann ganz am ende, wenn alles geladen und geparsed wurde, in einer datei gespeichert wird.

hier mal ein ausschnitt aus meinem code, der so nicht richtig sein kann:

Code: Alles auswählen

    thread_limit #max anzahl v. threads
    all_url_q #queue mit allen zu downloadenden urls
    for n in range(thread_limit)
        thread = threading.Thread(target=getSite, args=(all_url_q.get(False),))
        thread.start()
    #
    #stuff happens
    #...
    #die getSite-funktion, die die websites runterläd und als liste zurück gibt
    #(in jedem listenelement befindet sich eine zeile):
    def getSite(gURL):
        req = urllib2.Request(gURL, headers={'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:36.0) Gecko/20100101 Firefox/36.0'})
        response = urllib2.urlopen(req)
        #remove empty lines and leading/trailing whitespaces
        sitelist = [one_line.strip() for one_line in response if one_line.strip() != '']
        response.close()
        return sitelist
single-threaded funktioniert getSite().
wie kriege ich aber nun die ergebnisse verschiedener threads (return sitelist) um sie zu parsen?
und ich bin mir relativ sicher, dass das mit dem starten der threads so auch nicht richtig sein kann...
wie gesagt will ich ja eigl. einen pool von "thread_limit" threads.
mit der for schleife würde ich aber nur "thread_limit" threads starten, die dann einmal getSite ausführen und dann idle sind, oder?!
leider habe ich aber auch keine idee was ich ändern muss, um zu überprüfen, ob einer der threads idle ist und wie ich ihm dann eine neue url zum downloaden übergeben kann...

sorry für den langen post & in 'alter' internet-manier:
hier eine potato-python: http://fc01.deviantart.net/fs11/i/2006/ ... ugebag.jpg
**hoffe die leute hier verstehen spaß^^**

Edit:
ich sollte vermutlich noch anmerken, dass ich das ganze in python 2.7.9 schreibe
BlackJack

@no_clue_dude: Bevor Du Dir einen Thread-Pool selber programmierst könntest Du fertige anschauen. Zum Beispiel `concurrent.futures`. Gehört bei Python 3 zur Standardbibliothek, es gibt aber auch für Python 2 einen Backport den man nachinstallieren kann. Da erstellst Du einen `ThreadPoolExecutor`, `submit()`\est alle Downloads, und benutzt dann die `as_completed()`-Funktion mit den ganzen `Future`-Exemplaren von `submit()` um die Ergebnisse zu verarbeiten sobald sie vorhanden sind.
Antworten