基于豆瓣影评数据的完整文本分析
?
作者:沂水寒城,CSDN博客專家,個(gè)人研究方向:機(jī)器學(xué)習(xí)、深度學(xué)習(xí)、NLP、CV
Blog:?http://yishuihancheng.blog.csdn.net
文本分析中很多的工作都是基于評(píng)論數(shù)據(jù)來(lái)進(jìn)行的,比如:滴滴出行的評(píng)價(jià)數(shù)據(jù)、租房的評(píng)價(jià)數(shù)據(jù)、電影的評(píng)論數(shù)據(jù)等等,從這些預(yù)料數(shù)據(jù)中能夠挖掘出來(lái)客戶群體對(duì)于某種事物或者事情的看法,較為常見(jiàn)的工作有:輿情分析、熱點(diǎn)挖掘和情感分析。
在之前的工作經(jīng)歷中,我對(duì)微博數(shù)據(jù)和電影評(píng)論數(shù)據(jù)進(jìn)行文本分析工作較多,今天的文章主要就是想以影評(píng)數(shù)據(jù)為切入點(diǎn)介紹一些自己文本分析的流程和方法,本文簡(jiǎn)單的實(shí)現(xiàn)流程如下圖所示:
主要分為:數(shù)據(jù)采集、數(shù)據(jù)清洗存儲(chǔ)、主題挖掘、分詞與詞頻統(tǒng)計(jì)、詞云展示幾個(gè)部分。
一、影評(píng)數(shù)據(jù)采集
影評(píng)數(shù)據(jù)有很多網(wǎng)站可以去獲取,比如最常用的貓眼電影、豆瓣電影等等,本文是基于豆瓣電影完成的數(shù)據(jù)采集工作,這個(gè)具體的采集項(xiàng)目網(wǎng)上都有很多詳細(xì)的講解與實(shí)現(xiàn),這里我就不再對(duì)采集過(guò)程進(jìn)行過(guò)多的介紹,直接看代碼實(shí)現(xiàn)。
首選需要實(shí)現(xiàn)對(duì)于給定電影名稱獲取到其對(duì)應(yīng)的id功能,因?yàn)樵跀?shù)據(jù)中電影數(shù)據(jù)項(xiàng)都是以id作為標(biāo)識(shí)的,這里的代碼實(shí)現(xiàn)很簡(jiǎn)單,主要是就是需要找到具體請(qǐng)求的API即可:
1.def?getIMDBIdByName(name='勇敢的心',save_path='id_title.txt'):?? 2.????'''''? 3.????基于劇名查詢獲取?id? 4.????'''?? 5.????url="https://movie.douban.com/j/subject_suggest?q="+urllib.quote(name)?? 6.????data=getJsonData(url)?? 7.????if?data:?? 8.????????id_list=[one['id']?for?one?in?data]?? 9.????????title_list=[one['title']?for?one?in?data]?? 10.????????with?open(save_path,'a')?as?f:?? 11.????????????for?i?in?range(len(id_list)):?? 12.????????????????f.write(','.join([id_list[i],title_list[i]]).strip()+'\n')??獲取到的電影id會(huì)存儲(chǔ)在我們默認(rèn)的文件id_title.txt中,之后影評(píng)數(shù)據(jù)的獲取會(huì)從這里讀取數(shù)據(jù)來(lái)構(gòu)建映射字典。
完成上述功能后我們就可以對(duì)給定名稱的電影獲取其對(duì)應(yīng)的影評(píng)數(shù)據(jù)了,這里給出來(lái)樣例爬蟲(chóng)代碼的具體實(shí)現(xiàn):
1.def?demoSpider(movie_id='12345689',offset=0):?? 2.????'''''? 3.????爬蟲(chóng)數(shù)據(jù)展示? 4.????'''?? 5.????res_list=[]?? 6.????url="https://movie.douban.com/subject/{0}/comments?start={1}&limit=20&sort=new_score&status=P".format(movie_id,str(offset))?? 7.????header,proxy=buildProxy()?? 8.????res=getPageHtml(url,header,proxy,flag=True,num_retries=3)?? 9.????soup=BeautifulSoup(res.content,'html5lib')?? 10.????div_comment=soup.find_all('div',class_='comment-item')??? 11.????for?one?in?div_comment:?? 12.????????username=one.find('div',class_='avatar').a['title']?? 13.????????comment_time=one.find('span',class_='comment-time')['title']?? 14.????????votes=one.find('span',class_='votes').get_text()?? 15.????????comment=one.p.get_text()?? 16.????????one_list=[username.strip(),comment_time.strip(),votes.strip(),comment.strip()]?? 17.????????print?one_list?? 18.????????res_list.append(one_list)?? 19.????????offset+=20?? 20.????????time.sleep(random.randint(3,8))?? 21.????????url="https://movie.douban.com/subject/{0}/comments?start={1}&limit=20&sort=new_score&status=P".format(movie_id,str(offset))?? 22.????????header,proxy=buildProxy()?? 23.????????res=getPageHtml(url,header,proxy,flag=True,num_retries=3)?? 24.????????soup=BeautifulSoup(res.content,'html5lib')?? 25.????????div_comment=soup.find_all('div',class_='comment-item')??? 26.????????for?one?in?div_comment:?? 27.????????????username=one.find('div',class_='avatar').a['title']?? 28.????????????comment_time=one.find('span',class_='comment-time')['title']?? 29.????????????votes=one.find('span',class_='votes').get_text()?? 30.????????????comment=one.p.get_text()?? 31.????????????one_list=[username.strip(),comment_time.strip(),votes.strip(),comment.strip()]?? 32.????????????res_list.append(one_list)?? 33.????return?res_list??仔細(xì)看上述代碼會(huì)發(fā)現(xiàn),這里的實(shí)現(xiàn)是非常簡(jiǎn)單的,我們的翻頁(yè)操作是基于網(wǎng)頁(yè)的offset偏移量來(lái)間接完成的。上述代碼實(shí)現(xiàn)了指定電影評(píng)論數(shù)據(jù)的采集工作。
如果在實(shí)際應(yīng)用中出現(xiàn)大量數(shù)據(jù)采集工作的話需要考慮一些網(wǎng)站的反爬蟲(chóng)機(jī)制,這里我較為常用的三種反反爬蟲(chóng)機(jī)制主要包括:隨機(jī)休眠機(jī)制、隨機(jī)User-Agent偽裝機(jī)制和動(dòng)態(tài)IP代理池構(gòu)建機(jī)制,如果對(duì)這方面感興趣的話可以閱讀我的頭條號(hào)系列文章,搜索《反反爬蟲(chóng)機(jī)制三重奏》即可,這里我基于代碼實(shí)現(xiàn)了隨機(jī)UA和代理池的功能,具體不多解釋了,直接看代碼實(shí)現(xiàn)即可:
1.def?buildProxy():?? 2.????'''''? 3.????構(gòu)建代理信息? 4.????'''?? 5.????header_list=generateRandomUA(num=500)?? 6.????header={'User-Agent':random.choice(header_list)}?? 7.????ip_proxy=random.choice(ip_list)?? 8.????one_type,one_ip,one_port=ip_proxy[0],ip_proxy[1],ip_proxy[2]?? 9.????proxy={one_type:one_type+'://'+one_ip+':'+one_port}?? 10.????return?header,proxy??二、影評(píng)數(shù)據(jù)清洗存儲(chǔ)
完成第一部分的工作后,我們就采集到了所需的評(píng)論數(shù)據(jù),但是這里的評(píng)論數(shù)據(jù)難以直接用于分析工作,我們需要對(duì)其進(jìn)行解析處理后,對(duì)所需的評(píng)論文本數(shù)據(jù)進(jìn)行清洗后才能夠使用,這里簡(jiǎn)單對(duì)相關(guān)的工作進(jìn)行說(shuō)明。
我們隨便打開(kāi)一部電影《紅海行動(dòng)》的影評(píng)數(shù)據(jù)文件,找出前3條評(píng)論數(shù)據(jù)樣例如下所示:
1.評(píng)論人:夢(mèng)夢(mèng)夢(mèng)夢(mèng)?? 2.評(píng)論時(shí)間:2018-02-16?00:05:42?? 3.支持人數(shù):14673 ? 4.評(píng)論內(nèi)容:本來(lái)對(duì)這類電影不感興趣,陪著男朋友去看的,很意外,還不錯(cuò),一部很燃的片子,倆個(gè)多小時(shí)的電影,至少一個(gè)半小時(shí)的高潮,全程無(wú)尿點(diǎn),據(jù)說(shuō)是根據(jù)真實(shí)事件改編的,海陸空作戰(zhàn),超級(jí)帥。算是春節(jié)檔電影的一股清流,大家真的要感受一下中國(guó)軍人的風(fēng)采,只想說(shuō)威武!!佟莉炸飛機(jī)還有狙擊手對(duì)戰(zhàn)那段太帥了?? 5.評(píng)論人:烏鴉火堂?? 6.評(píng)論時(shí)間:2018-02-13?15:35:16?? 7.支持人數(shù):10557 ? 8.評(píng)論內(nèi)容:春節(jié)檔最好!最好不是戰(zhàn)狼而是戰(zhàn)爭(zhēng),有點(diǎn)類似黑鷹墜落,主旋律色彩下,真實(shí)又殘酷的戰(zhàn)爭(zhēng)渲染。故事性不強(qiáng),文戲不超20分鐘,從頭打到尾,林超賢場(chǎng)面調(diào)度極佳,巷戰(zhàn)、偷襲、突擊有條不紊,軍械武器展示效果不錯(cuò)。尺度超大,鋼鋸嶺式血肉橫飛,還給你看特寫(xiě)!敵人如喪尸一般打不完,雙方的狙擊手都是亮點(diǎn)?? 9.評(píng)論人:sylvia曉霄小小?? 10.評(píng)論時(shí)間:2018-02-11?00:11:02?? 11.支持人數(shù):7839 ? 12.評(píng)論內(nèi)容:超前點(diǎn)映場(chǎng)。場(chǎng)面真實(shí),劇情緊湊。中間其實(shí)很想上廁所,但是愣是沒(méi)有找到任何尿點(diǎn)…作為戰(zhàn)爭(zhēng)片,已超額完成任務(wù),在真實(shí)度還原上,達(dá)到了國(guó)產(chǎn)影片從未有過(guò)的高度。細(xì)節(jié)處理也很妙,剝糖紙的那一段看的揪心。被海清和蔣璐霞的演技圈粉…看到最后,感覺(jué)自己整個(gè)人都在燃燒。準(zhǔn)備春節(jié)的時(shí)候帶著爸媽二刷。?? 13.評(píng)論人:華盛頓櫻桃樹(shù)?? 14.評(píng)論時(shí)間:2018-02-06?00:06:34?? 15.支持人數(shù):10171 ? 16.評(píng)論內(nèi)容:國(guó)產(chǎn)類型片的里程碑,2個(gè)多小時(shí)節(jié)奏全程緊繃清晰,真熱血真刺激。敘事,人物,情感,動(dòng)作,制作都幾乎無(wú)可挑剔。該有的都有,演員群像都比想象中出色,但最出色的還是導(dǎo)演。這個(gè)格局,超越某狼N倍。??分析發(fā)現(xiàn):對(duì)于單條影評(píng)數(shù)據(jù)主要包含:評(píng)論人、評(píng)論時(shí)間、支持人數(shù)和評(píng)論內(nèi)容四部分,我們需要的是評(píng)論內(nèi)容,這里需要對(duì)原始獲取到數(shù)據(jù)進(jìn)行解析,具體實(shí)現(xiàn)如下:
1.def?singeCommentParse(data='comments/1291546.txt',save_path='handle/1291546.json'):?? 2.????'''''? 3.????單個(gè)影評(píng)數(shù)據(jù)的解析處理? 4. ???數(shù)據(jù)樣式:? 5. ???評(píng)論人:phoebe 6. ???評(píng)論時(shí)間:2007-11-21 20:38:33 7. ???支持人數(shù):22660? 8. ???評(píng)論內(nèi)容:陳凱歌可以靠它吃兩輩子飯了,現(xiàn)在看來(lái)江郎才盡也情有可原? 9.????'''?? 10.????with?open(data)?as?f:?? 11.????????data_list=[one.strip()?for?one?in?f.readlines()?if?one]?? 12.????comment_list=cutList(data_list,c=4)?? 13.????res_list=[]?? 14.????for?i?in?range(len(comment_list)):?? 15.????????one_list=comment_list[i]?? 16.????????try:?? 17.????????????one_dict={}?? 18.????????????one_dict['person'],one_dict['timestamp'],one_dict['number'],one_dict['content']='N','N','N','N'?? 19.????????????for?one?in?one_list:?? 20.????????????????if?one.startswith('評(píng)論人'):?? 21.????????????????????one_dict['person']=one.split(':')[-1].strip()?? 22.????????????????elif?one.startswith('評(píng)論時(shí)間'):?? 23.????????????????????one_dict['timestamp']=one.split(':')[-1].strip()?? 24.????????????????elif?one.startswith('支持人數(shù)'):?? 25.????????????????????one_dict['number']=one.split(':')[-1].strip()?? 26.????????????????elif?one.startswith('評(píng)論內(nèi)容'):?? 27.????????????????????one_dict['content']=one.split(':')[-1].strip()?? 28.????????????res_list.append(one_dict)?? 29.????????except:?? 30.????????????pass?? 31.????with?open(save_path,'wb')?as?f:?? 32.????????f.write(json.dumps(res_list))?? 33.?? 34.?? 35.def?allCommentsHandle(dataDir='comments/',saveDir='handle/'):?? 36.????'''''? 37.????對(duì)整個(gè)目錄下的影評(píng)數(shù)據(jù)全部處理? 38.????'''?? 39.????if?not?os.path.exists(saveDir):?? 40.????????os.makedirs(saveDir)?? 41.????txt_list=os.listdir(dataDir)?? 42.????for?one_txt?in?txt_list:?? 43.????????one_name=one_txt.split('.')[0].strip()?? 44.????????one_txt_path=dataDir+one_txt?? 45.????????one_json_path=saveDir+one_name+'.json'?? 46.????????singeCommentParse(data=one_txt_path,save_path=one_json_path)??上述代碼實(shí)現(xiàn)了對(duì)所有電源原始評(píng)論數(shù)據(jù)的解析處理,執(zhí)行后就得到了所需的評(píng)論內(nèi)容數(shù)據(jù)。
完成解析處理后需要對(duì)影評(píng)內(nèi)容數(shù)據(jù)進(jìn)行清洗,這里的清洗我主要是去除評(píng)論數(shù)據(jù)中的特殊字符等信息,具體實(shí)現(xiàn)如下:
1.def?dataClean(one_line):?? 2.????'''''? 3.????去臟、去無(wú)效數(shù)據(jù)? 4.????'''?? 5.????with?open('stopwords.txt')?as?f:?? 6.????????stopwords_list=[one.strip()?for?one?in?f.readlines()?if?one]?? 7.????sigmod_list=[',','。','(',')','-','——','\n','“','”','*','#','《','》','、','[',']','(',')','-',?? 8.???????????????????'.','/','】','【','……','!','!',':',':','…','@','~@','~','「一」','「','」',?? 9.????????????????'?','"','?','~','_','?',';','◆','①','②','③','④','⑤','⑥','⑦','⑧','⑨','⑩',?? 10.????????????????'⑾','⑿','⒀','⒁','⒂','"','?','/','·','…','!!!','】','!',',',?? 11.????????????????'。','[',']','【','、','?','/^/^','/^','”',')','(','~','》','《','。。。',?? 12.????????????????'=','⑻','⑴','⑵','⑶','⑷','⑸','⑹','⑺','…','']?? 13.????for?one_sigmod?in?sigmod_list:?? 14.????????one_line=one_line.replace(one_sigmod,'')?? 15.????return?one_line??到這里文本數(shù)據(jù)的預(yù)處理工作就結(jié)束了,之后需要對(duì)數(shù)據(jù)進(jìn)行存儲(chǔ),這里我是直接將數(shù)據(jù)存儲(chǔ)到了MySQL數(shù)據(jù)庫(kù)中。
首先需要?jiǎng)?chuàng)建對(duì)應(yīng)的表,具體實(shí)現(xiàn)如下:
1.def?createTableMySQL(tablename='mytable'):?? 2.????'''''? 3.????創(chuàng)建表? 4.????'''?? 5.????conn=pymysql.connect(**mysql)?? 6.????cur=conn.cursor()???? 7.????try:?? 8.????????drop_sql="drop?table?if?exists?%s"?%?tablename?? 9.????????cur.execute()?? 10.????except?Exception,e:?? 11.????????print?'Drop?Exception:?',e?? 12.????try:?? 13.????????create_sql="""CREATE?TABLE?%s?(? 14.?????????????????????movieId?VARCHAR(50)?NOT?NULL,? 15.?????????????????????movieName?VARCHAR(50)?NOT?NULL,? 16.?????????????????????personName?VARCHAR(50)?NOT?NULL,? 17.?????????????????????supportNum?VARCHAR(50),? 18.?????????????????????content?VARCHAR(255),? 19.?????????????????????timePoint?VARCHAR(50)?NOT?NULL,? 20.?????????????????????"""?%(table)?? 21.????????cur.execute(create_sql)?? 22.????????conn.commit()?? 23.????????cur.close()?? 24.????????conn.close()?? 25.????except?Exception,e:?? 26.????????print?'createTableMySQL?Exception:?',e??數(shù)據(jù)入庫(kù)操作實(shí)現(xiàn)如下:
到此就完成了影評(píng)數(shù)據(jù)的清洗與存儲(chǔ)工作!
三、LDA主題挖掘分析
這一部分主要是基于LDA主題挖掘模型來(lái)對(duì)處理好的影評(píng)數(shù)據(jù)進(jìn)行主題傾向性的分析挖掘工作。具體實(shí)現(xiàn)如下所示:
結(jié)果輸出如下:
1.{"蝶衣":?1,?"記得":?1,?"故事":?1,?"哥哥":?6,?"背景":?1,?"作品":?2,?"時(shí)代":?1,?"真的":?1,?"瘋魔":?1,?"女?huà)?#34;:?1,?"霸王":?1,?"說(shuō)好":?1,?"生活":?1,?"角色":?1,?"陳凱歌":?3,?"電影":?6,?"人生":?2,?"風(fēng)華絕代":?1,?"成活":?1,?"中國(guó)":?4,?"喜歡":?1,?"一年":?1,?"人物":?1,?"這部":?3,?"一輩子":?2,?"歷史":?2,?"時(shí)辰":?1,?"經(jīng)典":?3,?"看過(guò)":?1,?"感情":?1,?"導(dǎo)演":?1,?"程蝶衣":?6,?"真虞姬":?1,?"一部":?2,?"霸王別姬":?2,?"不算":?1,?"關(guān)注":?1,?"虞姬":?3,?"一個(gè)月":?1,?"永遠(yuǎn)":?1,?"張國(guó)榮":?5,?"一出":?1,?"巔峰":?1,?"之作":?1}??上述代碼中我們數(shù)據(jù)的數(shù)據(jù)是《霸王別姬》的評(píng)論數(shù)據(jù),輸出的是對(duì)應(yīng)的10個(gè)主題中主題詞的詞頻數(shù)據(jù)。基于詞云對(duì)其可視化結(jié)果如下所示:
接下來(lái)我們借助于主題可視化分析工具對(duì)其各個(gè)主題進(jìn)行展示如下所示:
Topic0:
Topic1:
Topic2:
Topic3:
這里僅展示出前4個(gè)主題的分布情況,借助于可視化工具來(lái)呈現(xiàn)主題還是一種不錯(cuò)的方式。
四、分詞與詞頻統(tǒng)計(jì)
這部分的工作主要是對(duì)原始的影評(píng)數(shù)據(jù)進(jìn)行分詞和詞頻統(tǒng)計(jì),相對(duì)來(lái)說(shuō)較為簡(jiǎn)單,就不多說(shuō)明了,直接看代碼實(shí)現(xiàn)即可:
1.def?singleCommentCut(data='1291546.json',word_path='1291546.txt',fre_path='1291546.json'):?? 2.????'''?? 3.????對(duì)單個(gè)影評(píng)數(shù)據(jù)清洗、分詞處理?? 4.????'''?? 5.????with?open(data)?as?f:?? 6.????????data_list=json.load(f)?? 7.????content=[]?? 8.????fre_dict={}?? 9.????for?one_dict?in?data_list:?? 10.????????one_clean=dataClean(one_dict['content'])?? 11.????????one_cut=seg(one_clean)?? 12.????????one_line='/'.join(one_cut)?? 13.????????content.append(one_line)?? 14.????????for?one?in?one_cut:?? 15.????????????if?one?in?fre_dict:?? 16.????????????????fre_dict[one]+=1?? 17.????????????else:?? 18.????????????????fre_dict[one]=1?? 19.????with?open(word_path,'w')?as?f:?? 20.????????for?one_line?in?content:?? 21.????????????f.write(one_line.strip()+'\n')?? 22.????with?open(fre_path,'w')?as?f:?? 23.????????f.write(json.dumps(fre_dict))??上述代碼實(shí)現(xiàn)了對(duì)輸入影評(píng)數(shù)據(jù)的分詞與詞頻統(tǒng)計(jì),并存儲(chǔ)到本地文件中。
五、詞云可視化分析
這里是本文的最后一個(gè)部分,主要是對(duì)前面幾章中計(jì)算處理得到的文本數(shù)據(jù)進(jìn)行可視化展示分析,對(duì)于文本數(shù)據(jù)的可視化我用的最多的也就是詞云了,簡(jiǎn)單看下具體的效果吧。
原始影評(píng)數(shù)據(jù)詞云可視化結(jié)果如下:
《我不是藥神》
《流浪地球》
《肖申克的救贖》
《紅海行動(dòng)》
主題挖掘詞云可視化分析結(jié)果如下:
《我不是藥神》
《流浪地球》
《肖申克的救贖》
《紅海行動(dòng)》
對(duì)于完整影評(píng)數(shù)據(jù)的可視化來(lái)說(shuō)更全面地展現(xiàn)出來(lái)了評(píng)論數(shù)據(jù)的信息,對(duì)于主題挖掘的可視化來(lái)說(shuō),突出了在廣大評(píng)論數(shù)據(jù)中的主題傾向性。
到這里本文的工作就結(jié)束了,很高興在自己溫習(xí)回顧知識(shí)的同時(shí)能寫(xiě)下點(diǎn)分享的東西出來(lái),如果說(shuō)您覺(jué)得我的內(nèi)容還可以或者是對(duì)您有所啟發(fā)、幫助,還希望得到您的鼓勵(lì)支持,謝謝!
贊 賞 作 者
Python中文社區(qū)作為一個(gè)去中心化的全球技術(shù)社區(qū),以成為全球20萬(wàn)Python中文開(kāi)發(fā)者的精神部落為愿景,目前覆蓋各大主流媒體和協(xié)作平臺(tái),與阿里、騰訊、百度、微軟、亞馬遜、開(kāi)源中國(guó)、CSDN等業(yè)界知名公司和技術(shù)社區(qū)建立了廣泛的聯(lián)系,擁有來(lái)自十多個(gè)國(guó)家和地區(qū)數(shù)萬(wàn)名登記會(huì)員,會(huì)員來(lái)自以工信部、清華大學(xué)、北京大學(xué)、北京郵電大學(xué)、中國(guó)人民銀行、中科院、中金、華為、BAT、谷歌、微軟等為代表的政府機(jī)關(guān)、科研單位、金融機(jī)構(gòu)以及海內(nèi)外知名公司,全平臺(tái)近20萬(wàn)開(kāi)發(fā)者關(guān)注。
▼ 點(diǎn)擊成為社區(qū)注冊(cè)會(huì)員? ? ? ? ??「在看」一下,一起PY!
總結(jié)
以上是生活随笔為你收集整理的基于豆瓣影评数据的完整文本分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Cortex、ARMv8、arm架构、A
- 下一篇: FCPX:快速时尚视频转场Stupid