UnicodeEncodeError: codec 'charmap' tidak dapat menyandikan karakter

206

Saya mencoba mengikis situs web, tetapi itu memberi saya kesalahan.

Saya menggunakan kode berikut:

import urllib.request
from bs4 import BeautifulSoup

get = urllib.request.urlopen("https://www.website.com/")
html = get.read()

soup = BeautifulSoup(html)

print(soup)

Dan saya mendapatkan kesalahan berikut:

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>

Apa yang bisa saya lakukan untuk memperbaikinya?

SstrykerR
sumber

Jawaban:

258

Saya mendapatkan hal yang sama UnicodeEncodeErrorketika menyimpan konten web tergores ke file. Untuk memperbaikinya saya mengganti kode ini:

with open(fname, "w") as f:
    f.write(html)

dengan ini:

import io
with io.open(fname, "w", encoding="utf-8") as f:
    f.write(html)

Menggunakan iomemberi Anda kompatibilitas dengan Python 2.

Jika Anda hanya perlu mendukung Python 3, Anda dapat menggunakan openfungsi builtin sebagai gantinya:

with open(fname, "w", encoding="utf-8") as f:
    f.write(html)
twasbrillig
sumber
6
Di mac (python 3) berfungsi sempurna dengan hanya membuka tanpa pengkodean, tetapi di windows (w10, python3) bukan pilihan. Hanya berfungsi seperti itu, dengan encoding = "utf-8" param.
xtornasol512
3
Terima kasih. Ini bekerja untuk saya, saya bekerja dengan file xml dan menulis hasil xml.toprettyxml () dalam file baru
Luis Cabrera Benito
1
Ini harus menjadi jawaban yang diterima karena pada akhirnya akan menulis string ke output, dan bukan representasi string byte.
Shirkan
Namun OP meminta untuk membaca file, bukan menulis file. Masalah ini tampaknya terkait dengan konsol.
NaturalBornCamper
188

Aku tetap dengan menambahkan .encode("utf-8")ke soup.

Itu artinya print(soup)menjadi print(soup.encode("utf-8")).

SstrykerR
sumber
3
jangan hardcode pengkodean karakter lingkungan Anda (misalnya, konsol) di dalam skrip Anda, cetak Unicode langsung sebagai gantinya
jfs
Ini hanya mencetak repr dari suatu bytesobjek, yang akan mencetak sebagai kekacauan \xurutan jika ada banyak teks yang dikodekan UTF-8. Saya sarankan menggunakan win_unicode_console, seperti yang disarankan @JFSebastian.
Eryk Sun
2
Saya menggunakan solusi di atas tetapi masih mendapatkan masalah: kelas MyStreamListener (tweepy.StreamListener): def on_status (self, status): print (str (status.encode ("utf-8"))) UnicodeEncodeError: 'charmap' codec can ' t menyandikan karakter '\ u2019' di posisi 87: peta karakter ke <undefined>
Vivek
2
Ini membuatnya mencetak b'\x02x\xc2\xa9'(objek byte) sebagai gantinya
MilkyWay90
1
print(soup.encode("utf-8"))bekerja untuk saya, tetapi sebelum itu saya juga harus menambahkanwith open("f_name", encoding="utf-8") as f: soup = BeautifulSoup(f, "html.parser")
TheWalkingData
44

Dalam Python 3.7, dan menjalankan Windows 10 ini berhasil (saya tidak yakin apakah itu akan bekerja pada platform lain dan / atau versi Python lainnya)

Mengganti baris ini:

with open('filename', 'w') as f:

Dengan ini:

with open('filename', 'w', encoding='utf-8') as f:

Alasan mengapa itu bekerja adalah karena pengkodean diubah menjadi UTF-8 saat menggunakan file, sehingga karakter dalam UTF-8 dapat dikonversi ke teks, bukannya mengembalikan kesalahan ketika bertemu dengan karakter UTF-8 yang tidak didukung oleh pengkodean saat ini.

Sabbir Ahmed
sumber
1
print (soup) return \ xd0 \ xbf \ xd0 \ xbe \ xd0 \ xb6 \ xd0 \ xb0 \ xd0 \ xbb \ xd1 \ x83 \ xd0 \ xb9 \ xd
Kopi
12

Saat menyimpan respons permintaan dapatkan, kesalahan yang sama dilemparkan ke Python 3.7 pada jendela 10. Respons yang diterima dari URL, penyandian adalah UTF-8 sehingga selalu disarankan untuk memeriksa penyandian agar hal yang sama dapat dilewatkan untuk menghindari masalah sepele seperti itu. karena benar-benar membunuh banyak waktu dalam produksi

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)

Ketika saya menambahkan encoding = "utf-8" dengan perintah terbuka itu menyimpan file dengan respons yang benar

with open ('NiftyList.txt', 'w', encoding="utf-8") as f:
    f.write(resp.text)
Abhishek Jain
sumber
10

Bahkan saya menghadapi masalah yang sama dengan pengkodean yang terjadi ketika Anda mencoba mencetaknya, membaca / menulis atau membukanya. Seperti yang disebutkan di atas, menambahkan .encoding = "utf-8" akan membantu jika Anda ingin mencetaknya.

soup.encode ("utf-8")

Jika Anda mencoba membuka data yang tergores dan mungkin menulisnya ke dalam file, kemudian buka file dengan (......, encoding = "utf-8")

dengan open (filename_csv, 'w', newline = '', encoding = "utf-8") sebagai csv_file:

Pardhu Gopalam
sumber
6

Bagi mereka masih mendapatkan kesalahan ini, menambahkan encode("utf-8")untuk soupjuga akan memperbaiki hal ini.

soup = BeautifulSoup(html_doc, 'html.parser').encode("utf-8")
print(soup)
Pseudo Sudo
sumber
2
soupbukan lagi BeautifulSoupobjek setelah Anda melakukan ini sehingga tidak dapat dimanipulasi atau dicari
NaturalBornCamper