UnicodeEncodeError: кодек 'charmap' не может кодировать символы
Я пытаюсь почистить сайт, но он выдает ошибку.
Я использую следующий код:
import urllib.request
from bs4 import BeautifulSoup
get = urllib.request.urlopen("https://www.website.com/")
html = get.read()
soup = BeautifulSoup(html)
print(soup)
И я получаю следующую ошибку:
File "C:\Python34\lib\encodings\cp1252.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode characters in position 70924-70950: character maps to <undefined>
Что я могу сделать, чтобы это исправить?
12 ответов
Я исправил это, добавив .encode("utf-8")
в soup
,
Это означает, что print(soup)
становится print(soup.encode("utf-8"))
,
Я получал то же самое UnicodeEncodeError
при сохранении очищенного веб-содержимого в файл. Чтобы исправить это, я заменил этот код:
with open(fname, "w") as f:
f.write(html)
с этим:
import io
with io.open(fname, "w", encoding="utf-8") as f:
f.write(html)
С помощью io
обеспечивает обратную совместимость с Python 2.
Если вам нужно только поддерживать Python 3, вы можете использовать встроенный open
функция вместо:
with open(fname, "w", encoding="utf-8") as f:
f.write(html)
В Python 3.7 и под управлением Windows 10 это работало (я не уверен, будет ли оно работать на других платформах и / или в других версиях Python)
Замена этой строки:
with open('filename', 'w') as f:
С этим:
with open('filename', 'w', encoding='utf-8') as f:
Причина, по которой он работает, заключается в том, что при использовании файла кодировка изменяется на UTF-8, поэтому символы в UTF-8 могут быть преобразованы в текст, вместо того, чтобы возвращать ошибку, когда он встречает символ UTF-8, который является не поддерживается текущей кодировкой.
set PYTHONIOENCODING=utf-8
set PYTHONLEGACYWINDOWSSTDIO=utf-8
Вам может потребоваться или не потребоваться установить эту вторую переменную среды PYTHONLEGACYWINDOWSSTDIO
.
В качестве альтернативы это можно сделать в коде (хотя кажется, что рекомендуется делать это через env vars):
sys.stdin.reconfigure(encoding='utf-8')
sys.stdout.reconfigure(encoding='utf-8')
Дополнительно: воспроизведение этой ошибки было немного затруднительным, поэтому оставьте и ее здесь на случай, если вам нужно воспроизвести ее на своем компьютере:
set PYTHONIOENCODING=windows-1252
set PYTHONLEGACYWINDOWSSTDIO=windows-1252
При сохранении ответа на запрос get та же ошибка была выдана на Python 3.7 в окне 10. Ответ, полученный от URL, кодировка была UTF-8, поэтому всегда рекомендуется проверять кодировку, чтобы ее можно было пропустить, чтобы избежать такой тривиальной проблемы. как это действительно убивает много времени в производстве
import requests
resp = requests.get('https://en.wikipedia.org/wiki/NIFTY_50')
print(resp.encoding)
with open ('NiftyList.txt', 'w') as f:
f.write(resp.text)
Когда я добавил кодировку ="utf-8" командой open, он сохранил файл с правильным ответом
with open ('NiftyList.txt', 'w', encoding="utf-8") as f:
f.write(resp.text)
Даже я столкнулся с той же проблемой с кодировкой, которая возникает, когда вы пытаетесь распечатать, прочитать / написать или открыть ее. Как уже упоминалось выше, добавление.encoding="utf-8" поможет, если вы пытаетесь его распечатать.
soup.encode ("UTF-8")
Если вы пытаетесь открыть очищенные данные и, возможно, записать их в файл, откройте файл с помощью (......,encoding="utf-8")
с открытым (filename_csv, 'w', newline='',encoding="utf-8") как csv_file:
Для тех, кто все еще получает эту ошибку, добавив encode("utf-8")
в soup
также исправит это.
soup = BeautifulSoup(html_doc, 'html.parser').encode("utf-8")
print(soup)
У этой проблемы есть несколько аспектов. Фундаментальный вопрос заключается в том, какой набор символов вы хотите вывести. Возможно, вам также придется выяснить набор входных символов.
Печать (либо либоwrite
) в файл с явнымencoding="..."
переведет внутреннее представление Unicode Python в эту кодировку. Если вывод содержит символы, которые не поддерживаются этой кодировкой, вы получитеUnicodeEncodeError
. Например, вы не можете написать русский или китайский, или индийский, или иврит, или арабский, или эмодзи, или... что угодно, кроме ограниченного набора из примерно 200+ западных символов в файл, кодировка которого"cp1252"
потому что этот ограниченный 8-битный набор символов не может представлять эти символы.
В основном та же проблема возникает с любым 8-битным набором символов, включая почти все устаревшие кодовые страницы Windows (437, 850, 1250, 1251 и т. д. и т. д.), хотя некоторые из них поддерживают некоторые дополнительные сценарии в дополнение к английскому языку или вместо него. (например, 1251 поддерживает кириллицу, поэтому вы можете писать на русском, украинском, сербском, болгарском и т. д.). 8-битная кодировка имеет максимум 256 кодов символов и не может представить символ, который не входит в их число.
Возможно, сейчас самое время прочитать книгу Джоэла Спольски « Абсолютный минимум, который каждый разработчик программного обеспечения обязательно должен знать о Unicode и наборах символов (без оправданий!)
На платформах, где терминал не может печатать Unicode (на самом деле только Windows в наши дни, хотя, если вы увлекаетесь ретрокомпьютерами, эта проблема также была распространена на других платформах в предыдущем тысячелетии), попыткаprint
Строки Unicode также могут вызывать эту ошибку или выводить mojibake. Если вы видите что-то вроде вместо , это ваша проблема.
Короче говоря, вам нужно знать:
Каков набор символов страницы, которую вы очистили, или данных, которые вы получили? Правильно ли он был соскоблен? Правильно ли автор определил его кодировку, или вы можете получить эту информацию (или угадать) иным образом? Некоторые веб-сайты неправильно объявляют набор символов, отличный от того, который содержит страница на самом деле, некоторые сайты неправильно настроили соединение между веб-сервером и внутренней базой данных. См., например, очистку с правильной кодировкой символов (запросы Python + BeautifulSoup) для более подробного примера с некоторыми решениями.
Какой набор символов вы хотите написать? Если вы печатаете на экран, правильно ли настроен ваш терминал и точно ли настроен ваш интерпретатор Python? Возможно, см. также Как отобразить utf-8 в консоли Windows.
Если вы здесь, возможно , ответ на один из этих вопросов не «UTF-8». Эта кодировка становится все более распространенной и для веб-страниц, хотя прежним стандартом был ISO-8859-1 (он же Latin-1), а совсем недавно — кодовая страница Windows 1252.
В дальнейшем вы в основном хотите, чтобы все ваши текстовые данные были в Unicode, за исключением нескольких дополнительных вариантов использования. Как правило, это означает UTF-8, хотя в Windows (или если вам нужна совместимость с Java) UTF-16 также неопределенно жизнеспособна, хотя и несколько громоздка. (Существует несколько других форматов сериализации Unicode, которые могут быть полезны в особых случаях. UTF-32 технически тривиален, но занимает гораздо больше памяти; UTF-7 используется в нескольких сетевых протоколах, где для транспорт.) См. также https://utf8everywhere.org/
Естественно, если вы печатаете в файл, вам также необходимо проверить этот файл с помощью инструмента, который может правильно его отобразить. Распространенной ошибкой пилота является открытие файла с помощью инструмента, который отображает только текущую выбранную системную кодировку, или инструмент, который пытается угадать кодировку, но ошибается. Опять же, общий симптом при просмотре текста UTF-8 с использованием кодовой страницы Windows 1252 может привести, например, к отображению какHéllö
.
Если кодировка символьных данных неизвестна, нет простого способа ее автоматически установить. Если вы знаете, что должен представлять текст, вы, возможно, сможете сделать вывод, но обычно это ручной процесс с некоторыми догадками. (Автоматические инструменты, такие какchardet
иftfy
может помочь, но они тоже иногда ошибаются.)
Чтобы определить, какую кодировку вы ищете, может быть полезно определить отдельные байты в символе, который отображается неправильно. Например, если вы смотрите наH\x8ell\x9a
но ожидайте, что он будет представлятьHéllö
, вы можете посмотреть байты в таблице перевода. Я опубликовал одну такую таблицу на https://tripleee.github.io/8bit , где вы можете видеть, что в этом примере это, вероятно, один из устаревших 8-битных наборов символов Mac; с большим количеством точек данных, возможно, вы сможете сузить его до одной из них (а если нет, то любая из них подойдет на практике, поскольку все кодовые точки, которые вам нужны, сопоставляются с одними и теми же символами Unicode).
Python 3 на большинстве платформ по умолчанию использует UTF-8 для всех входных и выходных данных, но в Windows это обычно не так. Вместо этого по умолчанию будет использоваться системная кодировка по умолчанию (в некоторой документации Microsoft она все еще ошибочно называется «кодовой страницей ANSI»), которая зависит от ряда факторов. В западных системах стандартной кодировкой по умолчанию обычно является кодовая страница Windows 1252.(Более ранние версии Python имели несколько иные ожидания, а в Python 2 внутреннее строковое представление не было Unicode.)
Если вы находитесь в Windows и пишете UTF-8 в текстовый файл, возможно, укажитеencoding="utf-8-sig"
который добавляет последовательность BOM в начало файла. Строго говоря, это не обязательно или правильно, но некоторым инструментам Windows это нужно для правильного определения кодировки.
Некоторые из предыдущих ответов здесь предлагают слепо применять некоторую кодировку, но, надеюсь, это должно помочь вам понять, почему это не совсем правильный подход, и как выяснить, а не угадывать, какую кодировку использовать.
Начиная с Python 3.7, установите переменную средыPYTHONUTF8
до 1
Следующий сценарий также включает другие полезные переменные, которые устанавливают системные переменные среды.
setx /m PYTHONUTF8 1
setx PATHEXT "%PATHEXT%;.PY" ; In CMD, Python file can be executed without extesnion.
setx /m PY_PYTHON 3.10 ; To set default python version for py
Я получил ту же ошибку, поэтому я использую (encoding="utf-8"), и это решает ошибку. Обычно это происходит, когда мы получили какой-то неопознанный символ или шаблон в текстовых данных, которые наш кодировщик не понимает.
with open("text.txt", "w", encoding='utf-8') as f:
f.write(data)
Это решит вашу проблему.
Если вы используете Windows, попробуйте передать кодировку ='latin1', кодировку ='iso-8859-1' или кодировку ='cp1252', например:
csv_data = pd.read_csv(csvpath,encoding='iso-8859-1')
print(print(soup.encode('iso-8859-1')))
Эта ошибка также появляется, если мы пытаемся открыть файл Excel без специальной функции, которая обрабатывает такие файлы.
В следующем примере сначала создается файл Excel с именемfile.xlsx
(который был создан в предыдущей строке кода в качестве образца данных) пытается открыться с помощью встроенногоopen()
функция, которая выдает ошибку в заголовке. Во-вторых, ошибка не отображается, и файл читается, если мы используем специальный обработчик Excel, такой как pandas.read_excel()
.
import pandas as pd
# sample data
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'c']})
df.to_excel('file.xlsx') # save to an Excel file
with open('file.xlsx') as f:
f.read() # <---- UnicodeDecodeError: 'charmap' codec can't decode
df = pd.read_excel('file.xlsx') # <---- OK