Utf8-кодек не может декодировать байт 0x96 в python
Я пытаюсь проверить, существует ли определенное слово на странице для многих сайтов. script работает нормально, скажем, 15 сайтов, а затем останавливается.
UnicodeDecodeError: кодек 'utf8' не может декодировать байт 0x96 в позиции 15344: недопустимый стартовый байт
Я сделал поиск в stackoverflow и нашел много проблем, но я не могу понять, что пошло не так в моем случае.
Я хотел бы либо решить его, либо, если есть ошибка, пропустите этот сайт. Совет Pls, как я могу это сделать, поскольку я новичок, и сам нижеприведенный код заставил меня написать день. Кстати, сайт, на котором остановился script, был 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"
В соответствии с комментариями Mark я изменил код для реализации 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"
Ответы
Ответ 1
Многие веб-страницы закодированы неправильно. Для анализа HTML попробуйте BeautifulSoup, так как он может обрабатывать множество типов неверных HTML, которые находятся в дикой природе.
Beautiful Soup - это парсер HTML/XML Python, предназначенный для быстрого оборотные проекты, такие как скрипинг экрана. Три функции делают это мощный:
-
Красивый суп не задохнется, если вы дадите ему плохую разметку. Это дает дерево разбора, которое делает примерно такое же значение, как и ваш оригинал документ. Обычно это достаточно хорошо для сбора необходимых данных и убежать.
-
Beautiful Soup предлагает несколько простых методов и Pythonic идиомы для навигации, поиска и изменения дерева синтаксического анализа: a инструментарий для анализа документа и извлечения необходимого вам. Вы не нужно создавать собственный парсер для каждого приложения.
-
Красивые Суп автоматически конвертирует входящие документы в Юникод и исходящие документы для UTF-8. Вам не нужно думать о кодировках, если только в документе не указывается кодировка, а Beautiful Soup не может автоопределить один. Тогда вам просто нужно указать исходную кодировку.
Акцент на мой.
Ответ 2
Байт в 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()
.
Ответ 3
Сайт "http://www.homestead.com" не претендует на отправку вам utf-8, на самом деле ответ считается iso-8859-1:
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
Вы должны использовать правильную кодировку для страницы, которую вы действительно получили, а не просто гадать случайным образом.