我正在做一个项目,分析城市政策类(class)的推文。该脚本的目的是从同事下载的 JSON 文件中解析出某些信息。以下是我尝试解析的示例推文的链接:
https://www.dropbox.com/s/qf1e06601m2mrxr/5thWardChicago.0.json?dl=0
我让我的一个 friend 在某些版本的 Python 2 (Windows) 中测试了以下脚本,并且它有效。但是,我的机器(Windows 10)正在运行最新版本的 Python 3,但它对我不起作用。
import json
import collections
import sys, os
import glob
from datetime import datetime
import csv
def convert(input):
if isinstance(input, dict):
return {convert(key): convert(value) for key, value in input.iteritems()}
elif isinstance(input, list):
return [convert(element) for element in input]
elif isinstance(input, unicode):
return input.encode('utf-8')
else:
return input
def to_ilan_csv(json_files):
# write the column headers
csv_writer = csv.writer(open("test.csv", "w"))
headers = ["tweet_id", "handle", "username", "tweet_text", "has_image", "image_url", "created_at", "retweets", "hashtags", "mentions", "isRT", "isMT"]
csv_writer.writerow(headers)
# open the JSON files we stored and parse them into the CSV file we're working on
try:
#json_files = glob.glob(folder)
print("Parsing %s files." % len(json_files))
for file in json_files:
f = open(file, 'r')
if f != None:
for line in f:
# hack to avoid the trailing \n at the end of the file - sitcking point LH 4/7/16
if len(line) > 3:
i = 0
tweets = convert(json.loads(line))
for tweet in tweets:
has_media = False
is_RT = False
is_MT = False
hashtags_list = []
mentions_list = []
media_list = []
entities = tweet["entities"]
# old tweets don't have key "media" so need a workaround
if entities.has_key("media"):
has_media = True
for item in entities["media"]:
media_list.append(item["media_url"])
for hashtag in entities["hashtags"] :
hashtags_list.append(hashtag["text"])
for user in entities["user_mentions"]:
mentions_list.append(user["screen_name"])
if tweet["text"][:2] == "RT":
is_RT = True
if tweet["text"][:2] == "MT":
is_MT = True
values = [
tweet["id_str"],
tweet["user"]["id_str"],
tweet["user"]["screen_name"],
tweet["text"],
has_media,
','.join(media_list) if len(media_list) > 0 else "",
datetime.strptime(tweet["created_at"], '%a %b %d %H:%M:%S +0000 %Y').strftime('%Y-%m-%d %H:%M:%S'),
tweet["retweet_count"],
','.join(hashtags_list) if len(hashtags_list) > 0 else "",
','.join(mentions_list) if len(mentions_list) > 0 else "",
is_RT,
is_MT
]
csv_writer.writerow(values)
else:
continue
f.close()
except:
print("Something went wrong. Quitting.")
for i in sys.exc_info():
print(i)
def parse_tweets():
file_names = []
file_names.append("C:\\Users\\Adam\\Downloads\\Test Code\\sample1.json")
file_names.append("C:\\Users\\Adam\\Downloads\\Test Code\\sample2.json")
to_ilan_csv(file_names)
然后我通过简单地执行来执行
parse_tweets()
但我收到以下错误:
Parsing 2 files.
Something went wrong. Quitting.
<class 'UnicodeDecodeError'>
'charmap' codec can't decode byte 0x9d in position 3338: character maps to <undefined>
<traceback object at 0x0000016CCFEE5648>
我向我的一位计算机科学 friend 寻求帮助,但他无法诊断问题。所以我就来这里了。
我的问题
这个错误是什么?为什么它只出现在 Python 3 而不是 Python 2 中?
对于那些想要尝试的人,所提供的代码应该能够使用 Jupyter 笔记本和我提供的投递箱链接中的文件副本运行。
最佳答案
Sooo,在聊天中进行了一些调试后,解决方案如下:
显然,OP 使用的文件未正确识别为 UTF-8,因此迭代该文件(使用 for line in f
)导致了 UnicodeDecodeError
cp1252
编码模块。我们通过明确将文件打开为 utf-8 来解决这个问题:
f = open(file, 'r', encoding='utf-8')
完成此操作后,文件可以正确打开,并且 OP 遇到了我们之前一直期待和看到的 Python 3 问题。出现了以下三个问题:
“dict”对象没有属性“iteritems”
dict.iteritems()
在 Python 3 中不再存在,因此我们在这里切换到dict.items()
:return {convert(key): convert(value) for key, value in input.items()}
名称“unicode”未定义
Unicode在Python 3中不再是一个单独的类型,普通的字符串类型已经能够支持unicode,所以我们只需删除这种情况:
elif isinstance(input, unicode): return input.encode('utf-8')
“dict”对象没有属性“has_key”
要检查字典中是否存在某个键,我们使用
in
运算符,因此if
检查如下:if "media" in entities:
之后,代码应该可以在 Python 3 上正常运行。
关于python - <class 'UnicodeDecodeError' > 仅出现在 Python 3 中,而不出现在 Python 2 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41824061/