Laden eines Bildes von einer Webseite

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
starki
User
Beiträge: 8
Registriert: Freitag 17. August 2012, 19:59

Hallo Leute,

ich habe eine URL von einem Bild und will dieses Bild downloaden und lokal abspeichern. Leider tritt bei mir ein Fehler auf, bei dem ich nicht mehr weiter weiß :-(
Traceback (most recent call last):
File "/usr/lib/python3.2/urllib/request.py", line 1764, in open_local_file
stats = os.stat(localname)
OSError: [Errno 2] No such file or directory: 'None'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "wbw.py", line 105, in <module>
save_img(find_picture_url(load_url(start_url)))
File "wbw.py", line 59, in save_img
urllib.request.urlretrieve(img_url, "./my_image" + rand_name() + ".jpg")
File "/usr/lib/python3.2/urllib/request.py", line 150, in urlretrieve
return _urlopener.retrieve(url, filename, reporthook, data)
File "/usr/lib/python3.2/urllib/request.py", line 1569, in retrieve
fp = self.open(url, data)
File "/usr/lib/python3.2/urllib/request.py", line 1537, in open
return getattr(self, name)(url)
File "/usr/lib/python3.2/urllib/request.py", line 1755, in open_file
return self.open_local_file(url)
File "/usr/lib/python3.2/urllib/request.py", line 1766, in open_local_file
raise URLError(e.errno, e.strerror, e.filename)
TypeError: __init__() takes at most 3 positional arguments (4 given)
Und hier mal der Code der Funktion:

Code: Alles auswählen

	
def save_img(img_url):
	urllib.request.urlretrieve(img_url, "./my_image" + rand_name() + ".jpg")
	urllib.request.urlcleanup()
BlackJack

@starki: Lass Dir mal `img_url` ausgeben.
starki
User
Beiträge: 8
Registriert: Freitag 17. August 2012, 19:59

Danke für den Hinweis. Hab ein Return bei der Funktion vergessen, die mir das die URL des Bildes ausgibt.

Aber jetzt habe ich ein anderes Problem: Die Datei wird nicht runtergeladen. Also es gibt schon eine neue Datei, aber die ist gerade mal 23 Byte groß :-/ Und das kann nicht ganz sein.

Habt ihr ein paar Ideen?
fnorb
User
Beiträge: 7
Registriert: Sonntag 5. August 2012, 11:18

Hallo starki,

Du solltest zunächst mal die URL des Bildes in einem Browser ausprobieren, um sicherzustellen, dass das Bild tatsächlich an der entsprechenden Adresse existiert.

Dann schau dir die Rückgabewerte von retrieve(...) an. Der HTTP-Antwort-Header im zweiten Rückgabewert gibt Dir evtl. Aufschluss darüber, was schiefgegenagen ist.

Achte auch darauf, ob die Rückgabe komprimiert (bspw. GZIP) ist.

Gruß
starki
User
Beiträge: 8
Registriert: Freitag 17. August 2012, 19:59

Also die URL stimmt schon mal.

Die Ausgabe vom retrieve lautet folgendermaßen:
('my_image440326292.jpg', <http.client.HTTPMessage object at 0xb6e2490c>)
Nur kann ich jetzt damit nichts anfangen ...

Edit: OK, habs herausgefunden. Anstelle der Bilddateien kommt nur eine Nachricht und diese wird in die Bilddatei gespeichert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Und statt `urllib` und Konsorten würde ich auf requests zurückgreifen - eine angenehmere API für HTTP wirst Du kaum finden :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
fnorb
User
Beiträge: 7
Registriert: Sonntag 5. August 2012, 11:18

Hallo starki,

das zweite Rückgabeargument ist -- zumindest in Python 3 -- eine Instanz von email.message.Message.
In Python 2 heißt das Modul evtl. anders.

Wirf mal einen Blick in die Python-Doku. Da ist die Klasse recht ausführlich beschrieben.

Versuch mal:

Code: Alles auswählen

filename, message = urllib.request.urlretrieve(...)
for key, value in message.items():
    print( key, '=', value )
Und schick mal die Ausgabe.

Gruß
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

fnorb hat geschrieben:das zweite Rückgabeargument ist -- zumindest in Python 3 -- eine Instanz von email.message.Message.
Die Doku sagt folgendes: "Return a tuple (filename, headers) where filename is the local file name under which the object can be found, and headers is whatever the info() method of the object returned by urlopen() returned"

Warum sollte ein HTTP-Request eine Mail-Message-Objekt zurückliefern?
fnorb
User
Beiträge: 7
Registriert: Sonntag 5. August 2012, 11:18

Hallo /me,

Vielleicht war es in Python 2 anders, ich hab momentan nur eine Python 3-Installation zum Testen.
Dort wird eine Instanz von http.client.HTTPMessage, welche wiederum von email.message.Message erbt, zurückgegeben.
Der Code-Schnipsel könnte trotzdem funktionieren.

Gruß
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Hyperion hat geschrieben:Und statt `urllib` und Konsorten würde ich auf requests zurückgreifen - eine angenehmere API für HTTP wirst Du kaum finden :-)
requests soll ja seit neuestem auch Python 3-fähig sein *hint* *hint* *hint*.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Leonidas hat geschrieben: requests soll ja seit neuestem auch Python 3-fähig sein *hint* *hint* *hint*.
Ich mache noch mehr Werbung und drücke es mal in einer Adaption eines Subkultur-Werbeslogans aus: Das Ding ist der Burner!!! :twisted:

Ich glaube mehr können wir nicht tun... ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten