Seite 1 von 1

charset en-/decoding unicode python3

Verfasst: Mittwoch 30. August 2017, 18:43
von hazelnut2
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

Re: charset en-/decoding unicode python3

Verfasst: Mittwoch 30. August 2017, 20:43
von 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)

Re: charset en-/decoding unicode python3

Verfasst: Donnerstag 31. August 2017, 18:55
von hazelnut2
@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 :-)

Re: charset en-/decoding unicode python3

Verfasst: Donnerstag 31. August 2017, 19:28
von Sirius3
@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.

Re: charset en-/decoding unicode python3

Verfasst: Freitag 1. September 2017, 16:11
von hazelnut2
@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 :-)

Re: charset en-/decoding unicode python3

Verfasst: Sonntag 10. September 2017, 18:27
von hazelnut2
'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