utf-8 vs. ascii: Codierungsproblem beim urrlib.request-Modul

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
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Ich stehe gerade auf dem Schlauch, weil ich ein kleineres Verständnisproblem bei nachfolgendem Traceback habe:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Users\...\spider.py", line 237, in <module>
    spider = Spider(url)
  File "C:\Python34\lib\site-packages\spider_bib.py", line 84, in __init__
    self.__getHTML()
  File "C:\Python34\lib\site-packages\spider_bib.py", line 281, in __getHTML
    self.__htmlseite = urllib.request.urlopen(self.url).read().decode('utf-8')
  File "C:\Python34\lib\urllib\request.py", line 153, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Python34\lib\urllib\request.py", line 455, in open
    response = self._open(req, data)
  File "C:\Python34\lib\urllib\request.py", line 473, in _open
    '_open', req)
  File "C:\Python34\lib\urllib\request.py", line 433, in _call_chain
    result = func(*args)
  File "C:\Python34\lib\urllib\request.py", line 1261, in http_open
    return self.do_open(http.client.HTTPConnection, req)
  File "C:\Python34\lib\urllib\request.py", line 1235, in do_open
    h.request(req.get_method(), req.selector, req.data, headers)
  File "C:\Python34\lib\http\client.py", line 1066, in request
    self._send_request(method, url, body, headers)
  File "C:\Python34\lib\http\client.py", line 1094, in _send_request
    self.putrequest(method, url, **skips)
  File "C:\Python34\lib\http\client.py", line 958, in putrequest
    self._output(request.encode('ascii'))
UnicodeEncodeError: 'ascii' codec can't encode character '\xf3' in position 20: ordinal not in range(128)
Das Tool ist ein älter Crawler von mir, der im Netz Webseiten analysiert und Daten bereitstellt. Im konkreten Fall scheint das Sonderzeichen in der URL und in der Seite aufzutreten, d. h. von außen kann ich da die Fehlerquelle nicht eingrenzen. Ein weiteres Problem für mich bei der Fehlersuche ist, dass die URL aus einer Liste geholt wird, die ein anderes Tool auf Basis einer Online-Quelle bereitstellt.

Ich habe die Kernfunktionen mal herausgelöst, kann dann aber das Problem nicht reproduzieren, d. h. mit einer neuen py-Quellcode-Datei tritt das Problem nicht auf.

Mich irritiert, dass ich oben utf-8 im Quelltext setze und unten etwas von ascii lesen muss. Hat jemand eine Idee, wo ich nach dem Fehler suchen muss? Ich habe jetzt mal an Codierung der URL gedacht (spielt aber beim Versuch den Fehler zu reduzieren keine Rolle), dann an die Codierung der Quelldateien (.py, utf-8) und dann an ein Problem des Moduls.

Der Code ist schon älter und ich müsste da mal eine größere Überarbeitung starten, was auch schon angedacht ist, nur momentan kann ich dem keine Priorität widmen und es ist auch keine Freude, weil das Spaghetti-Code ** 2 ist. Für mich sieht es so aus, als würde alles funktionieren und die Seite abgerufen werden; der Fehler tritt dann erst auf, wenn urllib.request eine Rückgabe an das Hauptprogramm versucht?

PS Der Umstieg auf das request-Modul ist angedacht; neuere Programme nutzen das Modul schon, nur dieses Schätzchen noch nicht.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

An dem Traceback siehst du doch ganz genau was das Problem ist. `request` ist ein String mit einem Zeichen dass sich nicht in ascii repräsentieren lässt. Ich würde empfehlen einen Debugger zu nehmen und damit zu schauen was genau `request` ist und zu schauen wo es herkommt. Entweder es gibt einen Bug in urllib oder du hast irgendwo einen Fehler gemacht und der ist bis an die Stelle durchgerutscht.
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Soweit war ich gedanklich auch schon, hatte aber nicht erfasst, dass request der Rückgabewert ist und auf einen Debugger war ich auch noch nicht gekommen (schaue ich mir direkt einmal an).

Was mich irritiert ist, dass ich den Fehler, wenn ich den Kernquelltext herauslöse, nicht reproduzieren kann. Das haut mich gerade etwas um.

Für mich ist folgende Sache unklar: Wenn ich oben doch klar sage, dass ich utf-8 wünsche, warum geht dann das Modul wieder auf ascii?

Mein Quellcode an der Stelle:

Code: Alles auswählen

urllib.request.urlopen(self.url).read().decode('utf-8')
Und dann das Modul:

Code: Alles auswählen

self._output(request.encode('ascii'))
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

pixewakb hat geschrieben:Für mich ist folgende Sache unklar: Wenn ich oben doch klar sage, dass ich utf-8 wünsche, warum geht dann das Modul wieder auf ascii?

Code: Alles auswählen

urllib.request.urlopen(self.url).read().decode('utf-8')
Dort sagst du aber nicht, dass du UTF-8 wünschst. Dort gehst du davon aus, dass du via read() bereits eine in UTF-8 kodierte Bytefolge bekommst aus der du Unicode machen möchtest.
BlackJack

@pixewakb: Was Du Dir *wünscht* ist völlig Wurst, URLs sind halt reines ASCII. Zeichen ausserhalb dieses Wertebereichs müssen als Punycode kodiert werden.
Antworten