UnicodeEncodeError:“charmap”编解码器无法在位置 1087 编码字符“\u011f”:字符映射到 <undefined>

Posted

技术标签:

【中文标题】UnicodeEncodeError:“charmap”编解码器无法在位置 1087 编码字符“\\u011f”:字符映射到 <undefined>【英文标题】:UnicodeEncodeError: 'charmap' codec can't encode character '\u011f' in position 1087: character maps to <undefined>UnicodeEncodeError:“charmap”编解码器无法在位置 1087 编码字符“\u011f”:字符映射到 <undefined> 【发布时间】:2021-01-27 21:09:06 【问题描述】:

我的抓取功能有问题。

在这个项目中,我有一个 sqlite3 数据库,其中包含指向音乐专辑评论的链接。我创建了一个包含这两种方法的 scraper.py 文件:

from bs4 import BeautifulSoup
import requests

def take_source(url):
    if 'http://' or 'https://' in url:
        source = requests.get(url).text
        return source
    else:
        print("Invalid URL")


def extract_corpus(source):
    soup = BeautifulSoup(source, "html.parser")
    soup.prettify().encode('cp1252', errors='ignore')
    corpus = []
    for e in soup.select("p"):
        corpus.append(e.text)

    return corpus

我在一个名为 embedding.py 的文件中调用 extract_corpus 方法, 在这个文件中,我创建了一个与 sqlite3 数据库的连接,并将数据放入 Pandas 数据框中。 我想将所有链接的内容存储在 csv 文件中。我的 embedding.py 文件包含:

import sqlite3
import pandas as pd
import scraper
import csv

#create connection with sqlite db
con = sqlite3.connect("database.sqlite")

#creating a pandas data frame
query = pd.read_sql_query("SELECT url, artist, title FROM reviews;", con)


#populating data frame with urls
df = pd.DataFrame(query, columns=['url', 'artist', 'title'])

#preparing the .csv file for storing the reviews
with open('reviews.csv', 'w') as csvfile:
        fieldnames = ['title', 'artist', 'review']
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        writer.writeheader()

def append_csv(tit,art,rev):
    with open('reviews.csv','a') as csv_f:
        writer = csv.DictWriter(csv_f, fieldnames=fieldnames)
        writer.writerow('title': tit, 'artist':art,'review':rev)

for i, row in df.iterrows():
    
    album = (str(row.__getitem__('title')))
    artist = (str(row.__getitem__('artist')))
    review = str(scraper.extract_corpus(scraper.take_source(str(row.__getitem__('url')))))
    append_csv(album,artist,review)
    

当我运行这个文件时,它适用于初始的一组链接,然后它会中断返回标题中的错误。这是错误:

Traceback(最近一次调用最后一次):文件 “C:/Users/kikko/PycharmProjects/SongsBot/embedding.py”,第 59 行,在 append_csv(album,artist,review) 文件“C:/Users/kikko/PycharmProjects/SongsBot/embedding.py”,第 52 行,在 append_csv writer.writerow('title': tit, 'artist':art,'review':rev) File "C:\Users\kikko\AppData\Local\Programs\Python\Python37-32\lib\csv.py ", 第 155 行,在 writerow 中 返回 self.writer.writerow(self._dict_to_list(rowdict)) 文件 "C:\Users\kikko\AppData\Local\Programs\Python\Python37-32\lib\encodings\cp1252.py", 第 19 行,在编码中 return codecs.charmap_encode(input,self.errors,encoding_table)[0] UnicodeEncodeError: 'charmap' codec can't encode character '\u011f' in 位置 1087:字符映射到

很遗憾,我找不到错误。

【问题讨论】:

用您自己的话说,您希望soup.prettify().encode('cp1252', errors='ignore') 做什么?特别是,您是否希望修改原始的soup?它没有:它改为创建字符串的字节编码,然后将其丢弃,未使用。 【参考方案1】:

看来你这里有多重误解。

soup.prettify().encode('cp1252', errors='ignore')

这没有任何用处:您创建一个表示 HTML 源的字符串(使用.prettify),将其编码为字节(.encode),然后对生成的对象不做任何事情。 soup 未修改。

幸运的是,在此过程中,您不需要或不想对编码做任何事情。但最好完全删除这条线,以免误导自己。

for e in soup.select("p"):
    corpus.append(e.text)

return corpus

您将生成并返回一个字符串列表,稍后您将尝试使用str 将其强制转换为字符串。结果将显示列表的表示形式:即,它将包含在[] 中,并用逗号分隔每个字符串的项目、引号和转义序列。这可能不是您想要的。

我假设您想将字符串连接在一起,例如'\n'.join(corpus)。但是,像这样的多行数据不适合存储在 CSV 中。 (转义列表表示形式存储在 CSV 中也相当尴尬。您可能应该更多地考虑如何格式化数据。)

review = str(scraper.extract_corpus(scraper.take_source(str(row.__getitem__('url')))))

首先,你不应该直接调用像__getitem__ 这样的双下划线方法。我知道它们在文档中是这样写的;这只是 Python 一般如何工作的产物。您应该使用__getitem__,因此:row['url']

您应该期望结果已经是一个字符串,所以内部的str 调用是无用的。然后你用take_source,有这个错误:

if 'http://' or 'https://' in url:

这个does not do what you want;该函数将始终认为 URL 是“有效的”。

无论如何,一旦你设法 extract_corpus 并从中强行生成一个字符串,你所询问的实际问题就会发生:

with open('reviews.csv','a') as csv_f:

您不能简单地将任意字符串写入 cp1252 编码的文件(您知道这是正在使用的字符串,因为在您的堆栈跟踪中提到了cp1252.py;它是您平台的默认设置)。 这个是你应该指定文件编码的地方。例如,您可以指定应该使用encoding='utf-8' 写入文件,它可以处理任何字符串。 (当您出于任何其他目的再次打开文件时,您还需要明确指定这一点。)

如果您坚持手动进行编码,那么您将需要 .encode 对文件进行 .writeing 处理。但是,因为.encode 产生原始编码字节,所以您需要以二进制模式打开文件(如'ab'),这也意味着您必须自己处理通用换行编码。这不是一个愉快的任务。请按照设计使用的方式使用该库。


在正确处理文本编码等方面,您不能仅通过尝试修复出现的每个错误来编写质量不错的正确代码,执行网络搜索每个错误或通过强制转换消除类型错误。您必须真正了解发生了什么。我不能强调这一点。请开始here,然后也阅读here。从上到下阅读,旨在理解所说的内容,而不是试图解决任何具体问题。

【讨论】:

非常感谢您详细而一致的回复。感谢您的澄清,我已经成功解决了我遇到的问题。不幸的是,我对这些概念不太熟悉,我写了一些代码而没有注意这些问题。仔细看了你传给我的文章,我可以说我的思路清晰多了。再次感谢您给我的时间。

以上是关于UnicodeEncodeError:“charmap”编解码器无法在位置 1087 编码字符“\u011f”:字符映射到 <undefined>的主要内容,如果未能解决你的问题,请参考以下文章

Charm Bracelet

poj 3624 Charm Bracelet

POJ-3624-Charm Bracelet

Charm Bracelet(01背包问题)

dp--01背包--Charm Bracelet

POJ3624 Charm Bracelet 01背包