任务要求
情绪理解是文本处理里最常见任务之一。现提供一个五类情绪字典(由情绪词组成,5 个文件,人工标注),实现一个情绪分析工具,并利用该工具对10000条「某社交平台」内容进行测试和分析(一行一条「某社交平台」内容)。字典数据见公开数据中的emotion lexicon (https://doi.org/10.6084/m9.figshare.12163569.v2)。
STEP1 数据清洗与转换
观察原始数据的特点可以发现:
每日必做一事要越来越多哈,第三日[做鬼脸]刚刚差点忘了QQ空间@何凯文 每日一句,filial duty[爱你] 我在这里:http://t.cn/z8AG60D Fri Oct 11 01:09:49 +0800 2013 [39.979173530384, 116.43293726453]
内涵图 我在:http://t.cn/z8FTqat Fri Oct 11 14:51:38 +0800 2013 [39.856444, 116.357902]
💋感谢一路有你💓💛💙💜💚❤💗💘💞💖💕 我在:http://t.cn/zRqGqkQ Sat Oct 12 20:23:18 +0800 2013 [39.97234, 116.312958]
补贴家用之兔子幼儿园和小伙伴冰箱贴[带着微博去旅行][熊猫] 我在:http://t.cn/zRG6lGY Fri Oct 11 21:35:28 +0800 2013 [39.925411, 116.338135]
也许有时我们脚步太快,忘却了身边简单的快乐 我在:http://t.cn/zRGCcE5 Fri Oct 11 23:57:00 +0800 2013 [39.999714, 116.385483]
我在这里:#清华大学第六教学楼#大家近来可好呀? @蓝蓝嫣然 @Kakakakakaka_kaka @麦田里的塔木德 @徐_小敏敏敏 @姑奶奶何叶叶 @西城佩玉 @小羊在成长 @嘻哈糊 @Eason彤 @徐_小敏敏敏 @smile要阳光 @1990图腾 @onenudtambition @苏苏Sue杰声慧影 @佳木朽 @于文小思 @Miss_绚 我在:http://t.cn/zRbr415 Fri Oct 11 09:00:28 +0800 2013 [40.004493, 116.32875]
我们可以发现微博里存在的几种特别格式:
-
位置网址链接(同时包括
我在: / 我在这里:
) -
emoji表情💓💛💙💜💚❤与微博自带表情
[]
(需要注意的是表情符号通常带有一定的情绪倾向,时间原因本次作业对表情影响暂不考虑,数据清洗时直接将表情去除) -
@
其他用户信息 -
话题
#
(需要注意的是,根据微博用户的使用习惯,话题通常为句子的一个必要组成部分,不能直接删除,选择去除符号#
) -
文字和时间、时间和经纬度之间用
\t
区隔。
根据后续分析的需求,计划构建一个字典列表,为:
[{
原文wb_word, 处理后wb_text, 时间wb_time, 地点wb_loca, 分词wb_cut}, ..., {
...}]
1.1数据清洗
- 读取文件:
def document_to_list(path):
"""
读取文档,按行划分,返回列表
:param path: 目标文档路径
:return doc_l: 文档内容列表
"""
print("正在将%s转换为文本列表, 请稍等..." % path)
doc_list = []
with open(path, 'r', encoding='utf-8') as doc_f:
for line in doc_f.readlines():
line = line.strip('\n')
doc_list.append(line)
return doc_list
- 在网上查找到利用正则表达式清洗微博数据的库
HarvestText
,得到微博清洗函数:
def clean_text(text):
"""
根据提供的微博数据集,进行各种文本清洗操作,微博中的特殊格式,网址,email,html代码,等等
:param text: 输入文本
:return: 清洗后的文本
"""
text = re.sub(r"(回复)?(//)?\s*@\S*?\s*(:| |$)", " ", text) # 去除 @ 和转发链 //
text = re.sub(r"\[\S+?]", "", text) # 去除微博表情 [文字]
addr_URL = re.compile(
r'(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?«»“”‘’]))',
re.IGNORECASE)
text = re.sub(addr_URL, "", text) # 去除地址和 URL
text = re.sub("转发微博", "", text)
text = re.sub("我在:", "", text)
text = re.sub("我在这里:", "", text) # 去除无意义的字样
text = re.sub(r"\s+", " ", text) # 去除多余的空格
text = re.sub(r"#", "", text)
emoji_pattern = re.compile("["
u"\U0001F600-\U0001F64F" # emoticons
u"\U0001F300-\U0001F5FF" # symbols & pictographs
u"\U0001F680-\U0001F6FF" # transport & map symbols
u"\U0001F1E0-\U0001F1FF" # flags (iOS)
u"\U00002702-\U000027B0"
"]+", flags=re.UNICODE)
text = emoji_pattern.sub(r'', text)
return text.strip()
- 测试数据清洗结果:
ts = clean_text("🇨🇳🇨🇳又#失眠#了[抓狂][抓狂]。每天发生每一件很细小的事情,晚上都会静静的思考一些种种问题。明天早晨然后完美的解决。我在进步[阴险][阴险] 😄")
---------------
>>>print(ts)
又失眠了。每天发生每一件很细小的事情,晚上都会静静的思考一些种种问题。明天早晨然后完美的解决。我在进步
1.2jieba 分词,并实现前文所述的数据结构
def cut_words(doc, stopwords):
"""
给出语句和停用词集合,使用 jieba 分词,返回分词列表
:param doc: 语句
:param stopwords: 停用词集合
:return wordlist: 分词后列表
"""
wordlist = []
for word in jieba.cut(doc):
if word not in stopwords:
wordlist.append(word)
return wordlist
def get_weibo_info(doc_list):
"""
根据输入的每行文本列表,对信息进行初步处理,包括获取微博内容、发送时间、发送位置、并用jieba进行分词
:param doc_list: 微博文档列表
:return weibo_list: 列表,元素为单条微博的字典
"""
weibo_list = []
jieba.load_userdict(r"0_Res/anger.txt")
jieba.load_userdict(disgust_path)
jieba.load_userdict(fear_path)
jieba.load_userdict(joy_path)
jieba.load_userdict(sadness_path)
for