UnicodeEncodeError: Kodek „charmap” nie może kodować znaków

205

Próbuję zeskrobać stronę internetową, ale pojawia się błąd.

Używam następującego kodu:

import urllib.request
from bs4 import BeautifulSoup

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

soup = BeautifulSoup(html)

print(soup)

I pojawia się następujący błąd:

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>

Co mogę zrobić, aby to naprawić?

SstrykerR
źródło

Odpowiedzi:

257

Tak samo było UnicodeEncodeErrorpodczas zapisywania zeskrobanej zawartości internetowej w pliku. Aby to naprawić, zastąpiłem ten kod:

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

z tym:

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

Używanie iozapewnia wsteczną kompatybilność z Python 2.

Jeśli potrzebujesz tylko obsługiwać Python 3, możesz openzamiast tego użyć wbudowanej funkcji:

with open(fname, "w", encoding="utf-8") as f:
    f.write(html)
twasbrillig
źródło
6
W systemie Mac (python 3) działa idealnie z otwartym po prostu bez kodowania, ale w systemie Windows (w10, python3) nie jest opcją. Po prostu działa w ten sposób, z param kodowaniem = "utf-8".
xtornasol512
3
Dziękuję Ci. To działało dla mnie, pracowałem z plikami xml i zapisywałem wynik xml.toprettyxml () w nowym pliku
Luis Cabrera Benito
1
To powinna być zaakceptowana odpowiedź, ponieważ ostatecznie zapisze ciąg wyjściowy, a nie ciąg reprezentujący bajty.
Shirkan
OP poprosił o odczytanie pliku, ale nie zapisywanie pliku. Problem wydaje się związany z konsolą.
NaturalBornCamper
187

Naprawiłem to, dodając .encode("utf-8")do soup.

To znaczy, że print(soup)się stanie print(soup.encode("utf-8")).

SstrykerR
źródło
3
nie koduj kodowo znaków w swoim środowisku (np. konsoli) w skrypcie, zamiast tego wypisz bezpośrednio Unicode
jfs
To jest po prostu drukowanie repr bytesobiektu, który wydrukuje jako bałagan \xsekwencji, jeśli jest dużo tekstu zakodowanego w UTF-8. Polecam używanie win_unicode_console, jak sugeruje @JFSebastian.
Eryk Sun
2
Użyłem powyższego rozwiązania, ale wciąż pojawiają się problemy: klasa MyStreamListener (tweepy.StreamListener): def on_status (self, status): print (str (status.encode („utf-8”)))) UnicodeEncodeError: kodek „charmap” może ” t koduje znak „\ u2019” na pozycji 87: znak odwzorowuje na <nie zdefiniowano>
Vivek
2
To sprawia, że b'\x02x\xc2\xa9'zamiast tego jest drukowany (obiekt bajtów)
MilkyWay90
1
print(soup.encode("utf-8"))pracował dla mnie, ale wcześniej musiałem również dodaćwith open("f_name", encoding="utf-8") as f: soup = BeautifulSoup(f, "html.parser")
TheWalkingData,
44

W Pythonie 3.7 i systemie Windows 10 to działało (nie jestem pewien, czy będzie działać na innych platformach i / lub innych wersjach Pythona)

Zastępując ten wiersz:

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

Z tym:

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

Powodem, dla którego działa, jest to, że kodowanie zmienia się na UTF-8 podczas korzystania z pliku, więc znaki w UTF-8 można konwertować na tekst, zamiast zwracać błąd, gdy napotka znak UTF-8, który jest nie suppord przez obecne kodowanie.

Sabbir Ahmed
źródło
1
print (zupa) powrót \ xd0 \ xbf \ xd0 \ xbe \ xd0 \ xb6 \ xd0 \ xb0 \ xd0 \ xbb \ xd1 \ x83 \ xd0 \ xb9 \ xd
Coffee inTime
12

Podczas zapisywania odpowiedzi na żądanie get ten sam błąd został zgłoszony w Pythonie 3.7 w oknie 10. Odpowiedź otrzymana z adresu URL, kodowanie to UTF-8, więc zawsze zaleca się sprawdzenie kodowania, aby można było przekazać to samo, aby uniknąć tak trywialnego problemu ponieważ naprawdę zabija dużo czasu w produkcji

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)

Kiedy dodałem kodowanie = "utf-8" za pomocą polecenia open, zapisałem plik z poprawną odpowiedzią

with open ('NiftyList.txt', 'w', encoding="utf-8") as f:
    f.write(resp.text)
Abhishek Jain
źródło
10

Nawet ja napotkałem ten sam problem z kodowaniem, który występuje, gdy próbujesz go wydrukować, odczytać / zapisać lub otworzyć. Jak wspomniano powyżej, dodanie .encoding = "utf-8" pomoże, jeśli spróbujesz go wydrukować.

soup.encode („utf-8”)

Jeśli próbujesz otworzyć zeskrobane dane i być może zapisać je w pliku, otwórz plik za pomocą (......, encoding = "utf-8")

z otwartym (filename_csv, 'w', newline = '', encoding = "utf-8") jako plik csv:

Pardhu Gopalam
źródło
6

Dla tych, którzy nadal otrzymują ten błąd, dodanie encode("utf-8")go souprównież to naprawi.

soup = BeautifulSoup(html_doc, 'html.parser').encode("utf-8")
print(soup)
Pseudo Sudo
źródło
2
soupBeautifulSouppo wykonaniu tej czynności nie jest już obiektem, więc nie można nim manipulować ani wyszukiwać
NaturalBornCamper