26 Stimmen

utf8-Codec kann Byte 0x96 in Python nicht dekodieren

Ich versuche zu prüfen, ob ein bestimmtes Wort auf einer Seite für viele Websites vorhanden ist. Das Skript läuft gut für etwa 15 Seiten und dann stoppt es.

UnicodeDecodeError: 'utf8' Codec kann Byte 0x96 an Position 15344 nicht dekodieren: ungültiges Startbyte

Ich habe eine Suche auf Stackoverflow durchgeführt und viele Probleme dazu gefunden, aber ich kann nicht verstehen, was in meinem Fall schief gelaufen ist.

Ich möchte entweder zu lösen oder wenn es ein Fehler ist, überspringen Sie diese Seite. Bitte geben Sie mir einen Rat, wie ich das machen kann, da ich neu bin und ich einen Tag gebraucht habe, um den folgenden Code zu schreiben. Übrigens war die Seite, auf der das Skript anhielt http://www.homestead.com

filetocheck = open("bloglistforcommenting","r")
resultfile = open("finalfile","w")

for countofsites in filetocheck.readlines():
        sitename = countofsites.strip()
        htmlfile = urllib.urlopen(sitename)
        page = htmlfile.read().decode('utf8')
        match = re.search("Enter your name", page)
        if match:
            print "match found  : " + sitename
            resultfile.write(sitename+"\n")

        else:
            print "sorry did not find the pattern " +sitename

print "Finished Operations"

Gemäß Marks Kommentaren habe ich den Code geändert, um beautifulsoup zu implementieren

htmlfile = urllib.urlopen("http://www.homestead.com")
page = BeautifulSoup((''.join(htmlfile)))
print page.prettify() 

Jetzt erhalte ich diesen Fehler

page = BeautifulSoup((''.join(htmlfile)))
TypeError: 'module' object is not callable

Ich versuche das Schnellstart-Beispiel von http://www.crummy.com/software/BeautifulSoup/documentation.html#Quick%20Start . Wenn ich ihn kopiere und einfüge, funktioniert der Code gut.

ENDLICH hat es funktioniert. Ich danke euch allen für eure Hilfe. Hier ist der endgültige Code.

import urllib
import re
from BeautifulSoup import BeautifulSoup

filetocheck = open("listfile","r")

resultfile = open("finalfile","w")
error ="for errors"

for countofsites in filetocheck.readlines():
        sitename = countofsites.strip()
        htmlfile = urllib.urlopen(sitename)
        page = BeautifulSoup((''.join(htmlfile)))  
        pagetwo =str(page) 
        match = re.search("Enter YourName", pagetwo)
        if match:
            print "match found  : " + sitename
            resultfile.write(sitename+"\n")

        else:
            print "sorry did not find the pattern " +sitename

print "Finished Operations"

30voto

Jon Hanna Punkte 106367

Das Byte an 15344 ist 0x96. Vermutlich befindet sich an Position 15343 entweder eine Ein-Byte-Kodierung eines Zeichens oder das letzte Byte einer Mehr-Byte-Kodierung, so dass 15344 der Anfang eines Zeichens ist. 0x96 ist im Binärformat 10010110, und jedes Byte, das dem Muster 10XXXXXX (0x80 bis 0xBF) entspricht, kann nur ein zweites oder nachfolgendes Byte in einer UTF-8-Kodierung sein.

Der Stream ist also entweder nicht UTF-8 oder beschädigt.

Bei der Prüfung des URI, auf den Sie verweisen, finden wir die Kopfzeile:

Content-Type: text/html

Da keine Kodierung angegeben ist, sollten wir die Standardeinstellung für HTTP verwenden, nämlich ISO-8859-1 (auch bekannt als "Latin 1").

Wenn wir den Inhalt untersuchen, finden wir die Zeile:

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

Das ist ein Ausweichmechanismus für Leute, die aus irgendeinem Grund nicht in der Lage sind, ihre HTTP-Überschriften richtig zu setzen. Diesmal wird uns ausdrücklich mitgeteilt, dass die Zeichenkodierung ISO-8859-1 ist.

Es gibt also keinen Grund zu erwarten, dass das Lesen als UTF-8 funktioniert.

Wenn man bedenkt, dass 0x96 in ISO-8859-1 für U+0096 steht, das Steuerzeichen "START OF GUARDED AREA", dann ergibt sich folgendes Bild ISO-8859-1 ist auch nicht korrekt . Es scheint, dass die Leute, die die Seite erstellt haben, einen ähnlichen Fehler wie Sie gemacht haben.

Aus dem Kontext geht hervor, dass sie tatsächlich Windows-1252 verwendet haben, da 0x96 für U+2013 kodiert (EN-DASH, sieht aus wie ).

Um diese spezielle Seite zu analysieren, müssen Sie also in Windows-1252 dekodieren.

Generell sollten Sie bei der Auswahl von Zeichenkodierungen die Kopfzeilen prüfen, und obwohl dies in diesem Fall vielleicht nicht korrekt ist (oder vielleicht auch nicht, denn nicht wenige "ISO-8859-1"-Codecs sind in Wirklichkeit Windows-1252), werden Sie häufiger richtig liegen. Sie müssen immer noch etwas haben, das solche Fehler abfängt, indem Sie mit einem Fallback lesen. Die decode Methode nimmt einen zweiten Parameter namens errors . Der Standardwert ist 'strict' aber Sie können auch 'ignore' , 'replace' , 'xmlcharrefreplace' (nicht zutreffend), 'backslashreplace' (nicht geeignet) und Sie können Ihren eigenen Fallback-Handler mit codecs.register_error() .

9voto

Mark Byers Punkte 761508

Viele Webseiten sind falsch kodiert. Zum Parsen von HTML versuchen Sie BeautifulSoup da es mit vielen Arten von fehlerhaftem HTML umgehen kann, die in der freien Natur vorkommen.

Beautiful Soup ist ein Python HTML/XML-Parser, der für schnelle Projekte wie Screen-Scraping entwickelt wurde. Drei Eigenschaften machen ihn leistungsfähig:

  1. Beautiful Soup wird nicht ersticken, wenn man ihr einen schlechten Aufschlag gibt. Es liefert einen Parse-Baum, der ungefähr so viel Sinn ergibt wie Ihr Original Dokument. Das ist normalerweise gut genug, um die benötigten Daten zu sammeln und wegzulaufen.

  2. Beautiful Soup bietet ein paar einfache Methoden und Pythonic Idiome zum Navigieren, Suchen und Ändern eines Parse-Baums: ein Toolkit, um ein Dokument zu zerlegen und das zu extrahieren, was Sie brauchen. Sie müssen nicht für jede Anwendung einen eigenen Parser erstellen.

  3. Schön Soup konvertiert eingehende Dokumente automatisch in Unicode und ausgehende Dokumente in UTF-8. Sie müssen nicht über Kodierungen nachdenken es sei denn das Dokument gibt keine Kodierung an und Beautiful Soup kann nicht automatisch erkennen kann. Dann müssen Sie einfach die ursprüngliche Kodierung angeben.

Hervorhebung von mir.

3voto

Duncan Punkte 85702

Die Website "http://www.homestead.com" behauptet nicht, Ihnen utf-8 zu senden, sondern iso-8859-1:

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

Sie müssen die korrekte Kodierung für die tatsächlich empfangene Seite verwenden und dürfen nicht nur zufällig raten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X