樸素貝葉斯實戰--根據電鋸驚魂豆瓣影評判斷新寫的影評是好評還是差評
阿新 • • 發佈:2018-12-16
讀萬卷書行萬里路,故此學完樸素貝葉斯函式後,寫了個預測評論好壞的例子。
本例子是通過根據電鋸驚魂8的豆瓣評論而進行的預測,由於未登入的情況下只能獲取220條評論,為了檢驗貝葉斯函式也就沒在爬蟲上下功夫,只爬取了好評和差評各220條,各位如果想改進準確率的話可以多爬些資料,並且多爬些不同電影的評論。
對爬出的資料使用jieba包進行分詞和拆分權重最大的幾個關鍵字,再將所有的關鍵字(包括好評和差評)放到兩個map中(好評和差評),鍵為關鍵字值為當前類別中出現的次數。預設次數都為1,是為了計算概率時候出現0的情況,並且將概論的乘法改為log的加法。為了處理0.00000000000.....1這種無法顯示這種情況
廢話不多說,直接上程式碼:
先爬取資料
Crawler.py:
# *_*coding:utf-8 *_* import requests import sys import re import jieba import jieba.analyse import os reload(sys) sys.setdefaultencoding("utf-8") #好評 #url="https://movie.douban.com/subject/25788426/comments?start=0&limit=20&sort=new_score&status=P&percent_type=h" #差評 url="https://movie.douban.com/subject/25788426/comments?start=0&limit=20&sort=new_score&status=P&percent_type=l" #常用詞 oftenWord=['是','不是','電影','豎','鋸','電鋸',''] words='' def getPageContent(url): page=requests.get(url) page.encoding=requests.utils.get_encodings_from_content(page.text)[0] nextPage=re.findall(r'href="*.?start(.*?)"*.?data-page=',page.text,re.S) if not nextPage: return '','' nextPage=nextPage[-1] items=re.findall(r'<span class="short">(.*?)</span>',page.text,re.S) return nextPage,items def saveKeys(name): filePath = 'F:\\vidoTake\\' if not os.path.exists(filePath): os.makedirs(filePath) file = open(filePath+name.decode("utf-8")+".txt", "w") file.write(words) file.close() def textKey(text): # 1.分詞,這裡使用結巴分詞全模式 cutTexts=jieba.cut(text) # 2.去除常用詞 text="" for cutText in cutTexts: if cutText not in oftenWord: text=text+" "+cutText # 3.提取關鍵詞 # text 為待提取的文字 # topK:返回幾個 TF/IDF 權重最大的關鍵詞,預設值為20。 # withWeight:是否一併返回關鍵詞權重值,預設值為False。 # allowPOS:僅包括指定詞性的詞,預設值為空,即不進行篩選 keys=jieba.analyse.extract_tags(text,topK=10,withWeight=True,allowPOS=()) for word,qz in keys: global words words=words+" "+word words=words+"\n" def CheakText(url): page = [0] for i in page: nextPage, items = getPageContent(url) if nextPage == '': break url = "https://movie.douban.com/subject/25788426/comments?start" + nextPage for item in items: textKey(item) page.append(0) saveKeys("差評") CheakText(url)
評論分類:
PuSuBayes.py:
# *_*coding:utf-8 *_* import sys import math reload(sys) sys.setdefaultencoding('utf8') import jieba #讀取爬下來的檔案,並生成向量 #格式:{特徵:出現的次數} def getSet(url): file=open(url,"r") contents=file.readlines() setContent={} for content in contents: items=content.replace("\n", "").split(" ") for item in items: if item=='': continue setContent[item]=setContent.get(item,1)+1 return setContent,len(contents) #統計所有類別所有特徵出現的次數,並且統計各個類別的評論數 def countData(): goodContent,goodLen = getSet("F:\\vidoTake\\" + "好評".decode("utf-8") + ".txt") badContent,badLen = getSet("F:\\vidoTake\\" + "差評".decode("utf-8") + ".txt") keys = set(goodContent.keys()) | set(badContent.keys()); for key in keys: if key not in goodContent.keys(): goodContent[key] = 1 if key not in badContent.keys(): badContent[key] = 1 return goodContent,badContent,goodLen,badLen #計算各個類別的貝葉斯 #根據輸入的檔案進行詞語拆分,然後選擇出在上述特徵向量中出現的詞語(X,Y,Z) #計算P(類別i|特徵1,特徵2,特徵3) # =P(特徵1,特徵2,特徵3|類別i)*P(類別i)/P(特徵1,特徵2,特徵3) # =P(特徵1|類別i)*P(特徵2|類別i)*P(特徵3|類別i)*P(類別i)/P(特徵1,特徵2,特徵3) def bayes(word): goodContent, badContent, goodLen, badLen=countData() curWords=jieba.cut(word) #計算貝葉斯,由於拆分的分母一樣所以無需計算,小數點太多的話無法計算。故此轉成log,乘法變為加法 goodBayes =math.log(goodLen*1.0/(goodLen+badLen)) badBayes = math.log(badLen*1.0/(goodLen+badLen)) for curWord in curWords: if curWord in goodContent.keys(): goodBayes=math.log(goodContent.get(curWord.encode("utf-8"))*1.0/goodLen)+goodBayes badBayes=math.log(badContent.get(curWord.encode("utf-8"))*1.0/badLen)+badBayes return goodBayes,badBayes goodBayes,badBayes=bayes("就這東西,什麼玩意,期待了很久") print goodBayes print badBayes if goodBayes>badBayes: print '好評' else: print '差評'
-----------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------------
經手動測試寫了幾個好評和差評都,都成功的分類了出來。