mehrere urlopen gleichzeitig ?

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
debian75
User
Beiträge: 90
Registriert: Dienstag 27. November 2007, 01:05

salve,

ich möchte von ca. 20 verschiedenen seiten die lieferbarkeit von produkten abfragen, indem ich die html seiten parse.

ich habe das erst in php geschrieben, geht auch, ist aber sehr langsam....dauert gut 30 sekunden, weil das halt alles sequentiell gemacht wird.

ich habe gehört mit python kann man mehrere urls gleichzeitig öffnen und parsen, nennt sich wohl multithreading. leider finde ich nirgens ein beispiel.

hat jemand ein script an dem ich mich orientieren kann ? oder geht das auch ohne multithreading ?

thnx

d
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

debian75 hat geschrieben:ich habe gehört mit python kann man mehrere urls gleichzeitig öffnen und parsen, nennt sich wohl multithreading. leider finde ich nirgens ein beispiel.
Hallo debian75!

Willkommen im Python-Forum!

Ich sag's dir gleich vorab: Threading ist für den Anfang nicht einfach. Aber vielleicht kannst du trotzdem etwas damit anfangen.

Dieses Beispiel ist aber nicht ideal, da es genau so viele Threads öffnet, wie es URLs gibt. Und es versucht alle URLs gleichzeitig zu erreichen und die Daten zurück zu bekommen. Bei 30 URLs die gleichzeitig abgefragt werden, kann das evt. Probleme bereiten. Probier es einfach mal aus.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import urllib2
import threading
import time


lock = threading.Lock()


def download(url, retvals):
    
    try:
        html = urllib2.urlopen(url).read()
    except urllib2.URLError, exception:
        html = "ERROR: %s" % str(exception)
    lock.acquire()
    retvals.append((url, html))
    lock.release()


def main():
    urls = (
        "http://gerold.bcom.at/",
        "http://halvar.at/",
        "http://lugt.at/",
        "http://microsoft.de/",
        "http://www.python-forum.de/",
        "http://python.org/",
        "http://wallerforum.com/",
        #"http://log-in.fachdid.fu-berlin.de/Archiv/2001/2/Thema/", # braucht zu lange
    )
    retvals = []
    threads = []
    for url in urls:
        threads.append(
            threading.Thread(
                target = download, kwargs = dict(url = url, retvals = retvals)
            )
        )
        threads[-1].start()
        time.sleep(0.2)
    
    # Warten bis alle fertig sind
    for thread in threads:
        thread.join()
        
    for url, html in retvals:
        print url
        if html.startswith("ERROR"):
            print "Achtung Fehler!"
        print html[:100]
        print


if __name__ == "__main__":
    main()
Und lies dir die Hilfe zu den Modulen "thread" und "threading" genau durch. Und hier im Forum findest du auch einige Beispiele zum Threma "Threading". Z.B. hier: http://www.python-forum.de/topic-3869.html

mfg
Gerold
:-)
Zuletzt geändert von gerold am Dienstag 27. November 2007, 11:31, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
debian75
User
Beiträge: 90
Registriert: Dienstag 27. November 2007, 01:05

hey, vielen dank. muss ich gleich mal ausprobieren wenn ich von der arbeit komme.
debian75
User
Beiträge: 90
Registriert: Dienstag 27. November 2007, 01:05

hallo


ich nochmal. ich habe jetzt dieses script in die datei "m.py" kopiert. leider bekomme ich einen fehler wenn ich m.py über den browser aufrufen will.

"The server encountered an internal error or misconfiguration and was unable to complete your request."

----

Code: Alles auswählen

#!/usr/bin/env python 
# -*- coding: iso-8859-15 -*- 

import os
import urllib
import urllib2
import threading
import time
print 'Content-Type: text/html\n\n'

lock = threading.Lock() 


def download(url, retvals): 
    
    try: 
        html = urllib2.urlopen(url).read() 
    except urllib2.URLError, exception: 
        html = "ERROR: %s" % str(exception) 
    lock.acquire() 
    retvals.append((url, html)) 
    lock.release() 


def main(): 
    urls = ( 
        "http://www.google.com/", 
        "http://www.gmail.com/", 
        #"http://log-in.fachdid.fu-berlin.de/Archiv/2001/2/Thema/", # braucht zu lange 
    ) 
    retvals = [] 
    threads = [] 
    for url in urls: 
        threads.append( 
            threading.Thread( 
                target = download, kwargs = dict(url = url, retvals = retvals) 
            ) 
        ) 
        threads[-1].start() 
        time.sleep(0.2) 
    
    # Warten bis alle fertig sind 
    for thread in threads: 
        thread.join() 
        
    for url, html in retvals: 
        print url 
        if html.startswith("ERROR"): 
            print "Achtung Fehler!" 
        print html[:100] 
        print 

main()
----

was mach ich falsch ?

Edit by Gerold: Code-Tags gesetzt. Beim nächsten mal bitte selber machen.
Dakre
User
Beiträge: 16
Registriert: Dienstag 13. Juni 2006, 22:40

hört sich so an als könnte es an der Konfiguration des Web Servers liegen? nutzt du Apache mit mod_python? oder hast du den python Interpreter einfach so installiert?

stimmt der Pfad #!/usr/bin/env python?
debian75
User
Beiträge: 90
Registriert: Dienstag 27. November 2007, 01:05

ne, der pfad stimmt nicht, hab das aber in meinem script richtig:

#!/usr/bin/python


ja, der hoster den ich hab benutzt mod_python mit apache
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hallo!

Du willst das also als CGI ausführen. Da kann vieles schief laufen. Zu niedere Python-Version. Falscher Pfad zu Python im Kopf. Falsches Encoding (aber nicht in diesem Fall). ...

- [wiki]CGI[/wiki]
- [wiki]Web-Skripte zum Laufen bringen[/wiki]

Vielleicht bekommst du eine bessere Fehlermeldung mit:

Code: Alles auswählen

import cgi
import cgitb; cgitb.enable()
im Kopf deines Programms.

Und dann noch dieser Hinweis: http://www.python-forum.de/faq.php#21

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
debian75
User
Beiträge: 90
Registriert: Dienstag 27. November 2007, 01:05

danke, ich les mich da mal durch. anbei mal meine ausgangslage, nicht lachen, ist erst mein zweiter tag mit python :)

das hier funktioniert so, ich will halt jetzt nur noch mehrere urls gleichzeitig losrennen lassen:

das script soll die lieferzeit von büchern verschiedener online shops prüfen:

Code: Alles auswählen

#!/usr/bin/python
#print 'Content-Type: text/html\n\n'
import os
import urllib
import urllib2
import threading
import time

print 'Content-Type: text/html\n\n'

#EAN ist sowas wie die ISBN nummer von einem buch
def geturltest(ean):
	url = 'http://www.foobar.ch/search.aspx?some=params'
	page = urllib.urlopen(url)
	pagedata = page.read()
	return pagedata

def strpos(string,search):
	pos = string.find(search)
	return pos

def test(string,pos):
	return string[pos+5:pos+12]


page = geturltest('9783280071465')
position = strpos(page,"Lieferzeit")
print test(page,position)
Zuletzt geändert von debian75 am Dienstag 27. November 2007, 15:44, insgesamt 1-mal geändert.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Jetzt wirds ärgelich: http://www.python-forum.de/faq.php#21
Du kannst mit dem "Edit"-Button deinen Beitrag editieren.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
debian75
User
Beiträge: 90
Registriert: Dienstag 27. November 2007, 01:05

gerold hat geschrieben:Jetzt wirds ärgelich: http://www.python-forum.de/faq.php#21
Du kannst mit dem "Edit"-Button deinen Beitrag editieren.
sorry, hatte ich ned gesehen
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

gerold hat geschrieben:Vielleicht bekommst du eine bessere Fehlermeldung mit:

Code: Alles auswählen

import cgi
import cgitb; cgitb.enable()
im Kopf deines Programms.
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Oftmals hilft es auch in den `error.log` des Webservers reinzuschauen denn dort werden Fehlermeldungen von CGI-Skripten deponiert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
debian75
User
Beiträge: 90
Registriert: Dienstag 27. November 2007, 01:05

uhm....neues problem.

ich benutze den code so ziemlich wie vorgeschlagen. nur, wenn ein server nicht erreichbar ist, dann blockiert er die weitere verarbeitung.

gibt es eine möglichkeite einem thread zu sagen, er solle es nur 5 sekunden versuchen und wenn er dann nicht fertig ist aufhören ?

weil sonst hängt mein programm wegen diesem einen thead.
debian75
User
Beiträge: 90
Registriert: Dienstag 27. November 2007, 01:05

aha....scheint weniger trivial zu sein :)

keiner ne idee ?
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hallo!

Das eingebaute Timeout ist, glaube ich, bei 30 Sekunden angesetzt. Mehr weiß ich jetzt auch nicht. Vielleicht hilft ein Blick in den Quellcode von urllib2.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Man muss über `settimeout()` auf das Socket-Objekt das Timeout verstellen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten