上個星期五(16/11/18)去看了馮小剛的最新電影《我不是潘金蓮》,電影很長,有點黑色幽默。看完之后我就去知乎,豆瓣電影等看看大家對於這部電影的評價。果然這是一部很有爭議的電影,無論是在知乎還是豆瓣,大家對這部電影褒貶不一,有的說拍的好,寓意深刻,具有很強的現實諷刺意味,也有的說故作矯情,是一部爛片。大家眾說紛紜,那么這部電影到底怎么樣呢?我想還是用事實說話比較好。我想到最近剛好我學習了一段時間的爬蟲了,也知道詞雲可以形象地反映詞語分布。所以我決定親自動手對《我不是潘金蓮》制作一個詞雲。
先說一下使用的工具:python2.7.12 wordcloud1.2.1 selenium2.53.6 jieba(一個中文分詞工具) 分析的文本來源為豆瓣電影下《我不是潘金蓮》的1.6W+評論。
selenium 是一個可以操縱瀏覽器的爬蟲工具,對於抓取動態頁面(js生成的頁面)非常方便。這里之所以使用selenium的一個主要原因是,電影的評論只有在登錄之后才可以全部抓取,如果使用urllib2等標准庫模擬登錄,因為還要處理驗證碼等,略顯麻煩,而使用selenium則非常簡便。
jieba 是一個優秀的中文分詞工具,功能強大並且使用簡便,這里因為涉及到中文,wordcloud對於中文的分詞支持不是特別好,所以需要我們手動分詞,我把這個任務交給了jieba。
制作詞雲的流程如下:
1.使用selenium 登錄豆瓣,抓取《我不是潘金蓮》下所有電影評論,並且保存到txt文件(一行是一條評論)
2. 使用jieba 對於評論進行分詞,得到新的文本
3. 對於新的文本 使用wordcloud 進行制作詞雲
話不多說,下面直接貼代碼:
1 # -*- coding:utf-8 -*-
2 '''
3 抓取豆瓣電影某部電影的評論 4 這里以《我不是潘金蓮為例》 5 網址鏈接:https://movie.douban.com/subject/26630781/comments 6 為了抓取全部評論需要先進行登錄 7 '''
8 from selenium import webdriver 9 import time 10 import codecs 11 import jieba 12 import jieba.analyse as analyse 13 from wordcloud import WordCloud 14 from scipy.misc import imread 15 from os import path 16
17 def get_douban_comments(url): 18 comments_list = [] # 評論列表
19 login_url = 'https://accounts.douban.com/login?source=movie'
20 user_name = '1111111' # 這里替換成你的豆瓣用戶名
21 password = '11111111' # 這里替換成你的密碼
22 driver = webdriver.Firefox() # 啟動Firefox()
23 driver.get(login_url) 24 driver.find_element_by_id('email').clear() # 清除輸入框
25 driver.find_element_by_id('email').send_keys(user_name) # 輸入用戶名
26 driver.find_element_by_id('password').clear() 27 driver.find_element_by_id('password').send_keys(password) # 輸入密碼
28 captcha_field = raw_input('請打開瀏覽器輸入驗證碼:') # 手動填入驗證碼
29 driver.find_element_by_id('captcha_field').send_keys(captcha_field) 30 driver.find_element_by_class_name('btn-submit').click() # 點擊登錄按鈕
31 time.sleep(5) # 等待跳轉到登錄之后的頁面
32 driver.get(url) # 定位到目標頁面
33 driver.implicitly_wait(3) # 智能等待3秒
34 n = 501 # 頁數
35 count = 10000 # 評論數目
36 while True: 37 try: 38 results = driver.find_elements_by_class_name('comment') 39 for result in results: 40 # author = result.find_elements_by_tag_name('a')[1].text # 作者
41 # vote = result.find_element_by_class_name('comment-vote').find_element_by_tag_name('span').text # 贊同數目
42 # time0 = result.find_element_by_class_name('comment-info').find_elements_by_tag_name('span')[1].text # 時間
43 comment = result.find_element_by_tag_name('p').text # 評論內容
44 comments_list.append(comment+u'\n') 45 print u"查找到第%d個評論" % count 46 count += 1
47 driver.find_element_by_class_name('next').click() # 點擊下一頁
48 print u'第%d頁查找完畢!' % n 49 n += 1
50 time.sleep(4) 51 except Exception,e: 52 print e 53 break
54 with codecs.open('pjl_comment.txt','a',encoding='utf-8') as f: 55 f.writelines(comments_list) 56 print u"查找到第%d頁,第%d個評論!" %(n,count) 57
58 # 得到所有關鍵詞
59 def get_all_keywords(file_name): 60 word_lists = [] # 關鍵詞列表
61 with codecs.open(file_name,'r',encoding='utf-8') as f: 62 Lists = f.readlines() # 文本列表
63 for List in Lists: 64 cut_list = list(jieba.cut(List)) 65 for word in cut_list: 66 word_lists.append(word) 67 word_lists_set = set(word_lists) # 去除重復元素
68 sort_count = [] 69 word_lists_set = list(word_lists_set) 70 length = len(word_lists_set) 71 print u"共有%d個關鍵詞" % length 72 k = 1
73 for w in word_lists_set: 74 sort_count.append(w+u':'+unicode(word_lists.count(w))+u"次\n") 75 print u"%d---" % k + w+u":"+unicode(word_lists.count(w))+ u"次"
76 k += 1
77 with codecs.open('count_word.txt','w',encoding='utf-8') as f: 78 f.writelines(sort_count) 79
80 def get_top_keywords(file_name): 81 top_word_lists = [] # 關鍵詞列表
82 with codecs.open(file_name,'r',encoding='utf-8') as f: 83 texts = f.read() # 讀取整個文件作為一個字符串
84 Result = analyse.textrank(texts,topK=20,withWeight=True,withFlag=True) 85 n = 1
86 for result in Result: 87 print u"%d:" % n , 88 for C in result[0]: # result[0] 包含關鍵詞和詞性
89 print C,u" ", 90 print u"權重:"+ unicode(result[1]) # 關鍵詞權重
91 n += 1
92
93 # 繪制詞雲
94 def draw_wordcloud(): 95 with codecs.open('pjl_comment.txt',encoding='utf-8') as f: 96 comment_text = f.read() 97 cut_text = " ".join(jieba.cut(comment_text)) # 將jieba分詞得到的關鍵詞用空格連接成為字符串
98 d = path.dirname(__file__) # 當前文件文件夾所在目錄
99 color_mask = imread("F:/python2.7work/wordcloud/alice_color.png") # 讀取背景圖片
100 cloud = WordCloud(font_path=path.join(d,'simsun.ttc'),background_color='white',mask=color_mask,max_words=2000,max_font_size=40) 101 word_cloud = cloud.generate(cut_text) # 產生詞雲
102 word_cloud.to_file("pjl_cloud.jpg") 103
104
105
106 if __name__ == '__main__': 107 '''
108 url = 'https://movie.douban.com/subject/26630781/comments?start=10581&limit=20&sort=new_score' 109 get_douban_comments(url) 110 file_name = 'pjl_comment.txt' 111 get_top_keywords(file_name) 112 '''
113 draw_wordcloud()
有幾點需要說明:
1.使用selenium簡化了登錄抓取過程,但是也有一個缺點,因為需要啟動瀏覽器,所以抓取效率就比較低,電影評論頁數較多,有時會出現網頁加載過慢等情況導致無法正常抓取數據。所以這里使用n,count作為標記,記錄意外退出時上次抓取的位置,這樣下次可以繼續從上次中斷的地方抓取。
2. wordcloud 默認的是英文字體,所以在WordCloud()方法中需要指定一個中文字體的位置(可以使用windows自帶的中文字體,比如宋體,楷體都可以),使用font_path="字體路徑"
3. selenium 如果驅動狐火瀏覽器的話,需要自行下載驅動(一個.exe文件),具體方法可以自行上網搜索,這里不贅述。
最后 下載的評論文本文件我已經放到我的github(https://github.com/Lyrichu/selenium/blob/master/pjl_comment.txt),有興趣的朋友可以自己下載。最后得到的詞雲圖如下:

