如何用python爬取美团点评数据并做情感分析

自从18年10月底开始课余在导师的公司实习,不知不觉入坑机器学习和深度学习已经小半年时间。目前的主要方向是NLP和数据挖掘。

这期间接触了许多新的知识,见识了火热的深度学习的魅力和实际应用,也认识了很多浙大的牛人,有很多感触。

这篇文章,是对我近期做的情感分析demo的一个总结;但正因为它简单又内容丰富,相信会帮助即便外行的读者,也能对爬虫和深度学习有新的认识。

全文共计3800余字,阅读时间预计10分钟。阅读完本文,你将学习到:

01 如何安装使用python

02 如何用python爬取数据

03 如何使用pandas、numpy做简单的数据处理

04 如何调用bert-as-service,快速得到中文词向量

05 如何使用深度学习框架keras建模,做简单的情感分析

01 如何安装使用Python

安装python的方式很多,而Mac osUbuntu等操作系统甚至已经预装了python

但是,我还是强烈推荐你安装Anaconda套装。它是一个开源的python发行版本,包含了180多个科学包及其依赖项,其中很多工具包对于后期机器学习的研究非常重要。所以第一次就安装它,可以“一劳永逸”。

进入Anaconda官网的下载页面,可以根据你使用的系统下载最新版本的conda。如果你想下载历史版本的Anaconda,可以点击此链接

此后,根据中文提示一步步安装即可,非常简单方便。

image.png
安装完成后,进入终端(Windows下称“命令提示符”),我们使用conda创建一个虚拟环境,这样可以和系统中原有的python环境相隔离。

如图,我们创建了一个python3.6版本的虚拟环境,使用conda env list可以查看我们当前所有虚拟环境(目前只有py36),然后source activate py36激活它。

到此,python最基础的环境搭建全部完成啦。

02 如何用python爬取数据

学不学计算机,想必你都曾经听过“爬虫”这个词。说实话,我当初第一次听到这两个字,想到的是一群虫子在我身上爬,起了一身鸡皮疙瘩....

好!我们言归正传。在准备爬取数据前,我们得先对什么是爬虫有简单的了解:

网络爬虫(Web crawler),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本,采集所有其能够访问到的页面内容(包括文本、图片、视频、音频等)

简单的说,所谓爬虫就是用程序去自动采(爬)集(取)互联网上的公开内容。

而爬虫之所以总是和python挂钩,是因为python这一脚本语言非常适合写爬虫代码。如果你问我有多简单?

两行代码就完事了!

import requests
r = requests.get(url="http://www.baidu.com")

requests库会自动向我们指定的url链接(百度)发起http请求,并将结果返回到r.content中。

当然这只是最简单的一种情况,爬取到的内容也不过是百度首页的源码;但实际开发爬虫时的核心内容,已经在这两行代码里完美呈现了,可以说剩下的都是“点缀”。

在我们的这个项目中,使用了一个比requests库稍复杂的框架Scrapy,它是python最火热的爬虫框架,结构化的设计可以让开发人员非常方便的根据项目需求进行修改。

如果对 Scrapy有兴趣的同学,我可以为你提供一些参考资料:

01 Scrapy官方文档
02 《Python爬虫开发与项目实战》
03 构建单机千万级别的微博爬虫系统

当然,我觉得最快的学习方式是先简单了解scrapy的理论基础(如5大组成部分),然后进行项目实战(参考微博爬虫项目,写的挺完善)。

这里的美团点评爬虫,爬取的是杭州、上海、北京等5大城市各1000家餐馆的前200条点评(合计约100w+评论数据),通过构造访问api接口,提取json格式的数据。代码类似于长这样:

由于本文的重点不是爬虫讲解,所以代码部分直接一带而过。

在评论内容的筛选上,我只保留了4-5星和1-2星的评论,作为后期情感识别的训练/测试数据。

最终爬取结果:

我将评论数据存储到mongodb中,省去了建表的麻烦。

如果嫌慢,我们还可以采取分布式的架构(如scrapy-redis),加快爬虫的爬取速度。

耐心等待爬虫运行结束,去数据库中查看爬虫忠诚的为我们爬取的数据:


爬取结果

有了数据,接下来要做的就是数据预处理啦!

03 使用pandas、numpy做简单的数据处理

很多人把pandasnumpymatplotlib3个库称为python数据处理和可视化的三剑客,因为它们真的功能强大又好用。这里我先介绍前两个,matplotlib留到第5小节。

我们爬取的数据保留在mongodb中,我们可以用mogoexport或借助数据库可视化软件将其导出到csv文件中。

这里为了简化,我们分别导出评分5星和评分1星的评论(刚好对应正负两面情感)各6800条;在后续处理中,每种情感取6000条用作训练(包含验证集),剩余800条作为测试。

我们分别导出的数据命名为10_star.csv50_star.csv,借助pandas库用一行代码导入,并查看前5行内容。

import pandas as pd
df1 = pd.read_csv('./10_star.csv')
df2 = pd.read_csv('./10_star.csv')
print(df1.head())
print(df1.head())
运行结果

接下来,我们要遍历comment列的每一行,过滤其中的非中文字符;再将字数大于10的评论加入一个列表。

数据过滤

这是对其中的负面评论的数据处理,正面评论处理类似。最后将数据直接整合在一起:

X_data = X_data1[:6000] + X_data2[:6000]              # 训练数据
X_test_data = X_data1[6000:6800] + X_data2[6000:6800]      # 测试数据

请注意,这里我们保证了X_data前6000条数据是负面的(来自X_data1),后6000条是正面的(来自X_data2)。X_test_data也同理。

得到训练数据后,我们手工创建一个labels数组(训练标签),前6000个元素是0,后6000个元素是1;再通过numpy库转换为numpy数组,便于后期输入到神经网络中。

import numpy as np
y_data = [0 for i in range(6000)] + [1 for i in range(6000)]
y_data = np.asarray(y_data, dtype=np.float32)
y_test_data = [0 for i in range(800)] + [1 for i in range(800)]
y_test_data = np.asarray(y_data, dtype=np.float32)

现在,聪明的你可能发现一个问题:我们的数据太有规律啦,正负情感刚好前后各占了一半;假如我们输入了前3000条到模型中,机器“机智的”全判断为负面,能证明准确率就有100%了?

为了避免数据分布不规律的现象,我们需要为数据进行“洗牌”(随机打乱)。

还是借助numpy,我们可以轻松实现这一过程。

X_train = []
y_train = []
X_test = []
y_test = []

nums = np.arange(12000)
# 随机打乱12000个训练数据
np.random.shuffle(nums)
for i in nums:
    X_train.append(X_data[i])
    y_train.append(y_data[i])

# 随机打乱1600个测试数据
nums_ = np.arange(1600)
np.random.shuffle(nums_)  # shuffle改变的是自身的内容
for i in nums_:
    X_test.append(X_test_data [i])
    y_test.append(y_test_data [i])

# list转Numpy数组
X_train= np.asarray(X_train, dtype=np.float32)
X_test= np.array(X_test, dtype=np.float32)

到此为止,简单的数据预处理就结束了,是不是可以开始搭建我们的神经网络模型了?

别急!这儿我们的数据还全都是中文,即便是英文字母,计算机也一概不认识。所以,一位重量级的选手马上就要登场和我们见面了。👏👏

04 调用bert-as-service,快速得到中文词向量

在自然语言处理任务中,首先需要考虑词如何在计算机中表示。常见的表示方法有两种

01 one-hot representation (独热编码)

02 distribution representation

第一种是离散的表示方法,得到的是高维度的稀疏矩阵;第二种方法(Word Embedding)则是将词表示成定长的连续稠密向量。想深入的同学,请利用好您的搜索引擎(上网搜!)

从头训练一个有效的语言模型是耗时又耗能的过程。学习NLP的同学,一定知道去年底Google发布的Bert模型。

本例中,我们借助腾讯AI实验室发布的bert-as-service接口,让你能简单的通过两行代码,即可使用预训练好的bert模型生成句向量和ELMO风格的词向量。

关于bert-as-service的官方介绍,可以点击查看作者:肖涵博士的Git仓库

我们来看一看这两行代码是怎么实现的?

from bert_serving.client import BertClient
bc = BertClient
# 将待训练的中文数据转换为(,768)维的句向量
input_train = bc.encode(X_train)

觉得上面的内容不能马上看懂?

没关系,送上免费学习传送门:两行代码玩转Google BERT句向量词向量。写的很详细哦!

bert-as-service将一个句子统一转换成768维的句向量;最终我们得到的就是12000 * 768维度的句向量矩阵,也就是我们将输入到神经网络模型的真正数据。

05 使用Keras,实现简单的情感分析模型

虽然我们这里跑的只是一个很小的demo,但是数据处理部分依然是整个工程中最耗时间的部分;实际开发中也往往如此。

有了处理后的数据,后边的路一下畅通了许多,尤其是有keras这样容易上手的工具。

Keras是一个高层神经网络API,由纯python编写并使用Tensorflow,Theano,CNTK作为后端,以简介、快速为设计原则。

直接使用pip即可快速安装KerasTensorflow

$ pip install keras
$ pip install tensorflow

典型的Keras工作流程大致可以分为四步:

(1) 定义训练数据:输入张量和目标张量。
(2) 定义层组成的网络(或模型),将输入映射到目标。
(3) 配置学习过程:选择损失函数、优化器和需要监控的指标。
(4) 调用模型的 fit 方法在训练数据上进行迭代

我们直接使用使用Sequential类来定义模型(仅用于层的线性堆叠,是最常见的网络架构)。

from keras.models import Sequential
from keras.layers import Dense, Dropout
import tensorflow as tf
model = Sequential()
# 搭建模型
model.add(Dense(32, activation='relu', input_shape=(768,)))
model.add(Dropout(0.3))
model.add(Dense(32, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

对于简单的二分类问题,模型使用Dense全连接层拼接已经够用,最后的输出就是一个数,代表了正面/负面情感的概率。同时防止过拟合,在模型中加入了Dropout层,

接下来,我们来指定模型使用的优化器和损失函数,以及训练过程中想要监控的指标。

model.compile(
    loss='binary_crossentropy',
    optimizer=tf.train.AdamOptimizer(),
    metrics=['acc']
)

最后,通过fit方法将输入数据的Numpy数组传入模型;请注意,我们留出了20%的数据作为验证集:

history = model.fit(
    X_train, y_train,
    epochs=30,
    batch_size=128,
    validation_split=0.2,
    verbose=1
)

我们的模型就开始愉快的迭代训练啦!

训练过程可视化

可以观察到,随着迭代次数增加,模型的损失loss逐渐下降,准确度acc逐渐上升,直到最终趋于稳定,与我们的预期完全一致。

运行结束后,我们使用matplotlib库将结果可视化吧~

import matplotlib.pyplot as plt
history_dict = history.history
epochs = range(1, len(history_dict['acc']) + 1)
# 绘图部分
plt.figure()
plt.plot(epochs, history_dict['acc'], 'b', label='acc')
plt.plot(epochs, history_dict['val_acc'], 'bo', label='val_acc')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()

分别画出训练过程中损失和精确度的变化,可以知道我们的模型确实从输入数据中有效“学习”到了情感识别的模式。

image.png

因为训练数据不算太少,又加入了dropout预防过拟合,同时任务本身不算复杂,保证了我们的模型对于美团点评数据是好评还是差评有了96%的准确率!通过调参和加大模型的复杂度,这一结果应该会更高。

别忘了我们还有1600条数据被当作测试集还没使用,也就是说模型还没有“见过”这批数据。是时候派他们上场了!

调用evaluate方法实验我们的测试数据:

test_loss = model.evaluate(
    X_test,
    y_test,
    batch_size=63,
    verbose=1
)
print(test_loss)

得到结果:
[0.07956909381508012, 0.9731250016018749]

它表示训练损失和准确率分别为0.0797%


小结

本文带你了解了如何安装使用python,如何使用python爬取数据(构造爬虫),如何处理数据以及使用Keras训练模型,让最后的结果可视化。

可能涉及的内容比较多,又限于篇幅,对各个模块的内容只是管中窥豹,简要带过。

其实,这里很多模块的内容远不是一篇文章,甚至一本书就能全面详细介绍的(如对于爬虫的反爬措施部分,就可以写一本书)。如果大家愿意看,笔者会持续更新本专题下的文章。对于本文谈论的内容,你有没有什么不同的意见或者更好的建议?欢迎留言!

喜欢请不要吝啬于点赞哈。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容