charset en-/decoding unicode python3

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
hazelnut2
User
Beiträge: 7
Registriert: Mittwoch 2. September 2015, 19:37

Hallo,

ich bin derzeit daran eine Website mit HTMLParser nach Interpreten zu filtern. Die Website hat als charset "charset=ISO-8859-1" angegeben.
Ich möchte mit Python 3 utf-8 verwenden.

Auszug aus dem Code:

Code: Alles auswählen

def ddlMusicParser():
    alben_pages = ListDDLMusic_Alben_Pages()
    request = UrlOpener ('http://ddl-music.to/downloads/kategorie/alben/order/interpret/sort/D/')
  
    for line in request:
        ddl_music_site_url_decoded = str(line.decode('iso-8859-1').encode('utf-8'))
        alben_pages.feed(ddl_music_site_url_decoded)

    return
Bei einem Interpreten erhalte ich folgende Ausgabe:

Code: Alles auswählen

data = '10СС'
print('Interpret: ' + str(repr(data)))

'10\\xc4\\x90\\xcb\\x87\\xc4\\x90\\xcb\\x87'

Wenn ich die Seite im Browser Untersuche oder den Text in einen Texteditor kopiere findet er die beiden anderen Einträge des genannten Interpreten aber eben nur diesen einen nicht.


Wie kann ich herausfinden mit welchem charset/codepage dieses eine Element decodiert wurde?
Wenn ich das weiß, dann dürfte die konvertierung in eine lesbare Zeichenkett "10CC" kein Problem mehr sein.

Ich benutze Windows 10.
Python 3.6.1
Zuletzt geändert von Anonymous am Mittwoch 30. August 2017, 20:28, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Windows 10 Pro 64bit; Python 3.6.1 (64bit); Python 3 IDLE
BlackJack

@hazelnut2: Das kann nicht in einer ISO-8859-1 kodierten Seite stehen, denn die beiden С sind kyrillische Zeichen die in dieser Kodierung nicht enthalten sind.

Code: Alles auswählen

In [13]: u'10СС'
Out[13]: u'10\u0421\u0421'

In [14]: unicodedata.name(u'\u0421')
Out[14]: 'CYRILLIC CAPITAL LETTER ES'

In [15]: u'10СС'.encode('iso-8859-1')
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
<ipython-input-15-08553dfb0e13> in <module>()
----> 1 u'10СС'.encode('iso-8859-1')

UnicodeEncodeError: 'latin-1' codec can't encode characters in position 2-3: ordinal not in range(256)
hazelnut2
User
Beiträge: 7
Registriert: Mittwoch 2. September 2015, 19:37

@BlackJack: Also laut meta info:

Code: Alles auswählen

<base href="http://ddl-music.to/" />
	
	<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
sollte die Seite prinzipiell so codiert sein, nur halt nicht dieser Eintrag.

Wird erkannt:

Code: Alles auswählen

<span class="interpret">by <b>10CC</b></span>
Und der nächste Eintrag auf der selben Seite ein paar Zeilen weiter unten wird nicht erkannt:

Code: Alles auswählen

<span class="interpret">by <b>10СС</b></span>
Danke für die Antwort :-)
Windows 10 Pro 64bit; Python 3.6.1 (64bit); Python 3 IDLE
Sirius3
User
Beiträge: 18299
Registriert: Sonntag 21. Oktober 2012, 17:20

@hazelnut2: was da in den Metadaten steht, muß nicht unbedingt richtig sein. Der ContentType im HTTP-Header ist da vielleicht richtiger. Was verwendest Du zum Herunterladen? Das requests-Modul kümmert sich um die richtige Codierung automatisch. Das De- und gleich wieder Encodieren ist auch nicht so toll. Intern sollte man immer mit Unicode arbeiten.
hazelnut2
User
Beiträge: 7
Registriert: Mittwoch 2. September 2015, 19:37

@Sirius3: Ich verwende

Code: Alles auswählen

from html.parser import HTMLParser
import urllib.request
Okay, dass man intern am besten nur mit Unicode arbeitet steht bei der Dokumentation denke ich eh ziemlich weit vorne.
Danke für den Hinweis.

Ich werde meine Lösung dann posten sobald ich sie habe :-)
Windows 10 Pro 64bit; Python 3.6.1 (64bit); Python 3 IDLE
hazelnut2
User
Beiträge: 7
Registriert: Mittwoch 2. September 2015, 19:37

'CYRILLIC CAPITAL LETTER ES' nicht das Gleiche ist wie das "C" im Deutschen. Da ich davon ausgehe, dass solche unbekannten Zeichen eher selten auftreten, werde ich diese fehlerhaften Zeichenketten bzw. diese Einträge markieren und manuell überprüfen und korrigieren.

Das heißt ich muss mir eine passende Fehlerbehandlung ausdenken:

Code: Alles auswählen

def CheckString(string):
    if '\\x' in string:
        print('<Unknown Characters>')
        return False
    else:
        return True
Danke
Windows 10 Pro 64bit; Python 3.6.1 (64bit); Python 3 IDLE
Antworten