1. 程式人生 > >樸素貝葉斯實戰--根據電鋸驚魂豆瓣影評判斷新寫的影評是好評還是差評

樸素貝葉斯實戰--根據電鋸驚魂豆瓣影評判斷新寫的影評是好評還是差評

讀萬卷書行萬里路,故此學完樸素貝葉斯函式後,寫了個預測評論好壞的例子。

本例子是通過根據電鋸驚魂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 '差評'

-----------------------------------------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------------------------------------

經手動測試寫了幾個好評和差評都,都成功的分類了出來。