用户画像练习
第三方模块安装
需要安装的第三方模块有jieba、sklearn和wordcloud。jieba用于分词,sklearn已在第2章介绍过,wordcloud用于生成标签云图,分别用pip命令进行安装:
$ pip3 install jieba $ pip3 install sklearn
wordcloud需要下载whl文件进行安装,打开下载网站https://www.lfd.uci.edu/~gohlke/pythonlibs/#wordcloud,�选择对应Python版本安装,�例如64位的Python 3.6,就选择如图所示进行下载。
下载之后进行安装:
$ pip3 install wordcloud-1.4.1-cp36-cp36m-win_amd64.whl
从京东那里爬取商品评论
爬取评论方法:
def getComments(): f_comments_json = open('comments_json.txt', mode='w', encoding='gbk') #使用GBK编码,否则会出错 for i in range(100): #爬取100页,每页10条评论 url = 'https://sclub.jd.com/comment/productPageComments.action' data = 'productId=7437788&score=0&sortType=5&pageSize=10&page=%s' % str(i) complete_url = url + "?" + data response = urllib.request.urlopen(complete_url).read().decode('gbk') f_comments_json.write('%s\n' % response)
上述代码做了这些操作:先以gbk编码创建一个文件用来储存原始评论数据,这里使用gbk是因为京东返回的数据就是gbk编码的;接着组织好get请求的链接,使用urllib发起请求,就这样连续爬取100页,每页10条评论,把返回的json格式的数据写入comments_json.txt文件。( 详细代码及需要导入的模块请参考实操手册章节4.1.2)
www.bejson.com
数据清洗
爬取的评论数据包含了许多信息,包括用户名、评论时间等等,我们需要的是评论内容,所以需要把原始数据进行过滤清洗。原始评论的数据是json形式的,格式如图4-2所示。
使用 www.bejson.com使格式更好看一点。
从图中可以看出,comments是一个json对象数组,每个元素对应一个用户的评论,而用户评论的具体内容又存放在content中。了解了数据的具体结构后,就可以很容易实现代码了:
def filterComments(): f_comments = open('comments.txt', encoding='utf8', mode='w') with open('comments_json.txt', encoding='gbk') as f: for line in f: s = json.loads(line.strip()) # 解析json comments = s['comments'] # 读取json对象数组 for comment in comments: content = comment['content'].replace('\n', '') # 去掉换行符 f_comments.write('%s\n' % content)
上述代码做了这些操作:先创建一个utf-8编码的文件用于存放过滤后的评论数据;读取原始评论数据comments_json.txt的文件的每一行,每一行对应一个评论,调用json进行解析即可读取具体的评论内容;最后写入文件即可。
对评论进行中文分词、去停用词
中文分词(Chinese Word Segmentation) 指的是将一个汉字序列切分成一个个单独的词。 举个例子来简单说明分词做了什么操作。“张三买了张三角桌”可以分词为“张三”、“买了”、“张”、“三角桌”。使用jieba库可以很方便的实现分词操作,代码如下:
def wordSeg(): f_comments = open('comments.txt', encoding='utf8') f_comments_ws = open('comments_word_seg.txt', encoding='utf-8', mode='w') for line in f_comments: cut_txt = ' '.join(jieba.cut(line)) # 调用jibea进行分词 f_comments_ws.write('%s\n' % cut_txt)
上述代码做了这些操作:以utf-8编码创建一个文件用于存放分词的结果;读取评论内容文件comments的每一行调用jieba进行分词操作;最后把分词的结果写入文件。
在基于词的检索系统中,停用词是指出现频率太高、 没有太大检索意义的词,如“的、是、太、of、the等[7],停用词可以从互联网上搜索下载,这里使用的停用词列表是stop_words.txt文件,可以在附件中找到。去除停用词的代码如下:�
def removeStopWords(): f_stop_words = open('stop_words.txt', encoding='utf8') stop_words = [line.replace('\n', '') for line in f_stop_words] # 读取停用词列表 f_comments_processed = open('comments_processed.txt', encoding='utf-8', mode='w') with open('comments_word_seg.txt', encoding='utf-8') as f: for line in f: line = line.strip().split(' ') # 去除首尾空格,按照空格分割为列表 new_line = '' for c in line: if c not in stop_words: # 非停用词保留,停用词则去除 new_line = new_line + ' ' + c for word in new_line.split(' '): if len(word) != 0: f_comments_processed.write('%s ' % word) f_comments_processed.write('\n')
上述代码做了这些操作:首先读取停用词文件stop_words.txt存储为一个列表;以utf-8编码创建一个文件用于存储去停用词后的评论;按行读取先前分词后的评论文件comments_word_seg.txt;这每一行都按照空格分割为列表,遍历这个列表中的元素,判断是否为停用词,若是则进行保留;最后写入文件。
计算TF-IDF词频并应用K-均值聚类算法
TF-IDF的全称是Term Frequency-Inverse Document Frequency,翻译过来就是“词频-逆文本频率”。TF容易理解,即一个文本中各个词出现的频率统计。IDF反映了一个词在所有文本中出现的频率,能够反映词语的重要性,举个例子来说明IDF,有如下语料:
corpus=["I come to China to travel", "This is a car polupar in China", "I love tea and Apple ", "The work is to write some papers in science"]
上面的4个文本中几乎都出现了to、is、and,词频虽然高,但是重要性却没有China、Apple高。所以,若一个词出现在很多文本中,它的IDF值应当低,若一个词出现在比较少的文本中,它的IDF应当高。最后的TF-IDF值等于TF与IDF相乘。总的来说,TF-IDF就是从两个方面对文本中的词进行加权:①词在当前文本中出现的次数;②总文本数包含词的数目。
具体实现方法:为每一行建立一个10000个元素的数组,以统计每个词出现的次数
def calcTFIDF(n): corpus = [] # 读取评论文件作为语料 with open('comments_processed.txt', encoding='utf-8') as f: for line in f: if not line == '\n': corpus.append(line.strip()) # 将文本中的词语转换为词频矩阵 矩阵元素a[i][j] 表示j词在i类文本下的词频 vectorizer = CountVectorizer() # 该类会统计每个词语的tf-idf权值 transformer = TfidfTransformer() # 第一个fit_transform是计算tf-idf 第二个fit_transform是将文本转为词频矩阵 tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus)) # 获取词袋模型中的所有词语 terms = vectorizer.get_feature_names() # 将tf-idf矩阵抽取出来,元素w[i][j]表示j词在i类文本中的tf-idf权重 weight = tfidf.toarray() # for i in range(len(weight)): # print(u"-------这里输出第", i, u"类文本的词语tf-idf权重------") # for j in range(len(terms)): # print(weight[i][j], end=' ') # print() n_clusters = n model = KMeans(n_clusters) # 聚类成5组 model.fit(weight) # 进行拟合 for i in range(n_clusters): with open('cluster_' + str(i) + '.txt', encoding='utf-8', mode='w') as f: for j in range(len(model.labels_)): # 读取每个聚类的词并写入文件 if model.labels_[j] == i: f.write(corpus[j] + '')
生成词云
def generateCloud(n): for i in range(n): f = open('cluster_' + str(i) + '.txt', encoding='utf-8') lines = [] for line in f: if not line == '\n': lines.append(line.replace('\n', '')) all_words = ''.join(lines) # 读取文本中的文件合并为1行 color_mask = numpy.array(Image.open('mask.jpg')) cloud = WordCloud( # 设置字体,不指定就会出现乱码 font_path='simhei.ttf', width=1000, height=1000, # 设置背景色 background_color='white', # 词云形状 mask=color_mask, # 允许最大词汇 max_words=200, # 最大号字体 max_font_size=300, collocations=False ) word_cloud = cloud.generate(all_words) # 产生词云 word_cloud.to_file('cluster_cloud_' + str(i) + '.jpg') # 保存图片
返回 Spark电影推荐