2011-10-24 10 views
23

Próbuję sprawdzić, czy pewne słowo znajduje się na stronie dla wielu witryn. Skrypt działa dobrze dla 15 witryn, a następnie zatrzymuje się.Kodek utf8 nie może dekodować bajtu 0x96 w pythonie

UnicodeDecodeError: „utf8” kodek nie potrafi dekodować bajt 0x96 w pozycji 15344: nieprawidłowy początkowy bajt

zrobiłem wyszukiwania na stackoverflow i znalazł wiele problemów na nim, ale nie mogę zrozumieć, co wydaje się poszło nie tak w moim przypadku.

Chciałbym rozwiązać problem lub jeśli wystąpił błąd, pomiń tę witrynę. Pls radzi, jak mogę to zrobić, ponieważ jestem nowy, a sam poniższy kod zajęło mi dzień pisania. Nawiasem mówiąc miejsce, które skrypt zatrzymał się było 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" 

Zgodnie komentarze Marka Zmieniłem kod do wdrożenia BeautifulSoup

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

teraz otrzymuję ten błąd

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

Próbuję ich przykład szybkiego uruchamiania z http://www.crummy.com/software/BeautifulSoup/documentation.html#Quick%20Start. Jeśli skopiuję go, to kod działa poprawnie.

WRESZCIE udało mi się. Dziękuję wszystkim za pomoc. Oto ostateczny kod.

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" 

Odpowiedz

6

Wiele stron internetowych jest nieprawidłowo zakodowanych. W przypadku parsowania kodu HTML spróbuj BeautifulSoup, ponieważ może on obsługiwać wiele typów nieprawidłowego kodu HTML, które występują w środowisku naturalnym.

Beautiful Soup is a Python HTML/XML parser designed for quick turnaround projects like screen-scraping. Three features make it powerful:

  1. Beautiful Soup won't choke if you give it bad markup. It yields a parse tree that makes approximately as much sense as your original document. This is usually good enough to collect the data you need and run away.

  2. Beautiful Soup provides a few simple methods and Pythonic idioms for navigating, searching, and modifying a parse tree: a toolkit for dissecting a document and extracting what you need. You don't have to create a custom parser for each application.

  3. Beautiful Soup automatically converts incoming documents to Unicode and outgoing documents to UTF-8. You don't have to think about encodings, unless the document doesn't specify an encoding and Beautiful Soup can't autodetect one. Then you just have to specify the original encoding.

Podkreślam moją.

+0

Raczej po prostu pomijam tę stronę mogę zrobić to jak dekodowanie ('utf8', somecodeforerrortoskip) –

+0

user976847: Istnieje wiele innych zalet w korzystaniu z BeautifulSoup. Myślę, że powinieneś spróbować. –

+0

Zajrzyj do niego dzięki –

3

obszaru 'http://www.homestead.com' nie rości sobie do was posyłam UTF-8, odpowiedź faktycznie twierdzi, że ISO-8859-1:

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

Musisz użyj poprawnego kodowania dla strony, którą faktycznie otrzymałeś, a nie tylko zgaduj losowo.

+0

Chodzi o to, że mam ogromną listę stron i to jest po prostu pierwsza wielu błędów. Jaki byłby najlepszy sposób, aby pominąć stronę, jeśli znajdę błąd dekodowania? –

+1

'charset = ISO-8859-1' to cyber-odpowiednik" czeków w poczcie ". –

22

Bajt o 15344 to 0x96. Przypuszczalnie na pozycji 15343 istnieje jedno bajtowe kodowanie znaku lub ostatni bajt kodowania wielobajtowego, co powoduje 15344 początek znaku. 0x96 jest binarne 10010110, a każdy bajt pasujący do wzorca 10XXXXXX (0x80 do 0xBF) może być tylko drugim lub kolejnym bajtem w kodowaniu UTF-8.

W związku z tym strumień nie jest UTF-8 lub jest uszkodzony.

Badanie URI Ci link do niego, znajdujemy nagłówek:

Content-Type: text/html 

ponieważ nie ma kodowania stwierdził, powinniśmy użyć domyślnego dla protokołu HTTP, który jest ISO-8859-1 (aka „Latin 1 ").

Badając zawartość możemy znaleźć linię:

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

który jest mechanizm upadku-back dla ludzi, którzy z jakiegoś powodu nie można ustawić ich nagłówki HTTP poprawnie. Tym razem wyraźnie powiedzieliśmy, że kodowanie znaków to ISO-8859-1.

Jako takie, nie ma powodu oczekiwać odczytywania go jako UTF-8 do pracy.

Dla dodatkowej zabawy chociaż, jeśli weźmiemy pod uwagę, że w ISO-8859-1 0x96 koduje U + 0096, który jest znak kontrolny „POCZĄTEK strzeżony” dowiadujemy się, że ISO-8859-1 nie jest poprawna . Wygląda na to, że ludzie tworzący stronę popełnili podobny błąd.

Wygląda na to, że w rzeczywistości korzystali oni z Windows-1252, ponieważ kodowanie 0x96 w kodzie U + 2013 (EN-DASH wygląda tak: ).

Aby przetworzyć tę konkretną stronę, którą chcesz rozszyfrować w Windows-1252.

Mówiąc ogólniej, chcesz badać nagłówki podczas wybierania kodowania znaków i chociaż w tym przypadku może być niepoprawny (a może nie, więcej niż kilka kodeków "ISO-8859-1" to w rzeczywistości Windows-1252) , będziesz poprawiać częściej. Nadal musisz mieć coś takiego, jak przechwytywać, czytając z awarią. Metoda decode przyjmuje drugi parametr o nazwie errors. Wartością domyślną jest 'strict', ale możesz także mieć 'ignore', 'replace', 'xmlcharrefreplace' (niewłaściwe), 'backslashreplace' (nie jest to właściwe) i możesz zarejestrować swój własny moduł zastępczy z codecs.register_error().

+0

Aby naprawić zawartość Windows-1252 osadzoną w utf-8, można użyć ['bs4.UnicodeDammit.detwingle()'] (http://www.crummy.com/software/BeautifulSoup/bs4/doc/#inconsistent-encodings) – jfs

+0

W głębi odpowiedź, wyjaśniając, co to jest błąd (prawie na pewno). Niestety nie można tego zrozumieć bez bycia na poziomie bajtów, do którego oczywiście wielu ludzi nie jest przygotowanych. Dziękuję za dalszą podróż :-) – Forbesmyester

Powiązane problemy