0

    R从网页抓取到文本分析全教程:影评的获取与分析

    2023.07.14 | admin | 146次围观

    本期目录

    01

    网页抓取

    02

    中文分词

    03

    文档矩阵

    04

    词频共现

    05

    文本聚类

    06

    主题建模

    07

    情感分析

    08

    词频统计

    09

    绘制词云

    随着技术进步,定量分析方法,不再仅仅通过问卷、二手数据库等方式收集数据,不再仅仅通过数理统计、回归分析等手段分析数据。针对不同的研究需要,越来越多的新方法、新工具产生出来:

    例如,以元胞自动机为代表的生命体建模技术、以马尔可夫链蒙特卡罗(MCMC)算法为代表的计算机仿真模拟技术等等。

    本期介绍使用爬虫技术抓取网页,及对获取的网页文本数据做后续分析的实战案例。我将以网友对《流浪地球》豆瓣影评文本的获取与分析全过程,作为演示案例。

    文本挖掘的本质是,通过自然语言处理(Natural Language Processing,NLP)和分析方法,将文本转化为数据进行分析。因此,阅读本文,需要一定的知识基础,包括网页设计、自然语言处理方法,我会在文中适当补充。

    ➡ 1.准备工作

    分析工作之前,需要为软件配置工作环境,包括设置工作目录、调用需要的程序包等等。采集到的文本数据、各类词典、输出结果等等都会保存在工作目录中;外部程序包在首次使用前需要安装。

    ### 准备工作# 设置工作目录setwd('D:/The Wandering Earth')# 加载所需程序包library('rvest')library('stringr')library('jiebaRD')library('jiebaR')library('plyr')library('rJava')library('tm')library('tmcn')library('proxy')library('topicmodels')library('sqldf')library('wordcloud2')

    ➡ 2.网页抓取

    我依然按照定量分析的传统套路,将分析全过程分为数据收集与数据分析两部分。第一步,即通过爬虫技术抓取网页。

    网络爬虫(webcrawler),也称网络蜘蛛(spider),是一种用自动浏览万维网的网络机器人。其目的一般为编纂网络索引。爬虫访问网站的过程会消耗目标系统资源,不少网络系统并不默许爬虫工作。因此在访问大量页面时,爬虫需要考虑到规划、负载,还需要讲“礼貌”。不愿意被爬虫访问、被爬虫主人知晓的公开站点可以使用robots.txt文件等方法避免访问。

    例如,豆瓣电影()的robots.txt规定如下:

    User-agent: *Disallow: /subject_searchDisallow: /amazon_searchDisallow: /searchDisallow: /group/searchDisallow: /event/searchDisallow: /celebrities/searchDisallow: /location/drama/searchDisallow: /forum/Disallow: /new_subjectDisallow: /service/iframeDisallow: /j/Disallow: /link2/Disallow: /recommend/Disallow: /doubanapp/cardDisallow: /update/topic/Sitemap: https://www.douban.com/sitemap_index.xmlSitemap: https://www.douban.com/sitemap_updated_index.xml# Crawl-delay: 5
    User-agent: Wandoujia SpiderDisallow: /

    在实际应用中,网络爬虫技术没有特别复杂。许多情况下,我们往往指定网站及抓取内容,更倾向于网页采集而非网络爬虫。在此之前,我希望读者了解网页源代码的有关知识,特别是标记语言(HTML,只有语法,没有变量和逻辑)、层叠样式表(CSS,用于控制元素的展现形式)、脚本语言(JavaScript,操作HTML中元素的增删改)在网页设计中的作用。

    另外,当网页出现较复杂的展现形式时,例如,网址分页、超链接、异步加载等等,需要读者具备更多的理论知识。

    ### 网页采集# 观察网址规律index <- c(0,20,40,60,80,100,120,140,160,180,200,220)# 批量爬取好评数据comments <- data.frame()for (i in index){# 读取网址  url = paste("https://movie.douban.com/subject/26266893/comments?start=",i,"&limit=20&sort=new_score&status=P&percent_type=h",sep="")  web <-read_html(url)# 爬取豆瓣好评  words <- web%>%html_nodes('#comments p')%>%html_text()# 创建数据框存储以上信息  comments_data <- data.frame(words)  comments <- rbind(comments,comments_data) }# 把豆瓣好评保存为CSV文件write.csv (comments,file="好评.csv",row.names=FALSE)

    以上是本期抓取网页文本数据的代码。我抓取了220条豆瓣电影网站上,网友对《流浪地球》的好评文本,保存为“好评.csv”文件。HTTP error 403报错不影响结果,意思是从R中进入网页被识别为爬虫,拒绝访问更多如何设置网页关键词,受限制不能抓取全部评论:

    图1:豆瓣电影网站截图

    图2:抓取的220条评论文本数据截图

    ➡ 3.中文分词

    中文自动分词,指的是使用计算机自动对中文文本进行词语的切分,即像英文那样使得中文句子中的词之间有空格以标识。中文自动分词被认为是中文自然语言处理中的一个最基本的环节。

    许多教材以英文文本为教学案例,分词使用的程序包与处理中文文本时不同,读者在自学时需要注意。

    ### 中文分词# 获取当前工作目录getwd()# 设置用户自定义词典及停用词表engine <- worker(user="dictionary.txt", stop_word="ChineseStopWords.txt")# 导入好评文本good <- read.csv(file.choose())names(good)nchar(good)# 文本预处理good_res= good[good!=" "]ls()fix(good_res)# 好评文本分词good_segwords <- sapply(good_res, segment, engine)fix(good_segwords)# 删除停用词表没有过滤掉的词filter<-c("30","分钟","令人","一部","认为","更是","之处","非常","不到","b","没有")filter_segment(good_segwords, filter)fix(good_segwords)

    特别注意,用户自定义词典及停用词表,需要放置在工作路径下,且以UTF-8编码格式的txt文本文件保存。习惯上,第一行可以空出:

    图3:我的用户自定义词典及停用词表截图

    用户自定义词典是防止固定词汇被拆开,例如,如果不设置自定义词典,“漫游太空2001”就会被拆分为“漫游”、“太空”、“2001”三个词语;“韩朵朵”就会被拆分为“韩”、“朵朵”两个词语;这会给我们的后续分析带来麻烦。

    R从网页抓取到文本分析全教程:影评的获取与分析

    过滤停用词表,是将中文文本中,我们不需要的虚词等等删掉,例如,“啊”、“呀”、“吗”等单字,“应该”、“都是”等无关紧要的词,英文字母,标点符号及阿拉伯数字等等。

    对不同的研究问题,用户自定义词典及停用词表,不是每次分析都一样的,需要我们根据不同问题的需要,不断地调整和修改。下面是使用用户自定义词典及停用词表后,部分文本的分词效果:

    图4:部分文本分词效果截图

    ➡ 4.文档矩阵

    利用文档-词频矩阵(document-term matrix,DTM),可以实现文本数据的结构化。DTM矩阵转置后即为TDM,DTM矩阵的形式是,矩阵的行代表文档,列代表词汇,矩阵元素即为文档中某一词汇出现的次数。

    特别注意:需要先用Excel打开“好评.csv”文件,通过“审阅-繁转简”将所有繁体字转换为简体字,否则构建文档矩阵时会报错;构建文档-词频矩阵,是进行后续分析的基础:

    ### 文档矩阵# 创建好评文本的DTM文件good_corpus <- VCorpus(VectorSource(good_segwords))inspect(good_corpus[1:10])good_corpus<- tm_map(good_corpus, removeWords, stopwordsCN())ctrl<- list(removePunctuation = TRUE, removeNumbers= TRUE, wordLengths = c(1, Inf), stopwords = stopwordsCN(), wordLengths = c(2, Inf))good_dtm<- DocumentTermMatrix(good_corpus, control = ctrl)inspect(good_dtm[1:10, 110:112])good_dtm

    ➡ 5.词频共现

    共现分析利用词汇共同出现的情况,定量地研究文本关系。由此,统计一组词汇两两之间在同一文本中出现的频率,便可形成一个由这些词对关联所组成的共词网络,网络内节点之间的远近便可反映内容的亲疏关系。

    ### 词频共现# 以“硬核科幻”一词0.5关系及以上为例findAssocs(good_dtm, "硬核科幻", 0.5)

    我以与“硬核科幻”一词0.5关系及以上的词汇结果为例,发现“硬核科幻”一词与情节、瑰丽、热血、社会秩序、低成本、完成度、圆满、全人类等词共现关系较强:

    $硬核科幻    情节    低成本    第一次    瑰丽    借鉴     奇伟     热血   人类学   设想     社会秩序    0.94    0.87       0.87        0.87    0.87     0.87     0.87     0.87     0.87     0.87     想不到   新起点 烟花爆竹  印象   预告片     圆满     灾难  完成度   世界    全人类    0.87    0.87       0.87        0.87    0.87     0.87     0.85     0.71     0.57     0.55

    ➡ 6.文本聚类

    聚类分析是研究分类问题的一种统计分析方法,同时也是数据挖掘的重要算法。聚类(Cluster)分析是由若干模式(Pattern)组成的,通常,模式是一个度量(Measurement)的向量,或者是多维空间中的一个点。聚类分析以相似性为基础,在一个聚类中的模式之间比不在同一聚类中的模式之间具有更多的相似性。

    ### 文本聚类# 删除稀疏矩阵good_dtm_sub <- removeSparseTerms(good_dtm, 0.99)dim(good_dtm_sub)# 好评文本聚类good_dist <- proxy:: dist(as.matrix(good_dtm),method='cosine')heatmap(as.matrix(good_dist),labRow=FALSE, labCol=FALSE)good_clust <- hclust(good_dist)plot(good_clust)result1<- cutree(good_clust,k=5)result2<- cutree(good_clust,k=10)summary(result1)summary(result2)result1result2plot(good_clust)

    稀疏矩阵对于分类预测的系统效率和预测准确率有着负面的影响,因此需要对该词频矩阵进行降维处理,删除稀疏词条。

    以上使用余弦相似度算法。通过测量两个向量夹角的余弦值,度量它们之间的相似性。0度角的余弦值是1,而其他任何角度的余弦值都不大于1;并且其最小值是-1;从而两个向量之间的角度的余弦值确定两个向量是否大致指向相同的方向。

    结果是与向量的长度无关的,仅仅与向量的指向方向相关。余弦相似度通常用于正空间,因此给出的值为0到1之间。例如在信息检索中,每个词项被赋予不同的维度,而一个文档由一个向量表示,其各个维度上的值对应于该词项在文档中出现的频率。余弦相似度因此可以给出两篇文档在其主题方面的相似度。

    我分别使用k=5及k=10时的结果做比较,220条评论数量之多,使树状图略显杂乱,不过聚类报告十分清楚,下图即为k=5时,220条评论文本的聚类结果:

    图5:k=5时,220条评论文本的聚类结果

    ➡ 7.主题建模

    主题模型(Topic Model)在机器学习和自然语言处理等领域,用来在一系列文档中发现抽象主题的一种统计模型。直观来讲,如果一篇文章有一个中心思想,那么一些特定词语会更频繁的出现。比方说,如果一篇文章是在讲狗的,那“狗”和“骨头”等词出现的频率会高些;如果一篇文章是在讲猫的,那“猫”和“鱼”等词出现的频率会高些。而有些词例如“这个”、“和”大概在两篇文章中出现的频率会大致相等。

    但真实的情况是,一篇文章通常包含多种主题,而且每个主题所占比例各不相同。因此,如果一篇文章10%和猫有关,90%和狗有关,那么和狗相关的关键字出现的次数大概会是和猫相关的关键字出现次数的9倍。一个主题模型试图用数学框架来体现文档的这种特点。主题模型自动分析每个文档,统计文档内的词语,根据统计的信息来断定当前文档含有哪些主题,以及每个主题所占的比例各为多少。

    ### 主题建模# 以三个主题为例good_ctm<- CTM(good_dtm,k=3, control=list(seed=111))Terms<- terms(good_ctm, 7)Terms[,1:3]

    以上人为设定3个主题,并报告各自7个代表词。主题反映的实际意义,需要通过代表词解释:

         Topic 1  Topic 2 Topic 3[1,] "中国"   "华语"  "科幻"[2,] "科幻"   "地球"  "中国"[3,] "硬科幻" "希望"  "故事"[4,] "地球"   "电影"  "电影"[5,] "特效"   "故事"  "人类"[6,] "电影"   "国产"  "原著"[7,] "影片"   "人类"  "流浪地球"

    ➡ 8.情感分析

    文本情感分析,也称为意见挖掘,是指用自然语言处理、文本挖掘以及计算机语言学等方法来识别和提取原素材中的主观信息。

    通常来说,情感分析的目的是为了找出说话者/作者在某些话题上或者针对一个文本两极的观点的态度。这个态度或许是他或她的个人判断或是评估,也许是他当时的情感状态(就是说,作者在做出这个言论时的情绪状态),或是作者有意向的情感交流(就是作者想要读者所体验的情绪)。

    文本情感分析的一个基本步骤是对文本中的某段已知文字的两极性进行分类,这个分类可能是在句子级、功能级。分类的作用就是判断出此文字中表述的观点是积极的、消极的、还是中性的情绪。更高级的“超出两极性”的情感分析还会寻找更复杂的情绪状态,比如“生气”、“悲伤”、“快乐”等等:

    ### 情感分析# 读入正负面词库及停止词pos <- readLines(file.choose(), encoding = 'UTF-8')neg <- readLines(file.choose(), encoding = 'UTF-8')# 合并情感词库dict <- c(pos, neg)# 自定义情感类型得分函数fun <- function( x, y) x%in% ygetEmotionalType <- function( x,pwords,nwords){  pos.weight = sapply(llply( x,fun,pwords),sum)  neg.weight = sapply(llply( x,fun,nwords),sum)  total = pos.weight - neg.weightreturn(data.frame( pos.weight, neg.weight, total))}# 计算好评的每条评论的正负得分good_score <- getEmotionalType(good_segwords, pos, neg)# 将原始数据与得分数据进行合并good_evalu_score <- cbind(good, good_score)# 为给每个评论打上正负情感标签,总得分大于等于0设置为正面情感,小于0设置为负面情感good_evalu_score <- transform(good_evalu_score, emotion = ifelse(total>= 0, 'Pos', 'Neg'))# 把好评情感保存为CSV文件write.csv (good_evalu_score,file="好评情感.csv",row.names=FALSE)

    现有的文本情感分析的途径大致可以集合成四类:关键词识别、词汇关联、统计方法和概念级技术。工具包括机器学习、情感词典等方法,这里使用基于词典的情感分析方法,我已把常用的中文情感词典放进下载资源中,关注“阿虎定量笔记”公众号,后台回复“情感词典”即可获得:

    图6:常用中文情感词典资源

    特别有趣的是,在众多乐观评价中,一条得分为-3分的悲观评价很有趣:“一个悲伤的故事:太阳都要毁灭,地球都要流浪了,我国的校服还是这么丑......”如何设置网页关键词,哈哈哈哈哈哈:

    图7:220条评论的情感分析结果部分截图

    ➡ 9.词频统计

    词频(term frequency,TF)指的是某一个给定的词语在该文件中出现的频率。

    ### 词频词云# 计算好评文本的词频good_segwords <- sapply(good_res, segment, engine)good_df <- unlist(good_segwords)good_df <- as.data.frame(table(good_df))good_df <- arrange(good_df, desc(Freq))# 把好评词频保存为CSV文件write.csv (good_df,file="好评词频.csv",row.names=FALSE)

    下面是220条评论中,排名前20的词汇与词频:

    图8:220条评论的词频统计结果部分截图

    ➡ 10.绘制词云

    词云(Word Cloud),又称文字云,是文本数据的视觉表示,由词汇组成类似云的彩色图形,用于展示大量文本数据。通常用于描述网站上的关键字元数据(标签),或可视化自由格式文本。每个词的重要性以字体大小或颜色显示。词云常用来快速感知最突出的文字:

    # 绘制词云wordcloud2(good_df)

    版权声明

    本文仅代表作者观点。
    本文系作者授权发表,未经许可,不得转载。

    发表评论