海王是前段時間大熱的影片,個人對這種動漫題材的電影並不是很感興趣.然鵝,最近這部電影實在太熱了,正好最近看自然語言處理的時候,無意間發現了word cloud這個生成詞雲的庫,還蠻好玩的,那就抓抓這部電影的影評來試試吧.
爬蟲抓取豆瓣海王影評
首先我們登陸豆瓣,進入海王的影評頁面.然后打開影評的每一頁,看看url有什么特點.
還不錯,url很規律.
再開個頁面,F12看看,,評論內容在<span class="short">的tag下.
ok,那就閑話少說,開始抓取吧.requests和BeautifulSoup那是必備的庫了,寫過爬蟲的都知道,賊好用,誰用誰知道.
comments_counts = 0 current_url = "https://movie.douban.com/subject/3878007/comments?start=%d&limit=20&sort=new_score&status=P" % (comments_counts) while True: r=requests.get(current_url) print("processing",current_url) if r.status_code == 200: bs = BeautifulSoup(r.text,"html.parser") #print(bs.find_all("span",class_="short"))
for comment in bs.find_all("span",class_="short"): #print(comment.get_text())
comments.append(comment.get_text()) else: print(r.status_code,current_url) break comments_counts += 20 current_url = "https://movie.douban.com/subject/3878007/comments?start=%d&limit=20&sort=new_score&status=P" % (comments_counts)
爬的過程里,遇到2個問題,本來爬的好好的,爬着爬着都給我返回403了,403是禁止訪問啊,尼瑪,肯定是豆瓣給反爬了.糟老頭子壞得很嘛.
這時候我們需要把自己的爬蟲請求偽裝成瀏覽器請求.F12看一下.選中Network--左側選中一個url-右側headers中找到Request headers,其中包含了我們偽裝爬蟲所需要的信息.
我們將我們的請求里加上
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
后發現請求還是返回403,再一次嘗試加上cookiecookies = {'cookie':'你的cookie'},並且每次訪問都sleep 2秒,免得服務器認為我訪問太頻繁把我ip給封了.此時訪問成功了.
headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36' ,'Connection': 'keep-alive' } cookies = {'cookie':'你自己的cookie'} r=requests.get(current_url,headers=headers,cookies=cookies)
然后,爬蟲就開始開開心心地爬了,爬了N久,還沒爬完,果然又采坑了..................
上面講到,url很有規律,所以我們每一個url都是拼接出來的,我原先的想法是,如果評論一共200頁,那么第201頁的url應該是不能訪問的.然鵝,即便是沒有評論的評論頁,也是可以訪問的,比如第xx頁.......
再次修改我們的代碼
comments_counts = 0 current_url = "https://movie.douban.com/subject/3878007/comments?start=%d&limit=20&sort=new_score&status=P" % (comments_counts) comments = [] headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36' ,'Connection': 'keep-alive' } cookies = {'cookie':'替換成你自己的cookie'} effective = True while effective: r=requests.get(current_url,headers=headers,cookies=cookies) print("processing",current_url) effective = False if r.status_code == 200: bs = BeautifulSoup(r.text,"html.parser") #print(bs.find_all("span",class_="short")) for comment in bs.find_all("span",class_="short"): #print(comment.get_text()) comments.append(comment.get_text()) effective = True else: print(r.status_code,current_url) break print(effective) comments_counts += 20 current_url = "https://movie.douban.com/subject/3878007/comments?start=%d&limit=20&sort=new_score&status=P" % (comments_counts) time.sleep(2)
好了,到了這里,影評就已經抓取到存到了comments里.
這一步,我們做分詞處理.用大名鼎鼎的jieba分詞——一個中文分詞庫.
有2點要注意
- 去除各種標點符號
- 去除stopwords
去除標點請參考 https://github.com/fxsjy/jieba/issues/528.通過判斷中文編碼范圍去除標點.
我是用正則表達式處理的,new_sentence = re.sub(r'[^\u4e00-\u9fa5]', ' ', old_sentence) 然后再進行分詞的, \u4e00-\u9fa5這個是utf-8中,中文編碼的范圍
不過也有說對中文字符而言,不存在確定的范圍,建議自己寫個標點符號的dict,去做排除.
Actually, CJK characters are encoded together so there's no critical range for Chinese characters. A punctuation dict could be used to do the filtering.
幸運的是,通過中文編碼范圍的方式已經能夠解決我的問題了.
去除stopwords的話要去下載中文的stopwords集.https://github.com/goto456/stopwords
我們選用"哈工大停用詞表".
開始分詞.jieba分詞里有3種模式.官方git請戳這里.
支持三種分詞模式:
- 精確模式,試圖將句子最精確地切開,適合文本分析;
- 全模式,把句子中所有的可以成詞的詞語都掃描出來, 速度非常快,但是不能解決歧義;
- 搜索引擎模式,在精確模式的基礎上,對長詞再次切分,提高召回率,適合用於搜索引擎分
# encoding=utf-8 import jieba seg_list = jieba.cut("我來到北京清華大學", cut_all=True) print("Full Mode: " + "/ ".join(seg_list)) # 全模式 seg_list = jieba.cut("我來到北京清華大學", cut_all=False) print("Default Mode: " + "/ ".join(seg_list)) # 精確模式 seg_list = jieba.cut("他來到了網易杭研大廈") # 默認是精確模式 print(", ".join(seg_list)) seg_list = jieba.cut_for_search("小明碩士畢業於中國科學院計算所,后在日本京都大學深造") # 搜索引擎模式 print(", ".join(seg_list))
【全模式】: 我/ 來到/ 北京/ 清華/ 清華大學/ 華大/ 大學 【精確模式】: 我/ 來到/ 北京/ 清華大學 【新詞識別】:他, 來到, 了, 網易, 杭研, 大廈 (此處,“杭研”並沒有在詞典中,但是也被Viterbi算法識別出來了) 【搜索引擎模式】: 小明, 碩士, 畢業, 於, 中國, 科學, 學院, 科學院, 中國科學院, 計算, 計算所, 后, 在, 日本, 京都, 大學, 日本京都大學, 深造
這里我們采用,精確模式去對我們的影評分詞.
f = open("哈工大停用詞表.txt",encoding='utf-8') stopword_list = [line.strip() for line in f.readlines()] new_comments = [] for comment in comments: new_comment = re.sub(r'[^\u4e00-\u9fa5]', '', comment) new_comments.append(new_comment) word_list = [word for word in jieba.cut(''.join(new_comments),cut_all=False) if word not in stopword_list] print(word_list)
word_list內容如下:
['精美絕倫', '水下', '世界', '宏偉', '瑰麗', '海底',.....]
完成了分詞以后,我們開始繪制我們的詞雲.
我們使用wordcloud. 官方文檔https://amueller.github.io/word_cloud/index.html
在繪圖的時候又踩了個坑,中文的詞繪制出來全是空的長方形.請參考https://blog.csdn.net/xiemanR/article/details/72796739.
經過測試發現不支持顯示中文的原因是因為wordcloud的默認字體不支持中文,那就好辦了,我們設置一種支持中文的字體即可, wordlcloud.WordCloud類初始化函數有個設置字體的參數font_path,把支持中文的字體的路徑傳給font_path。
你可以去C:\Windows\Fonts下找一個自己喜歡的中文字體.右鍵屬性可以看到字體名稱.或者你去網上下載自己喜歡的中文字體.
wordcloud的api用法請參考官方文檔的例子.wordcloud的api簡單,稍微拿個例子看看改改就能上手.這里就不多說了.我選用了自己的博客頭像做背景圖樣式.
from wordcloud import WordCloud, ImageColorGenerator from scipy.misc import imread back_coloring = imread('./background.jpg') print(type(back_coloring)) #wc = WordCloud(background_color="white", max_words=200, mask=back_coloring,max_font_size=100, random_state=42, width=1000, height=860, margin=2,)
font='C:\Windows\Fonts\simhei.ttf' wc = WordCloud(background_color="black",font_path=font,mask=back_coloring,max_words=2000) wc.generate(" ".join(word_list))#注意:傳進來的word_list要用空格分隔
import matplotlib.pyplot as plt # create coloring from image
image_colors_default = ImageColorGenerator(back_coloring) plt.figure() # recolor wordcloud and show
plt.imshow(wc, interpolation="bilinear") plt.axis("off") plt.show() # save wordcloud
wc.to_file('./海王_wordcloud.png')
大功告成.
完整代碼請戳:這里.