❶ 怎樣避開豆瓣對爬蟲的封鎖,從而抓取豆瓣上電影內容
在互聯網中,有網路爬蟲的地方,絕對少不了反爬蟲的身影。網站反爬蟲的攔截前提是要正確區分人類訪問用戶和網路機器人,當發現可疑目標時,通過限制IP地址等措施阻止你繼續訪問。爬蟲該如何突破反爬蟲限制?
一、構建合理的HTTP請求頭
HTTP的請求頭是在你每次向網路伺服器發送請求時,傳遞的一組屬性和配置信息。由於瀏覽器和Python爬蟲發送的請求頭不同,有可能被反爬蟲檢測出來。
二、設置cookie的學問
Cookie是一把雙刃劍,有它不行,沒它更不行。網站會通過cookie跟蹤你的訪問過程,如果發現你有爬蟲行為會立刻中斷你的訪問,比如你特別快的填寫表單,或者短時間內瀏覽大量頁面。而正確地處理cookie,又可以避免很多採集問題,建議在採集網站過程中,檢查一下這些網站生成的cookie,然後想想哪一個是爬蟲需要處理的。
三、正常的時間訪問路徑
合理控制採集速度,是Python爬蟲不應該破壞的規則,盡量為每個頁面訪問時間增加一點兒間隔,可以有效幫助你避免反爬蟲。
四、使用http
對於分布式爬蟲和已經遭遇反爬蟲的人來說,使用http將成為你的首選。Ipidea分布地區廣,可滿足分布式爬蟲使用需要。支持api提取,對Python爬蟲來說再適合不過。
❷ 怎樣解析出HTML標簽中的數據,也就是說提取數據,我做了一個爬蟲,爬取豆瓣前250的電影。
用的是什麼語言?一般通用的可以用正則表達式解析,不過會麻煩一點。
如果用nodejs,可以用cheerio,類似jquery的用法。
❸ 豆瓣電影數據分析
這篇報告是我轉行數據分析後的第一篇報告,當時學完了Python,SQL,BI以為再做幾個項目就能找工作了,事實上……分析思維、業務,這兩者遠比工具重要的多。一個多月後回過頭來看,這篇報告雖然寫得有模有樣,但和數據分析報告還是有挺大差別的,主要原因在於:a.只是針對豆瓣電影數據分析太過寬泛了,具體關鍵指標到底是哪些呢?;b.沒有一個確切有效的分析模型/框架,會有種東一塊西一塊的拼接感。
即便有著這些缺點,我還是想把它掛上來,主要是因為:1.當做Pandas與爬蟲(Selenium+Request)練手,總得留下些證明;2.以豆瓣電影進行分析確實很難找到一條業務邏輯線支撐,總體上還是描述統計為主;3.比起網上能搜到的其他豆瓣電影數據分析,它更為詳細,可視化效果也不錯;
本篇報告旨在針對豆瓣電影1990-2020的電影數據進行分析,首先通過編寫Python網路爬蟲爬取了51375條電影數據,採集對象包括:電影名稱、年份、導演、演員、類型、出品國家、語言、時長、評分、評論數、不同評價佔比、網址。經過去重、清洗,最後得到29033條有效電影數據。根據電影評分、時長、地區、類型進行分析,描述了評分與時長、類型的關系,並統計了各個地區電影數量與評分。之後,針對演員、導演對數據進行聚合,給出產量與評分最高的名單。在分析過程中,還發現電影數量今年逐步增加,但評分下降,主要原因是中國地區今年低質量影視作品的增加。
另外,本篇報告還爬取了電影票房網( http://58921.com/ )1995-2020年度國內上映的影片票房,共採集4071條數據,其中3484條有效。進一步,本文分析了國內院線電影票房年度變化趨勢,票房與評分、評價人數、時長、地區的關系,票房與電影類型的關聯,並給出了票房最高的導演、演員與電影排名。
清洗、去重後,可以看到29033條數據長度、評分、評論數具有以下特點:
結合圖1(a)(b)看,可以看到電影數據時長主要集中在90-120分鍾之間,向兩極呈現階梯狀遞減,將數據按照短(60-90分鍾),中(90-120分鍾),長(120-150分鍾),特長(>150分鍾)劃分,各部分佔比為21.06%, 64.15%, 11.95%, 2.85%。
結合圖2(a)看,可以看到我們採集到的電影數據評分主要集中在6.0-8.0之間,向兩極呈現階梯狀遞減,在此按照評分劃分區間:2.0-4.0為口碑極差,4.0-6.0為口碑較差,6.0-7.0為口碑尚可,7.0-8.0為口碑較好,8.0-10.0為口碑極佳。
這5種電影數據的佔比分別為:5.78%, 23.09%, 30.56%, 29.22%, 11.34%
再將評分數據細化到每年進行觀察,可以發現,30年內電影數量與年度電影均分呈反相關,年度均分整體呈現下降趨勢,2016年電影均分最低,電影數量最多。
進一步做出每個年份下不同評級等級的電影數據佔比,可以發現,近年來,評分在[2.0,6.0)的電影數據佔比有著明顯提升,評分在[6.0,7.0)的數據佔比不變,評分在[7.0,10.0)的數據佔比減少,可能原因有:
對照圖5,可以發現,評分與時長、評論人數的分布大致呈現漏斗狀,高分電影位於漏鬥上部,低分電影位於漏斗下部。這意味著,如果一部電影的評論人數很多(特別是超過30w人觀影),時長較長(大於120min),那麼它大概率是一部好電影。
根據各個國家的電影數量作圖,可以得到圖6,列出電影數量前十的國家可得表格2,發現美國在電影數量上占第一,達到8490部,中國其次,達6222部。此外,法國,英國,日本的電影數量也超過1000,其餘各國電影數量相對較少。這可以說明美國電影有著較大的流量輸入,在中國產生了較大的影響。
進一步分析各國電影的質量,依據評分繪制評分箱線圖可得圖7,在電影數量排名前20的國家中:
接著我們可以探索,哪個國家的電影對豆瓣評分隨年份下降的貢獻最大,考慮到電影數量對應著評分的權重。根據上述各國的電影評分表現,我們可以猜測電影數量較多的國家可能對年度均分的下降有較大影響。於是,我們再計算出這些國家的年度電影均分,並與整體均分進行比較分析。
再作出中國大陸,中國台灣,中國香港的均分箱線圖圖9(a),可以看到,大陸電影均分低於港台電影,且存在大量低分電影拉低了箱體的位置。
分析相關性可得,大陸、香港、台灣電影年度均分與全部評分關聯度分別為R=0.979,0.919,0.822,說明濾去台灣和香港電影,大陸電影年度均分的變化趨勢與全部評分變化更接近。圖9(b)可以進一步反映這一點。
可以看到,大部分類型集中在X×Y=[10000,30000]×[6.00,7.50]的區間范圍內,劇情、喜劇、愛情、犯罪、動作類電影數量上較多,說明這些題材的電影是近三十年比較熱門的題材,其中劇情類電影佔比最多,音樂、傳記類電影平均得分更高,但在數量上較少,動作、驚悚類電影評論人數雖多,但評價普遍偏低。
除此之外,還有兩塊區域值得關註:
根據類型對電影數據進行聚合,整理得到各類型電影評分的時間序列,計算它們與整體均分時間序列的相關性,可得表格4與圖11,可以看到劇情,喜劇,懸疑這三種類型片與總分趨勢變化相關性最強,同時劇情、喜劇類電影在電影數量上也最多,因此可以認為這兩類電影對於下跌趨勢影響最大,但其餘類別電影的相關性也達到了0.9以上,說明幾種熱門的電影得分的變化趨勢與總體均分趨勢一致。
前面已經得知,中美兩國電影佔比最高,且對於均分時間序列的影響最大。在此,進一步對兩國電影進行類型分析,選取幾種主要的類型(數量上較多,且相關性較高)進行分析,分別是劇情,喜劇,愛情,驚悚,動作,懸疑類電影,繪制近年來幾類電影的數量變化柱狀圖與評分箱線圖可得圖12,13,14,15。
對導演與演員進行聚合,得到數據中共有15011名導演,46223名演員。按照作品數量在(0,2], (2,5], (5,10], (10,20], (20,999]進行分組統計導演數量,可以發現,15009名導演中有79.08%只拍過1-2部作品,46220名演員中有75.93%只主演過1-2部作品。忽略那些客串、跑龍套的演員,數據總體符合二八定律,即20%的人占據了行業內的大量資源。
在此,可以通過電影得分、每部電影評論人數以及電影數目尋找優秀的電影導演與演員。這三項指標分別衡量了導演/演員的創作水平,人氣以及產能。考慮到電影數據集中可能有少量影視劇/劇場版動畫,且影視劇/劇場版動畫受眾少於電影,但得分普遍要高於電影,這里根據先根據每部電影評論數量、作品數量來篩選導演/演員,再根據電影得分進行排名,並取前30名進行作圖,可得圖17,18。
結合電影票房網( http://58921.com/ )採集到的3353條票房數據,與豆瓣數據按照電影名稱進行匹配,可以得到1995-2020年在中國大陸上映的電影信息,分別分析中國內地電影的數量、票房變化趨勢,票房與評分、評價人數、時長、地區以及類型的關系,此外還給出了不同導演與演員的票房表現以及影片票房排名。
如圖19所示,國內票房數據與上映的電影數量逐年遞增,2020年記錄的只是上半年的數據,且由於受疫情影響,票房與數量驟減。這說明在不發生重大事件的情況下,國內電影市場規模正在不斷擴大。
對電影數據根據類型進行聚合,繪制散點圖21,可以發現:
提取導演/演員姓名,對導演/演員欄位進行聚合,計算每個導演/演員的票房總和,上映電影均分、以及執導/參與電影數目進行計算,作出票房總和前30名的導演/演員,可得圖22,23,圖中導演/演員標號反映了票房排名,具體每位導演/演員的上映影片數量、均分、每部電影評價人數、平均時長與總票房在表5、表6中給出。
最後根據電影票房進行排名,得到票房排名前20的電影如表格7所示,可以看到絕大部分上榜電影都是中國電影,索引序號為3、10、12、14、18、19為美國電影,這也反映了除國產電影之外,好萊塢大片占據較大的市場。
本篇報告採集了1990-2020年間豆瓣電影29033組有效數據,從豆瓣電影的評分、時長、地區、類型、演員、導演以及票房等信息進行分析評價,主要有以下結論:
❹ Python爬蟲如何抓取豆瓣影評中的所有數據
你可以用前嗅爬蟲採集豆瓣的影評,我之前用的,還可以過濾只採集評分在6分以上的所有影評,非常強大,而且他們軟體跟資料庫對接,採集完數據後,直接入庫,導出excel表。很省心。
❺ Python爬蟲實戰(1)requests爬取豆瓣電影TOP250
爬取時間:2020/11/25
系統環境:Windows 10
所用工具:Jupyter NotebookPython 3.0
涉及的庫:requestslxmlpandasmatplotlib
umpy
蛋肥想法: 先將電影名稱、原名、評分、評價人數、分類信息從網站上爬取下來。
蛋肥想法: print數據列表後發現電影原名、分類信息等存在不需要的字元,需預先處理;同時因為後續想做一個豆瓣電影TOP250的維度分布圖,而同一電影存在多個發行國家、類型(如「法國 美國 / 劇情 動作 犯罪」),為了簡(偷)便(懶),這里均取第一個作為記入的數據;最後將數據保存為xlsx。
蛋肥想法: 蛋肥想知道在豆瓣電影TOP250中年份、國家、類型的維度數據,為了練手,使用剛才保存成xlsx的數據,並分別畫成雷達圖、柱形圖、扇形圖。
❻ Python抓取豆瓣電影排行榜
1.觀察url
首先觀察一下網址的結構 http://movie.douban.com/top250?start=0&filter=&type= :
可以看到,問號?後有三個參數 start、filter、type,其中start代表頁碼,每頁展示25部電影,0代表第一頁,以此類推25代表第二頁,50代表第三頁...
filter顧名思義,是過濾已經看過的電影,filter和type在這里不重要,可以不管。
2.查看網頁源代碼
打開上面的網址,查看源代碼,可以看到信息的展示結構如下:
1 <ol class="grid_view"> 2 <li> 3 <div class="item"> 4 <div class="pic"> 5 <em class="">1</em> 6 <a href="http://movie.douban.com/subject/1292052/"> 7 <img alt="肖申克的救贖" src="http://img3.douban.com/view/movie_poster_cover/ipst/public/p480747492.jpg" class=""> 8 </a> 9 </div>10 <div class="info">11 <div class="hd">12 <a href="http://movie.douban.com/subject/1292052/" class="">13 <span class="title">肖申克的救贖</span>14 <span class="title"> / The Shawshank Redemption</span>15 <span class="other"> / 月黑高飛(港) / 刺激1995(台)</span>16 </a>17 18 19 <span class="playable">[可播放]</span>20 </div>21 <div class="bd">22 <p class="">23 導演: 弗蘭克·德拉邦特 Frank Darabont 主演: 蒂姆·羅賓斯 Tim Robbins /...<br>24 1994 / 美國 / 犯罪 劇情25 </p>26 27 28 <div class="star">29 <span class="rating5-t"><em>9.6</em></span>30 <span>646374人評價</span>31 </div>32 33 <p class="quote">34 <span class="inq">希望讓人自由。</span>35 </p>36 </div>37 </div>38 </div>39 </li>
其中<em class="">1</em>代表排名,<span class="title">肖申克的救贖</span>代表電影名,其他信息的含義也很容易能看出來。
於是接下來可以寫正則表達式:
1 pattern = re.compile(u'<div.*?class="item">.*?<div.*?class="pic">.*?' 2 + u'<em.*?class="">(.*?)</em>.*?' 3 + u'<div.*?class="info">.*?<span.*?class="title">(.*?)' 4 + u'</span>.*?<span.*?class="title">(.*?)</span>.*?' 5 + u'<span.*?class="other">(.*?)</span>.*?</a>.*?' 6 + u'<div.*?class="bd">.*?<p.*?class="">.*?' 7 + u'導演: (.*?) ' 8 + u'主演: (.*?)<br>' 9 + u'(.*?) / (.*?) / '10 + u'(.*?)</p>'11 + u'.*?<div.*?class="star">.*?<em>(.*?)</em>'12 + u'.*?<span>(.*?)人評價</span>.*?<p.*?class="quote">.*?'13 + u'<span.*?class="inq">(.*?)</span>.*?</p>', re.S)
在此處flag參數re.S代表多行匹配。
3.使用面向對象的設計模式編碼
代碼如下:
1 # -*- coding:utf-8 -*- 2 __author__ = 'Jz' 3 import urllib2 4 import re 5 import sys 6 7 class MovieTop250: 8 def __init__(self): 9 #設置默認編碼格式為utf-810 reload(sys)11 sys.setdefaultencoding('utf-8')12 self.start = 013 self.param = '&filter=&type='14 self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64)'}15 self.movieList = []16 self.filePath = 'D:/coding_file/python_file/File/DoubanTop250.txt'17 18 def getPage(self):19 try:20 URL = 'http://movie.douban.com/top250?start=' + str(self.start)21 request = urllib2.Request(url = URL, headers = self.headers)22 response = urllib2.urlopen(request)23 page = response.read().decode('utf-8')24 pageNum = (self.start + 25)/2525 print '正在抓取第' + str(pageNum) + '頁數據...' 26 self.start += 2527 return page28 except urllib2.URLError, e:29 if hasattr(e, 'reason'):30 print '抓取失敗,具體原因:', e.reason31 32 def getMovie(self):33 pattern = re.compile(u'<div.*?class="item">.*?<div.*?class="pic">.*?'34 + u'<em.*?class="">(.*?)</em>.*?'35 + u'<div.*?class="info">.*?<span.*?class="title">(.*?)'36 + u'</span>.*?<span.*?class="title">(.*?)</span>.*?'37 + u'<span.*?class="other">(.*?)</span>.*?</a>.*?'38 + u'<div.*?class="bd">.*?<p.*?class="">.*?'39 + u'導演: (.*?) '40 + u'主演: (.*?)<br>'41 + u'(.*?) / (.*?) / '42 + u'(.*?)</p>'43 + u'.*?<div.*?class="star">.*?<em>(.*?)</em>'44 + u'.*?<span>(.*?)人評價</span>.*?<p.*?class="quote">.*?'45 + u'<span.*?class="inq">(.*?)</span>.*?</p>', re.S)46 while self.start <= 225:47 page = self.getPage()48 movies = re.findall(pattern, page)49 for movie in movies:50 self.movieList.append([movie[0], movie[1], movie[2].lstrip(' / '),
51 movie[3].lstrip(' / '), movie[4],
52 movie[5], movie[6].lstrip(), movie[7], movie[8].rstrip(),53 movie[9], movie[10], movie[11]])54 55 def writeTxt(self):56 fileTop250 = open(self.filePath, 'w')57 try:58 for movie in self.movieList:59 fileTop250.write('電影排名:' + movie[0] + '\r\n')60 fileTop250.write('電影名稱:' + movie[1] + '\r\n')61 fileTop250.write('外文名稱:' + movie[2] + '\r\n')62 fileTop250.write('電影別名:' + movie[3] + '\r\n')63 fileTop250.write('導演姓名:' + movie[4] + '\r\n')64 fileTop250.write('參與主演:' + movie[5] + '\r\n')65 fileTop250.write('上映年份:' + movie[6] + '\r\n')66 fileTop250.write('製作國家/地區:' + movie[7] + '\r\n')67 fileTop250.write('電影類別:' + movie[8] + '\r\n')68 fileTop250.write('電影評分:' + movie[9] + '\r\n')69 fileTop250.write('參評人數:' + movie[10] + '\r\n')70 fileTop250.write('簡短影評:' + movie[11] + '\r\n\r\n')71 print '文件寫入成功...'72 finally:73 fileTop250.close()74 75 def main(self):76 print '正在從豆瓣電影Top250抓取數據...'77 self.getMovie()78 self.writeTxt()79 print '抓取完畢...'80 81 DouBanSpider = MovieTop250()82 DouBanSpider.main()
代碼比較簡單,最後將信息寫入一個文件,沒有什麼需要解釋的地方。
❼ 簡書用戶畫像 之 如何挖掘用戶的電影喜好
我在 《爬取百萬頁面 分析用戶畫像》 中分析了用戶的書籍喜好,這里繼續嘗試通過影評文章的抓取、內容清洗、影評句子提取,建立機器學習情緒預測模型,挖掘分析用戶對流行電影的喜好。
涉及的NLP(自然語言處理)知識點:
涉及的ML(機器學習)知識點:
電影的拍攝成本高、票價也不低,消費者投入的關注度和觀看成本高(最終的投入成本是包括注意力投入、金錢投入、時間投入和感情投入)。
簡單算下觀看一部電影的成本(步驟):先看下預告內容,做下同期上映電影的比較,覺得導演、演員陣容都不錯,下定決心要看了,跟男/女友/老婆 /老公/基友/閨密做推薦,推薦成功後去選座買票,觀影當天說不定還得先吃個飯,飯後乖乖的在影院呆上90分鍾(關鍵時刻還得憋尿),觀影結束後指不定還得來個夜宵、開個房間探討下人生什麼的。。。
讀一本書的成本(步驟):1.打開書/電子閱讀器/手機;2. 讀!
這樣對比看一部電影比讀一本書的投入成本高多了!
因此觀眾給出的反饋自然也比書籍會強烈一些,特別是滿懷期待看完卻發現是一部爛片,有種上當受騙的感覺。
因此對電影光是通過詞頻作為喜好度是不夠的,用戶可能反復的在罵呢。
所以需要引入多一個分析的因子:情緒。用戶提及某個電影時的情緒是怎麼樣的,是積極愉悅、還是負面憤怒,加上這個才能有效判定用戶對電影或者某個事物的喜好。
在豆瓣上,用戶的評分就是最直接的情緒數值:5力薦,4推薦,3還行,2較差,1很差。
但在這類寫作平台上,發布文章時是沒有一個選項來填寫分數,也沒提供選擇心情的選項。
「所言即其所思」,這是普遍人性。每個用戶寫下的文字表達想法,在字里行間都會不經意的使用一些情緒用詞來表達,這些便是我可以獲取的「原始數據」。
精準推薦!用戶談論得多的東西未必是TA所喜愛的,也許是TA痛恨的(比如說前任)。如果用戶在自己大力差評某部電影的文章底部看到另一部相似爛片的推薦,推薦文案還寫著「親,我猜你還喜歡看這些」,估計這用戶會有種吃了蒼蠅剛吐出來發現迎面又飛來幾只的感覺。
通過用戶在討論某事物時上下文的情緒分析,來判斷對該事物的喜惡,將預測結果加入對事物的打分計算中,最後得出一個可量化、可計算的分數值,便是一個精準推薦系統的需要解決的問題。
理論上只需要一句話:要識別出文章中提及的電影,以及作者對該電影的評論,是好評還是差評,作為文章作者對該電影的喜惡,並根據評論的情緒強烈程度轉化為喜惡程度即可。
那實際上,就要解決以下問題:
下面逐一細說。
我採集了上幾個比較受歡迎的電影專題以及一個大V帳號文章(數據截止至採集數據時):
但由於對專題頁面加了訪問限制,每個專題只能訪問到最新的200個列表頁面,因而每個專題可獲取2~3000篇文章,以此作為抽樣數據樣本。
要分析對電影的評價,首先就要獲取到文章中提到電影名稱有哪些,最簡單的匹配規則便是提取書名號 《》 內的內容。
而實際獲取到的電影名稱真可謂「臟亂差」,有電影名、書籍名、文章名等,有些電影名稱會用縮寫引用(如《變1》、《復聯》、《生化危機4/5/6》),或者中英文混合在一起(如《機器人總動員(wall-e)》),甚至還有錯漏別字(如《那些年,我們一起追過的女孩》,多了個「過」字),以及包含中英文特殊標點空白符號等,例如:
因此需要進行一輪「數據大清洗」,我使用如下清洗策略:
其中「電影專用詞典」,是通過採集了 「貓眼 影片總票房排行榜」 2000~2017年間上榜的所有電影,約有3000+部,如圖:
再根據文章中所收集到的電影名稱的候選文本,抓取「豆瓣網」的官方電影名字(遭遇了豆瓣業內聞名的反爬策略就不多說了),合並去重後約有8400多部。看一眼才發現好多電影連聽都沒聽過,有些電影名稱還挺有趣,以後有時間還可以做下電影名稱的分析。
為了解決錯別字,我通過文本相似性演算法,在電影專用詞典里找出與之最相似名稱。
知名的相似演算法有不少,如:
經過簡單比較,我選擇了其中表現最好的 jaro_winkler_distance
運用到文章內容上,可得到相似電影名稱,感覺效果還可以:
構建一個Pipeline用於提取頁面中電影名稱,對單個頁面測試效果如下:
運用到所有頁面上:
至此完成了電影名稱的提取、清洗,得出每篇文章提及的電影名稱,如圖:
判斷一篇文章的情緒,最簡單的做法是通過提取所有情緒詞來統計下詞頻及其權重可得到一個粗糙的結果,但這樣的結果對「影評」類文章不是很准確。
根據觀察,一篇電影評論文章中,往往會有大段的電影情節描述,然後夾雜一兩句評論。而有些電影本身劇情就是比較負面、陰暗的(如災難片類的),但影片本身質量很高(如《釜山行》,豆瓣評分8.2),如果文章內容包含大量的劇情描述,那麼得到關鍵詞會偏向於負面情緒,並不能用於表達出作者對電影的喜好情緒。
因此我使用了這樣的提取策略:
評論句子提取的結果示例如下:
這樣的策略對有些內容不是很適用,例如這樣的標題:《同樣是豆瓣9.2分,它或許比《摔跤吧!爸爸》更深》,這是典型的「借勢營銷」型文案,文章內容中推介的是另外一部韓國電影《熔爐》,而時下《摔跤吧!爸爸》正熱,標題中帶上這個會更吸引用戶點擊。
另外一個思路是對文章進行摘要提取,然後對摘要進行情緒識別。而對於文章的主題提取,可以使用在ML演算法中的用於解決 主題模型 問題的演算法(如LDA),但不確定是否適合影評這種混合了大量劇情描述的文章內容。
得到相關評論文本後,便可對文本進行分詞及情緒識別,這里有兩種做法,一是使用帶有情緒情感度的專業詞典,配合專有演算法;另外一種是使用機器學習演算法。
一開始我使用了大連理工大學的《大連理工情感詞彙本體庫》,是目前最權威的中文情緒詞典,共含有情感詞共計27466個,包含了詞語的詞性種類、情感類別、情感強度及極性等信息,例如:
中文情感詞彙本體的情感分類體系是在國外比較有影響的Ekman的6大類情感分類體系的基礎上構建的。在Ekman的基礎上,詞彙本體加入情感類別「好」對褒義情感進行了更細致的劃分。最終詞彙本體中的情感共分為7大類21小類,如圖:
把情感詞典加入分詞詞典,對候選每個句子進行分詞,得出情感片語,並累加每個情感詞的強度值作為句子的情感值。
但經過測試後,發現預測效果並不理想,究其原因發現是情感詞典中命中的詞語太少,在句子中得不到相關詞語,也就無法判斷情感極性和強度。
使用情感詞典的測試結果:
而專業詞典的擴展需要專業領域知識,擴展起來很困難,我目前沒找到更新的專業詞典,國內這塊的資料相當匱乏,而國外有個知名的SentiWordNet庫,中文NLP研究的難度系數可想而知。
鑒於情感詞典的資源限制,決定嘗試使用機器學習來對文本做正、負面情緒預測。
1). 構建分詞詞典:
分詞需要構建專用領域的詞典,這樣得到的分詞結果才會更精確。
因為只需要有正負情感類別、不需要有情感強度及極性等信息,我使用了網路上公開的一些情感詞典,:
合並、清洗和去重後,最終構建出了 14000+ 個詞的積極情緒詞典, 18000+ 個詞的消極情緒詞典。
積極詞典:
消極詞典:
2). 准備訓練語料
從網上搜集到幾個帶有積極、消極的標注的評論語料數據集,分別包含了書籍、DVD、音樂、購物領域的各有4000條評論,如下圖:
可惜沒找到中文影評相關的語料,但找到 國外英文的影評語料 ,對,英文資料很豐富。。。
3). 訓練模型
由於是文本型特徵,分類演算法上選擇了 樸素貝葉斯 ,把數據分為2份,一半訓練,另一半做測試。
使用 jieba 分詞工具,對文本進行分詞得到候選片語,把得到的片語作為特徵輸入來訓練情緒預測模型。
訓練後的模型測試結果如下:
訓練後的模型在書籍、音樂、影碟及購物評論的語料上都有不錯的效果。
在提取出的影評短句上測試:
又是「無聊」、「又俗又傻」而一個「但」字就反轉了情緒,真是難為分類器了:
經過反復對比實驗,發現語料的質量決定了模型的精度,而語料的擴展對比擴展專業詞典卻容易多了。例如幾年前都沒有「 因吹斯汀 」這些網路流行詞,更不知道它代表是正面情緒,以後只要不斷更新相關領域的語料庫來重新訓練則可得到更精確的模型。
俗話說「是騾子是馬拉出來遛遛」。
得到一個預測情緒的模型後,便可對影評文章進行預測,但預測的結果是否准確?准確率又有多高?這又是個問題。
每當事情陷入停滯,我就會想起日本漫畫大師安達充說過「當故事情節發展不下去的時候,加入一個新角色,是最簡單的做法」。
這時需要祭出一個「旁證」了。這所謂的「旁證」,也就是目前大家比較認可的電影評分網站——豆瓣網。
大家都知道豆瓣網上的電影用戶通過打星(5力薦,4推薦,3還行,2較差,1很差),轉換得出的10分制的評分,我們可簡單把1 4.9分視作負面評價、5 10分視作正面評價,沒有分數的視作中性評價。再把豆瓣的評價結果視作大部分人認同的結果,當然這樣肯定是有偏差的。
大膽假設,小心求證,先試試看吧。
根據電影名詞典再次去抓取豆瓣網上的電影信息,這次包含了電影分數::
使用獲取到的電影專題『電影院』文章內容測試,結果如下:
1048篇中,豆瓣評分結果與模型預測符合的有974篇,准確率是92.9%,WOW!真的這么准嗎?
看下詳細結果,豆瓣評分是正面的有1022條,預測對了973篇,例如:
而豆瓣評分是負面的有28條記錄,而模型只預測出1篇是負面的:
真的是模型預測錯了嗎?
從負面例子中抽樣看看模型分解的結果:
評論《麻煩家族》(豆瓣評分4.8)的:
從自動摘要出來的句子來看,實際上文章作者表現出正面情緒,模型預測為正面,預測正確 😊。
再看評論同一部電影的另外一個文章的評論:
作者顯然是給了個差評,但模型給了出的預測是正面,預測錯誤 😞。
負例的預測准確率低,有兩個原因,一個是豆瓣評分正負標準的閥值設定不夠精準,二是訓練數據不平衡。
之前使用的閥值策略是:「簡單把1 4分視作負面評價、5 10分視作正面評價,沒有分數的視作中性評價」。
我猜測在4~5分這個區間應該是灰度地帶,正負面評論都會有。為了驗證這個猜想,使用獲取到的所有豆瓣電影分數,導入數據分析工具中,排除掉沒有分數的條目後得到6500+條電影數據,其中最低是2.1,最高是9.7。
查看評分分布的直方圖與比例餅圖:
調整區間閥值,把 2.1-4.9 劃分為一個區間,系統自動分成了3組分值:
發現5分以下電影僅佔12%。
從評分分布結果看,在上大部分人寫文章是針對高分(好評)電影為主,低分(差評)電影的文章數量很少,從提取出來的數據量看,兩者比率約為100:3。
訓練數據不平衡導致正例過擬合,而負例欠擬合。
要解決數據不平衡問題,可以重新采樣訓練集。有兩種方法使不平衡的數據集來建立一個平衡的數據集——欠采樣和過采樣,解釋如下:
由於訓練數據不多,我使用了 過采樣 中的自舉方案。我將另外一個的電影專題『影視天堂』中模型預測結果與豆瓣評分結果一致的內容作為訓練數據集來強化訓練模型:
然後再對電影專題『電影院』測試一次:
負例的准確率改善了一些些,這說明效果是有的,以後只需繼續獲取到新的數據再「喂」給模型,模型預測結果會越來越精準。
至此,得到一個不算成熟的電影情緒預測模型,可以用來做一些有趣的統計分析了。
將『影視天堂』專題的分析結果在數據分析工具上進行數據可視化展示,得到一個「長尾圖」:
從報表中可得到這些信息:
注1:嚴格來說《歡樂頌》不是電影而是電視劇作品,在用豆瓣網的數據構建電影詞典時我沒有做嚴格區分
注2:專題的數據獲取是在5月份完成的,以及專題的最新收錄文章有訪問限制,無法獲取到舊的文章,因此得到的當時熱門影視作品的影評,從而呈現出信息跟當時熱播作品比較相關
再對先前獲取到的 1萬個用戶的近60萬篇文章內容 ,運行相應的Pipeline進行電影情緒數據的提取。
可視化數據後得到圖表:
現在可以看看,上用戶給予好評的電影有哪些,使用「詞雲圖」展示如下:
用戶給予差評的電影有哪些:
現在也可以精準了解每一個用戶的電影口味了,以 『毒舌電影 - 』 為例子:
注3:本文發表時上「毒舌電影」經歷過被封事件後已改名為「Sir電影」;專題「影視天堂」已改名為「電影」
以後做電影個性化推薦可就不要推薦錯了 😉。
❽ 【初學者】R語言 rvest包 爬取豆瓣電影top250,使用data.frame合並結果時,行數不一樣,無法合並
frame <- data.frame(x=c(1,2,3),
y=c(4,7,9))
if (3 %in% frame$x)
foo()