Codierung von Zeichenketten

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
ignis-draco
User
Beiträge: 15
Registriert: Freitag 25. Februar 2011, 12:33

Hi


Ich habe ein kleines Problem und weiß nicht so recht woran es liegt das es nicht geht.

Ich bin dabei ein Programm zu schreiben das die Episoden Namen und das Ausstrahlung Datum von Serienjunkies.de runterlädt und
Abspeichert.

Dabei habe ich aber Probleme mit Umlauten.
Ich Arbeite mit Python 3.2.2 auf einem Arch Linux und benutze den xterm.

So hole ich mir die Internet Seite und wandel die html umlaute um.

Code: Alles auswählen

httpSite = urllib.request.urlopen(url)
	
	content = str(httpSite.read())
	content = content.replace("Ä","Ä")
	content = content.replace("ä","ä")
	content = content.replace("Ö","Ö")
	content = content.replace("ö","ö")
	content = content.replace("Ü","Ü")
	content = content.replace("ü","ü")
	content = content.replace("ß","ß")
	content = content.replace(" "," ")

Das Funktioniert bei z.b. der Serie NCIS auch wunderbar jedoch bekomme ich bei z.b. The Unit
folgende Ausgabe.

Code: Alles auswählen

<td class="e0"><a href="/The-Unit/1x5-non-permissive-environment.html" title="Pr\xe4riefeuer - Alle Informationen zur Episode 1x05 der Serie \xabThe Unit\xbb">Pr\xe4riefeuer</a></td><td class="e0">04.04.2007</td>
Ich weiß das mir das read ein str gibt und somit dürfte es keine Probleme geben, aber ich weiß nicht wo es sonst probleme gibt.
Natürlich kann ich nicht ganz aus schlissen das bei dem print befehl noch etwas schief geht. Wobei es komisch wäre das es
bei der einen Serie geht und bei der anderen nicht.
Mittel .replace() kann ich das leider nicht lösen.

Das steht ja auch für ein ä aber bekomme ich es hin das ich dann auch ein richtige ä beim z.b. umbenennen einer Datei bekomme ?

wäre extrem nett wenn mir jemanden ein Link oder einen Begriff zum googlen geben könnte damit ich das Problem gelöst bekomme.

Gruß
Ignis-draco
BlackJack

@ignis-draco: Das `read()` wird sehr wahrscheinlich *keinen* `str` ergeben sondern `bytes`. Und wenn Du die in einen `str` umwandeln willst, dann musst Du wissen in welcher Kodierung die Bytes vorliegen.

In diesem Fall solltest Du aber sowieso einen HTML-Parser verwenden. Der wird auch die HTML-Entities für Dich dekodieren. Es gibt ja mehr als die Paar, die Du ersetzt.

Ausserdem ist nicht klar was Du da eigentlich ausgegeben hast. Bei der Ausgabe ist ja offensichtlich mehr passiert als nur das Ersetzen der HTML-Entities.
ignis-draco
User
Beiträge: 15
Registriert: Freitag 25. Februar 2011, 12:33

Hi


habe mit den html.parser etwas genauer angeschaut leider löst er mein Problem auch nicht.

Code: Alles auswählen

from html.parser import HTMLParser
import urllib.request
from html.entities import name2codepoint

class MyHTMLParser(HTMLParser):
    def handle_starttag(self, tag, attrs):
        print("Start tag:", tag)
        for attr in attrs:
            print("     attr:", attr)
    def handle_endtag(self, tag):
        print("End tag  :", tag)
    def handle_data(self, data):
        print("Data     :", data)
    def handle_comment(self, data):
        print("Comment  :", data)
    def handle_entityref(self, name):
        c = chr(name2codepoint[name])
        print("Named ent:", c)
    def handle_charref(self, name):
        if name.startswith('x'):
            c = chr(int(name[1:], 16))
        else:
            c = chr(int(name))
        print("Num ent  :", c)
    def handle_decl(self, data):
        print("Decl     :", data)

parser = MyHTMLParser(strict=False)
req = urllib.request.urlopen("http://www.serienjunkies.de/The-Unit/alle-serien-staffeln.html")
parser.feed(req.read())
Den Parser habe ich im Python doku gefunden. Leider taucht da genau das gleiche Problem auf.

Code: Alles auswählen

Data     : <td class="e0">
Data     : <a href="/The-Unit/1x5-non-permissive-environment.html" title="Pr\xe4riefeuer - Alle Informationen zur Episode 1x05 der Serie \xabThe Unit\xbb">
Data     : Pr\xe4riefeuer
Ausserdem ist nicht klar was Du da eigentlich ausgegeben hast. Bei der Ausgabe ist ja offensichtlich mehr passiert als nur das Ersetzen der HTML-Entities.
Jo ich habe das Datum der Ausstrahlung und den Namen für die Deutsche Episode und für die Englische ausgeschnitten. Aber die komsiche Kodierung tauchte ja sofort auf.

Wie gesagt wenn ich diese komische Kodierung noch weg bekomme habe ich alles soweit fertig.

Gruß
ignis-draco
BlackJack

@ignis-draco: Wenn ich Deinen Code ausprobiere passiert folgendes:

Code: Alles auswählen

$ python3.2 forum.py
Traceback (most recent call last):
  File "forum.py", line 58, in <module>
    parser.feed(req.read())
  File "/usr/lib/python3.2/html/parser.py", line 132, in feed
    self.rawdata = self.rawdata + data
TypeError: Can't convert 'bytes' object to str implicitly
Der HTML-Parser aus der Standardbibliothek kommt aber sowieso nur mit korrektem HTML klar, ist also für beliebiges HTML aus dem Internet nicht geeignet. Üblicher für solche Aufgaben sind `lxml.html` oder `BeautifulSoup`.

Du solltest auf jeden Fall mal überprüfen welchen Typ die Objekte haben, die Du da ausgibst, denn ich bekomme Deine Ausgabe nämlich weder mit `str` noch mit `bytes` hin:

Code: Alles auswählen

>>> print('Test:', 'Pr\xe4riefeuer')
Test: Präriefeuer
>>> print('Test:', b'Pr\xe4riefeuer')
Test: b'Pr\xe4riefeuer'
Die Webseite wehrt sich übrigens gegen das automatisierte Auslesen. Die `robots.txt` erlaubt es nur einigen wenigen bekannten Bots und verbietet es allen anderen. Und je nach dem wie man die Seite abfragt, bekommt man eine leere Zeichen/Bytekette zurück, oder eine sehr kurze Webseite wo nur der Text „Schade” drauf steht. Ich habe so das Gefühl die möchten nicht dass Du das tust was Du vorhast. ;-)
Antworten