UnicodeEncodeError: le codec 'charmap' ne peut pas coder les caractères

206

J'essaie de gratter un site Web, mais cela me donne une erreur.

J'utilise le code suivant:

import urllib.request
from bs4 import BeautifulSoup

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

soup = BeautifulSoup(html)

print(soup)

Et j'obtiens l'erreur suivante:

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>

Que puis-je faire pour résoudre ce problème?

SstrykerR
la source

Réponses:

258

J'obtenais la même chose UnicodeEncodeErrorlors de l'enregistrement du contenu Web gratté dans un fichier. Pour le réparer, j'ai remplacé ce code:

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

avec ça:

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

L'utilisation iovous donne une compatibilité descendante avec Python 2.

Si vous avez seulement besoin de prendre en charge Python 3, vous pouvez utiliser la openfonction intégrée à la place:

with open(fname, "w", encoding="utf-8") as f:
    f.write(html)
twasbrillig
la source
6
Dans mac (python 3) fonctionne parfaitement avec juste ouvert sans encodage, mais dans windows (w10, python3) n'est pas une option. Fonctionne juste de cette manière, avec encoding = "utf-8" param.
xtornasol512
3
Je vous remercie. Cela a fonctionné pour moi, je travaillais avec des fichiers xml et j'écrivais le résultat de xml.toprettyxml () dans un nouveau fichier
Luis Cabrera Benito
1
Cela devrait être la réponse acceptée car elle finira par écrire une chaîne dans la sortie, et non une représentation sous forme de chaîne d'octets.
Shirkan
OP a cependant demandé de lire le fichier, pas d'écrire le fichier. Le problème semble être lié à la console.
NaturalBornCamper
188

Je l'ai corrigé en ajoutant .encode("utf-8")à soup.

Cela signifie que cela print(soup)devient print(soup.encode("utf-8")).

SstrykerR
la source
3
ne codez pas en dur le codage des caractères de votre environnement (par exemple, la console) dans votre script, imprimez directement Unicode à la place
jfs
Il s'agit simplement d'imprimer la représentation d'un bytesobjet, qui s'imprimera comme un désordre de \xséquences s'il y a beaucoup de texte encodé en UTF-8. Je recommande d'utiliser win_unicode_console, comme le suggère @JFSebastian.
Eryk Sun
2
J'ai utilisé la solution ci-dessus mais j'obtiens toujours des problèmes: classe MyStreamListener (tweepy.StreamListener): def on_status (self, status): print (str (status.encode ("utf-8"))) UnicodeEncodeError: le codec 'charmap' peut '' t encoder le caractère '\ u2019' en position 87: mappage de caractères à <non défini>
Vivek
2
Cela le fait imprimer à la place b'\x02x\xc2\xa9'(un objet en octets)
MilkyWay90
1
print(soup.encode("utf-8"))travaillé pour moi, mais avant cela, je devais également ajouterwith open("f_name", encoding="utf-8") as f: soup = BeautifulSoup(f, "html.parser")
TheWalkingData
44

En Python 3.7 et fonctionnant sous Windows 10, cela a fonctionné (je ne sais pas si cela fonctionnera sur d'autres plates-formes et / ou d'autres versions de Python)

Remplacement de cette ligne:

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

Avec ça:

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

La raison pour laquelle cela fonctionne est que le codage est modifié en UTF-8 lors de l'utilisation du fichier, de sorte que les caractères dans UTF-8 peuvent être convertis en texte, au lieu de renvoyer une erreur lorsqu'il rencontre un caractère UTF-8 qui est pas supporté par l'encodage actuel.

Sabbir Ahmed
la source
1
print (soup) return \ xd0 \ xbf \ xd0 \ xbe \ xd0 \ xb6 \ xd0 \ xb0 \ xd0 \ xbb \ xd1 \ x83 \ xd0 \ xb9 \ xd
Coffee inTime
12

Lors de l'enregistrement de la réponse de la demande get, la même erreur a été émise sur Python 3.7 sur la fenêtre 10. La réponse reçue de l'URL, le codage était UTF-8, il est donc toujours recommandé de vérifier le codage afin qu'il puisse être transmis pour éviter un problème aussi trivial car il tue vraiment beaucoup de temps en production

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)

Lorsque j'ai ajouté encoding = "utf-8" avec la commande open, il a enregistré le fichier avec la bonne réponse

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

Même moi, j'ai rencontré le même problème avec l'encodage qui se produit lorsque vous essayez de l'imprimer, de le lire / écrire ou de l'ouvrir. Comme d'autres l'ont mentionné ci-dessus, l'ajout de .encoding = "utf-8" vous aidera si vous essayez de l'imprimer.

soup.encode ("utf-8")

Si vous essayez d'ouvrir des données grattées et peut-être de les écrire dans un fichier, ouvrez le fichier avec (......, encoding = "utf-8")

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

Pardhu Gopalam
la source
6

Pour ceux qui obtiennent toujours cette erreur, l'ajout encode("utf-8")à soupcorrigera également le problème.

soup = BeautifulSoup(html_doc, 'html.parser').encode("utf-8")
print(soup)
Pseudo Sudo
la source
2
soupn'est plus un BeautifulSoupobjet après cela, il ne peut donc pas être manipulé ou recherché
NaturalBornCamper