2011-10-24 4 views
23

Я пытаюсь проверить, существует ли определенное слово на странице для многих сайтов. Скрипт работает нормально, например, на 15 сайтах, а затем останавливается.utf8 codec не может декодировать байт 0x96 в python

UnicodeDecodeError: «utf8» кодек не может декодировать байт 0x96 в позиции 15344: недопустимый начальный байт

Я сделал поиск на StackOverflow и нашел много вопросов, на нем, но я не могу понять, что пошло не так в моем случае.

Я бы хотел либо решить эту проблему, либо, если есть ошибка, пропустите этот сайт. Совет Pls, как я могу это сделать, поскольку я новичок, и сам нижеприведенный код заставил меня написать день. Кстати сайт, который сценарий остановился на был 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" 

Согласно комментариям Марки я изменил код для реализации BeautifulSoup

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

теперь я получаю эту ошибку

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

Я пытаюсь их пример быстрого запуска от http://www.crummy.com/software/BeautifulSoup/documentation.html#Quick%20Start. Если я скопирую его, то код будет работать нормально.

Я ОКОНЧАТЕЛЬНО получил его на работу. Спасибо за вашу помощь. Вот окончательный код.

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" 

ответ

6

Многие веб-страницы закодированы неправильно. Для синтаксического анализа HTML попробуйте BeautifulSoup, так как он может обрабатывать множество типов неверных HTML, которые находятся в дикой природе.

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.

Emphasis mine.

+0

Я скорее просто пропущу этот сайт, я могу сделать это как декодирование ('utf8', somecodeforerrortoskip) –

+0

user976847: Есть много других преимуществ при использовании BeautifulSoup. Я думаю, вы должны уйти. –

+0

Я смотрю на это спасибо –

3

Сайт 'http://www.homestead.com' не претендует на отправку вам UTF-8, ответ на самом деле утверждает, что изо-8859-1:

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

Вы должны используйте правильную кодировку для страницы, которую вы фактически получили, а не просто гадаете случайным образом.

+0

Вещь у меня есть огромный список сайтов, и это только первый из многих ошибок. Что было бы лучшим способом для меня просто пропустить сайт, если я найду ошибку декодирования? –

+1

'charset = ISO-8859-1' - это кибер-эквивалент« Проверка в письме ». –

22

Байт при 15344 равен 0x96. Предположительно, в позиции 15343 имеется либо однобайтная кодировка символа, либо последний байт многобайтовой кодировки, что делает 15344 началом символа. 0x96 находится в двоичном коде 10010110, и любой байт, соответствующий шаблону 10XXXXXX (от 0x80 до 0xBF), может быть только вторым или последующим байтом в кодировке UTF-8.

Следовательно, поток является либо не UTF-8, либо поврежден.

Изучение URI вы ссылки на, мы находим заголовок:

Content-Type: text/html 

Поскольку не указано без кодирования, мы должны использовать по умолчанию для HTTP, который является ISO-8859-1 (так называемый «Latin 1 «).

Изучение содержания мы находим строку:

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

который является запасным механизм для людей, которые по каким-то причинам, не в состоянии правильно установить их HTTP-заголовки. На этот раз нам явно сказано, что кодировка символов - это ISO-8859-1.

Как таковой, нет никаких оснований ожидать, что его читают как UTF-8.

Для дополнительного удовольствия, хотя, когда мы считаем, что в ISO-8859-1 0x96 кодирует U + 0096, который является управляющим символом «СТАРТ охраняемого» мы находим, что ISO-8859-1 не исправить либо , Кажется, люди, создавшие страницу, сделали для вас подобную ошибку.

Из контекста, казалось бы, они фактически использовали Windows-1252, как в этой кодировке 0x96 кодирует U + 2013 (EN-DASH, выглядит как ).

Итак, чтобы проанализировать эту страницу, которую вы хотите декодировать в Windows-1252.

В общем случае вы хотите изучить заголовки при выборе кодировок символов, и хотя это может быть неверно в этом случае (или, возможно, нет, более чем несколько «кодеков ISO-8859-1» на самом деле являются Windows-1252) , вы будете правы чаще. Вам все равно нужно что-то уловить, как это, читая резервную копию. Метод decode принимает второй параметр, называемый errors. По умолчанию 'strict', но вы также можете получить 'ignore', 'replace', 'xmlcharrefreplace' (не подходит), 'backslashreplace' (не подходит), и вы можете зарегистрировать свой собственный резервный обработчик с codecs.register_error().

+0

Чтобы исправить содержимое Windows-1252, встроенное в utf-8, вы можете использовать ['bs4.UnicodeDammit.detwingle()'] (http://www.crummy.com/software/BeautifulSoup/bs4/doc/#inconsistent-encodings) – jfs

+0

В глубине ответа, объясняя, что такое ошибка (почти наверняка). К сожалению, невозможно понять этот материал, не будучи на уровне байтов, что, конечно, многие люди не готовы к этому. Спасибо, что выбрали лишнюю милю :-) – Forbesmyester

Смежные вопросы