2011-10-24 32 views
23

Estoy tratando de verificar si una determinada palabra está en una página para muchos sitios. La secuencia de comandos funciona bien para decir 15 sitios y luego se detiene.códec utf8 no puede decodificar byte 0x96 en python

UnicodeDecodeError: códec 'utf8' no puede decodificar el byte 0x96 en la posición 15344: byte de inicio no válida

Hice una búsqueda en StackOverflow y encontré muchas cuestiones en él, pero me parece que no puede entender lo salió mal en mi caso.

Me gustaría resolverlo o si hay un error, omita ese sitio. Pls consejos sobre cómo puedo hacer esto ya que soy nuevo y el código siguiente me ha tomado un día para escribir. Por cierto, el sitio que el guión se detuvo en la era 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" 

De acuerdo con los comentarios de Mark He cambiado el código para implementar BeautifulSoup

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

ahora estoy consiguiendo este error

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

Estoy intentando su ejemplo de inicio rápido desde http://www.crummy.com/software/BeautifulSoup/documentation.html#Quick%20Start. Si copio pegarlo, el código funciona bien.

FINALMENTE lo tengo para trabajar. Gracias por toda tu ayuda. Aquí está el código final.

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" 

Respuesta

6

Muchas páginas web están codificadas incorrectamente. Para analizar HTML intente BeautifulSoup ya que puede manejar muchos tipos de HTML incorrectos que se encuentran en la naturaleza.

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.

Énfasis mío.

+0

Prefiero simplemente omitir este sitio, puedo hacerlo como decodificar ('utf8', somecodeforerrortoskip) –

+0

user976847: Hay muchas otras ventajas en el uso de BeautifulSoup. Creo que deberías intentarlo. –

+0

Lo estoy viendo gracias –

3

El sitio 'http://www.homestead.com' no pretende ser enviar más UTF-8, la respuesta en realidad dice ser iso-8859-1:

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

Debe utilice la codificación correcta para la página que recibió en realidad, no solo adivine al azar.

+0

El caso es que tengo una gran lista de sitios y esta es solo la primera de muchos errores ¿Cuál sería la mejor manera de omitir un sitio si encuentro un error de decodificación? –

+1

'charset = ISO-8859-1' es el ciber-equivalente de" El cheque está en el correo ". –

22

El byte en 15344 es 0x96. Es de suponer que en la posición 15343 hay una codificación de un solo byte de un carácter, o el último byte de una codificación de múltiples bytes, lo que hace 15344 el comienzo de un carácter. 0x96 está en binario 10010110, y cualquier byte que coincida con el patrón 10XXXXXX (0x80 a 0xBF) solo puede ser un segundo byte o subsecuente en una codificación UTF-8.

Por lo tanto, la transmisión no es UTF-8 o está dañada.

El examen de la URI se vincula a, nos encontramos con el encabezado:

Content-Type: text/html 

Puesto que no se establece una codificación, que debe utilizar el valor por defecto para HTTP, que es la norma ISO-8859-1 (también conocido como "Latin 1 ").

Examinar el contenido nos encontramos con la línea:

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

que es un mecanismo de repliegue para personas que son, por alguna razón, incapaz de ajustar correctamente sus encabezamientos HTTP. Esta vez se nos dice explícitamente que la codificación de caracteres es ISO-8859-1.

Como tal, no hay ninguna razón para esperar que lo lea como UTF-8 para funcionar.

Para mayor diversión, sin embargo, si se considera que en el 0x96 ISO-8859-1 codifica U + 0096, que es el carácter de control "INICIO DEL ÁREA PROTEGIDA" nos encontramos con que ISO-8859-1 no es correcto, ya sea . Parece que las personas que crearon la página cometieron un error similar a ti mismo.

Desde el contexto, parece que realmente usaron Windows-1252, ya que en esa codificación 0x96 codifica U + 2013 (EN-DASH, se ve como ).

Por lo tanto, para analizar esta página en particular que desea decodificar en Windows-1252.

De manera más general, desea examinar los encabezados al seleccionar las codificaciones de caracteres, y si bien sería incorrecto en este caso (o tal vez no, más de unos pocos "en realidad son códecs ISO-8859-1" Windows-1252) , estarás en lo correcto más a menudo. Todavía necesita tener algo atrapar errores como este al leer con un respaldo. El método decode toma un segundo parámetro llamado errors. El valor predeterminado es 'strict', pero también puede tener 'ignore', 'replace', 'xmlcharrefreplace' (no apropiado), 'backslashreplace' (no apropiado) y puede registrar su propio controlador alternativo con codecs.register_error().

+0

Para corregir el contenido de Windows-1252 incrustado en utf-8, puede usar ['bs4.UnicodeDammit.detwingle()'] (http://www.crummy.com/software/BeautifulSoup/bs4/doc/#inconsistent-encodings) – jfs

+0

Respuesta en profundidad, explicando cuál es el error (casi seguro). Desafortunadamente, es imposible entender esto sin estar en el nivel de bytes, que por supuesto, muchas personas no están preparadas para ir. Gracias por hacer un esfuerzo adicional :-) – Forbesmyester

Cuestiones relacionadas