疫情下的家庭关系|《请回答1988》影评爬取
本文作者:张馨月
文字编辑:朱巧利
导读
一场疫情将我们困在了家中,对很多人来说,这都是在外求学工作多年后与家人相处最久的时间,四个多月过去,我们与家人的相处从疫情初期的彼此相守转变成现在“靠洗碗维持的亲情”,这段意外获得的与家人24h相处的时光,也让我们对自己与亲情有了新的理解。虽然家中有父母的嫌弃唠叨和亲戚突然的关心,但这里依然是我们最为依赖、最不可割舍的地方。在与家庭相关的众多影视作品中,最深受大家喜爱的作品之一便是《请回答1988》,双门洞的故事倒映着我们的生活,也让当下平常的日子显得更为珍贵。今天我们就用Stata来分析一下关于这部剧,豆瓣网友都留下了哪些内容~
本文主要介绍的内容如下:
1.豆瓣影评内容爬取
2.影评内容分析(数据统计与文本分析)
1.影评内容爬取
豆瓣影评的获取需要进行两层爬虫,第一层对所有页面遍历,获取每位用户影评的标题与链接,第二层对链接进行抓取,并提取出需要的内容。在之前的推文《少年的你影评》当中,我们介绍了爬取的详细过程并主要使用了命令split进行提取,今天的介绍将采取类似的思路,并使用正则表达式来提取关键内容。
copy "https://movie.douban.com/subject/26302614/reviews?start=10" temp.txt,replace
infix strL v 1-100000 using temp.txt, clear
观察源代码,可以发现影评的标题与链接都在标签</a></h2>所在行中:
因此,我们先使用ustrregexm()匹配</a></h2>所在的行,再用ustrregexs() 提取href=””中的链接,最后使用ustrregexra()将<>中的内容替换为空,便可得到标题。过程如下:
keep if ustrregexm(v,`"</a></h2>"')
gen url=ustrregexs(1) if ustrregexm(v,`"<a href="(.*)">"')
replace v=ustrregexra(v,"<.*?>","")
rename v title
对于所有页面的抓取,需要先从第一页的源代码中提取总页数,再遍历所有页面进行提取,并将每一页的内容进行合并。代码如下:
copy "https://movie.douban.com/subject/26302614/reviews?start=10" temp.txt,replace
infix strL v 1-100000 using temp.txt, clear
*提取页码
keep if index(v,`"<span class="thispage" data-total-page="')
replace v=ustrregexs(0) if ustrregexm(v,"(\d+)") //共有多少页评论
local p=v[1]
*第一层爬取:对页码循环
forvalues i=1/`p'{
local j=(`i'-1)*20 //定义评论对应的数字编码
cap copy "https://movie.douban.com/subject/26302614/reviews?start=`j'" temp.txt,replace
while _rc!=0{
cap copy "https://movie.douban.com/subject/26302614/reviews?start=`j'" temp.txt,replace
}
infix strL v 1-10000 using temp.txt,clear
keep if ustrregexm(v,`"</a></h2>"')
gen url=ustrregexs(1) if ustrregexm(v,`"<a href="(.*)">"')
replace v=ustrregexra(v,"<.*?>","")
rename v title
save "影评_`i'",replace
}
*合并文件
clear
local files:dir "." file "影评*.dta"
foreach file in `files'{
append using "`file'" //把上面生成的影评i.dta合并起来
}
drop if url==""
save "影评.dta",replace
接下来,我们使用fileread()对每一个url进行抓取,按照与上述类似的思路,从中提取出影评的内容、评分和点赞数:
*第二层爬取:抓取影评所在网页
gen v=""
forvalues i=1/`=_N'{
sleep 100
replace v=fileread(url) in `i'
while filereaderror(v[`i'])!=0 {
sleep 5000 //休息5000毫秒
replace v=fileread(url) in `i'
}
dis `i'
}
gen score=ustrregexs(1) if ustrregexm(v,"allstar([0-9]{2})") //提取评分
destring score,replace
replace score=score/10
gen like=ustrregexs(1) if ustrregexm(v,`" data-ad-ext="有用(\d+)"') //提取点赞数
destring like,replace
gsort -like
split v,p(`"<div id="link-report">"' `"<div class="main-author">"')
replace v2 = ustrregexra(v2,"\s","",.)
replace v2 = ustrregexra(v2, "<.*?>", "",.)
replace v2=ustrregexra(v2," |-|;","")
rename v2 content
keep title score like content
save "影评.dta",replace
2.内容分析
《请回答1988》在豆瓣的评分高达9.7,小编也对撰写影评的用户评分进行了统计,结果显示给这部剧打出5星好评的用户占比高达87.86%,而1分评级的占比仅为0.6%:
对于饼状图的绘制,我们先用collapse命令分组统计并对数据进行处理,再用graph pie输出图像,相关命令的介绍可以参考推文《利用collapse命令转化原始数据》《客官,来个饼图!》。
use 影评.dta,clear
collapse (count) like,by(score) //分组统计评分数量
drop if score==.
egen total=sum(like) //计算评分的总数
gen fre=like/total
grstyle init //初始化图形设置
grstyle set plain //去掉图形背景色
graph pie fre ,over(score) pie(5,explode color(navy *0.8)) plabel(5 percent ,size(*2) color(white))
接下来,通过Stata与Python的交互实现对影评的分词处理,由于影评的内容通常较长,包括形容词、名词等多种词性,因此我们使用jieba.posseg来分词以获取每个词语的词性。(关于词频统计代码的详细介绍,可以参考推文《高亮输出之唐诗作者》):
*分词处理
*导出为txt文档
use 影评.dta,clear
keep content
export delimited using content.txt,replace
*调用Python分词
clear all
python
import jieba.posseg
word=[]
with open(r"content.txt",encoding="utf8") as f:
for i in f.readlines():
str=i
word.append(str)
jieba.load_userdict(r"tsdict.txt") #添加自定义词典
with open("分词.txt","w",encoding="utf8") as f2:
for unit in word:
seg_list = jieba.posseg.cut(unit)
for word in seg_list:
f2.write(word.word+" "+word.flag+"\n")
end
*分词结果导入Stata,并删除单字、缺失值、停用词
import delimited using 分词.txt, clear encoding("utf-8")
split v1,p(" ")
drop v1
rename (v11 v12) (keyword flag)
drop if ustrlen(keyword) == 1 // 删除单字
drop if keyword =="" //删除缺失值
preserve
import delimited using 停用词表.txt, clear ///
encoding("utf-8") varname(nonames)
outsheet using 停用词表.txt, replace nonames noquote
levelsof v1, local(keyword)
restore
foreach word in `keyword' {
drop if keyword == "`word'" //删除停用词
}
*词频统计
bysort keyword: gen frequency = _N
gsort -frequency
duplicates drop
save word,replace
在《请回答1988》中有许多深入人心的角色,比如善良又美丽的德善、天才围棋少年阿泽、沉默的正焕、人生导师娃娃鱼等等,小编从分词结果中保留了几位主人公的名字,可以看到这些角色都被提及了非常多次:
上图绘制的代码如下:
keep if ustrregexm(keyword, "宝拉|德善|正焕|善宇|阿泽|正峰|娃娃鱼|珍珠")
save name,replace
keep in 1/8
sencode keyword,gen(name) gsort(-frequency)
twoway bar frequency name , barwidth(0.5) xlab(1(1)8,valuelabel angle(0) labsize(*0.7)) ylabel(1000(5000)35000,angle(0) labsize(*0.5)) ytitle("") xtitle("")
use word,clear
keep if ustrregexm(flag, "^[anv]")
keep in 1/100
wordcloud keyword frequency using 词云.html, replace size(15 80) range(3840 2160)
shellout 词云.html
微信公众号“Stata and Python数据分析”分享实用的stata、python等软件的数据处理知识,欢迎转载、打赏。我们是由李春涛教授领导下的研究生及本科生组成的大数据处理和分析团队。
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿+推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到有关数据处理、分析等问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。