朴素贝叶斯趣味挑战项目
1.目的
定時爬取笑話網站,利用樸素貝葉斯分析,將不同笑話發給不同人群。
2.方案
(1)首先利用python爬蟲抓取某個網站上的笑話。
(2)提供訓練樣本,然后用樸素貝葉斯模型來判斷當前的笑話是否屬于成人笑話。
(3)如果是成人笑話,把它自動發給好兄弟的qq郵箱。
(4)如果不是成人笑話,把它自動發給女朋友的qq郵箱。
? (5)之后用pyinstaller將.py文件打包成exe文件,適用于所有環境。
(6)利用windows系統的任務計劃程序功能早上8點定時執行此exe。因為不可能一直開著電腦,所以用云服務器。
3.實施
1.選取合適的笑話網站。---- 某某網站。
2.學習爬蟲,本來只會RSS源那樣子爬,但是好多網站找不到RSS地址,所以我只能學習爬蟲。
? ?(其實最后也沒用到抓包工具,可以先不下載)首先需要抓包工具,下載火狐瀏覽器的低版本才能兼容httpfox,下載地址http://ftp.mozilla.org/pub/firefox/releases/35.0/win32/zh-CN/,這個是中文版
? ?首先入門爬蟲,https://cuiqingcai.com/1052.html,學長推薦的課程,開始入門。
? ?這門課程上的是Python2,關于其中的函數的差別,http://blog.csdn.net/duxu24/article/details/77414298
? ? ? ? ? ?首先以post的方式爬取一個不需要驗證碼的
import urllib.request import urllib.parsevalues = {"username":"xxxxxxxxx@qq.com","password":"xxxxx"} data = urllib.parse.urlencode(values).encode('utf-8') url = "http://nian.so/" request = urllib.request.Request(url,data) response = urllib.request.urlopen(request) print(response.read())3.記錄一下cookie學習的代碼。
1)利用CookieJar對象實現獲取cookie的功能,并存儲到變量中,打印變量。
import urllib.request import urllib.parse import urllib.error import http.cookiejarcookie = http.cookiejar.CookieJar() #聲明一個CookieJar對象實例來保存cookie #使用HTTPCookieProcessor創建cookie處理器,并以其為參數構建opener對象 handler = urllib.request.HTTPCookieProcessor(cookie) opener = urllib.request.build_opener(handler) #構建請求 respoense = opener.open("http://www.baidu.com") for item in cookie:print('Name = ',item.name)print('Value = ',item.value)2)保存Cookie到文件,用MozillaCookieJar模塊
import urllib.request import urllib.parse import urllib.error import http.cookiejarfilename = "F:\\cookie.txt" cookie = http.cookiejar.MozillaCookieJar(filename) #聲明一個CookieJar對象實例來保存cookie #使用HTTPCookieProcessor創建cookie處理器,并以其為參數構建opener對象 handler = urllib.request.HTTPCookieProcessor(cookie) opener = urllib.request.build_opener(handler) #構建請求 respoense = opener.open("http://www.baidu.com") #保存cookie到文件 cookie.save(ignore_discard=True,ignore_expires=True)ignore_discard的意思是即使cookies將被丟棄也將它保存下來,ignore_expires的意思是如果在該文件中cookies已經存在,則覆蓋原文件寫入。
打開cookie文件。
3)從文件中獲取Cookie并訪問
import urllib.request import http.cookiejarfilename = "F:\\cookie.txt" cookie = http.cookiejar.MozillaCookieJar() #聲明一個CookieJar對象實例來保存cookie #使用HTTPCookieProcessor創建cookie處理器,并以其為參數構建opener對象 cookie.load(filename,ignore_discard=True,ignore_expires=True) request = urllib.request.Request("http://www.baidu.com") handler = urllib.request.HTTPCookieProcessor(cookie) opener = urllib.request.build_opener(handler) #構建請求 response = opener.open(request) print(response.readline())?4)利用cookie模擬網站登錄
? 訪問我校教務系統。
import urllib.request import http.cookiejarfilename = "F:\\cookie.txt" cookie = http.cookiejar.MozillaCookieJar(filename) #聲明一個CookieJar對象實例來保存cookie #使用HTTPCookieProcessor創建cookie處理器,并以其為參數構建opener對象 handler = urllib.request.HTTPCookieProcessor(cookie) opener = urllib.request.build_opener(handler) #構建請求 loginUrl = "http://ids.chd.edu.cn/authserver/login?service=http%3A%2F%2Fportal.chd.edu.cn%2F" values = {"username":"201524070201","password":"xxxxxx"} data = urllib.parse.urlencode(values).encode('utf-8') respoense = opener.open(loginUrl,data) #保存cookie到文件 cookie.save(ignore_discard=True,ignore_expires=True) gradeUrl = "http://bkjw.chd.edu.cn/eams/teach/grade/course/person!search.action?semesterId=75&projectType=" result = opener.open(gradeUrl) print(result.read())? 4.記錄正則表達式學習過程中的一點小問題。
我把學習正則的python文件命名為re.py,結果說module 're' has no attribute 'match',結果一百度
命名py腳本時,不要與python預留字,模塊名等相同,即Python文件名不要使用Python系統庫的名字,就是因為使用了Python系統庫的名字,
所以在編譯的時候才會產生.pyc文件。正常的Python文件在編譯運行的時候是不會產生.pyc文件的!
這類問題的解決方法則是:更改python腳本的命名,不要與python系統庫重合即可。回答鏈接:https://www.cnblogs.com/fangxx/p/xx-python02.html
5.正式學習爬取某笑話網站。
學習崔慶才大神的爬取記錄,還有后人更改py2為py3的博客,進行學習。
1)目標。
(1)抓取糗事百科熱門段子。
(2)過濾袋有圖片的段子。
(3)根據發布時間,段子內容,點贊數,進行篩選。
2)確定URL并抓取頁面代碼。
import urllib.request import urllib.error #不需要用到cookie #構建請求 page = 1 url = "https://www.qiushibaike.com/hot/page/" + str(page) header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36" } try:request = urllib.request.Request(url,headers=header)response = urllib.request.urlopen(request)print(response.read().decode("utf-8")) except urllib.error.URLError as e:if hasattr(e,"code"):print(e.code)if hasattr(e,"reason"):print(e.reason)? 提取到的內容如圖所示。
3)加入正則表達式提取第一頁的所有段子。
先寫正則表達式。
? 正則表達式如下:
#0發布人 1內容 2是圖片 3是點贊數pattern = re.compile('''<div class="article.*?<h2>(.*?)</h2>.*?'''+ '''<span>(.*?)</span>.*?'''+ '''<!-- 圖片或gif -->(.*?)<div class="stats">.*?'''+ '''<span class="stats-vote"><i class="number">(.*?)</i>''', re.S)正則表達式在寫的時候,一定要注意空格!!! ?<!-- 圖片或gif --> 里面的空格害我找了很長時間。
4)獲取笑話。
過濾掉帶圖片的。
import urllib.request import urllib.error import redef init():#不需要用到cookie#構建請求page = 1url = "https://www.qiushibaike.com/hot/page/" + str(page)header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36"}try:request = urllib.request.Request(url,headers=header)response = urllib.request.urlopen(request)content = response.read().decode("utf-8")#0發布人 1內容 2是圖片 3是點贊數pattern = re.compile('''<div class="article.*?<h2>(.*?)</h2>.*?'''+ '''<span>(.*?)</span>.*?'''+ '''<!-- 圖片或gif -->(.*?)<div class="stats">.*?'''+ '''<span class="stats-vote"><i class="number">(.*?)</i>''', re.S) items = re.findall(pattern,content)#只要沒圖片的段子for item in items:if not re.search("img",item[2]):result = re.sub('<br/>',"\n",item[1])print("發布人: %s\n內容:%s\n點贊數:%s\n" %(item[0].strip(),item[1].strip(),item[3].strip()))except urllib.error.URLError as e:if hasattr(e,"code"):print(e.code)if hasattr(e,"reason"):print(e.reason)init() #<div class="content">?
把那種查看全文的顯示全。
獲取段子完整代碼。其中遇到的問題:http://www.cnblogs.com/littlepear/p/8456897.html
import urllib.request import urllib.error import re page = 5 url = "https://www.qiushibaike.com/hot/page/" mainurl = "https://www.qiushibaike.com" header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36"} def init():content = getpage(index = page)#0發布人 1內容 2是圖片 3是點贊數pattern = re.compile('''<div class="article.*?<h2>(.*?)</h2>.*?'''+ '''<a href="(.*?)".*?'''+ '''<span>(.*?)</span>.*?'''+ '''<!-- 圖片或gif -->(.*?)<div class="stats">.*?'''+ '''<span class="stats-vote"><i class="number">(.*?)</i>''', re.S) items = re.finditer(pattern,content)pageItems = []#只要沒圖片的段子for item in items:zannum = int(item.group(5).strip())if ((not re.search("img",item.group(4))) and (zannum>1000)):#print(zannum) 挑選贊大于1000的笑話#print(item.group())if ((not re.search("查看全文",item.group()))):result = re.sub("<br/>","\n",item.group(3))#print("發布人: %s\n內容:%s\n點贊數:%s\n" %(item.group(1).strip(),result.strip(),item.group(5).strip()))pageItems.append([item.group(1).strip(),result.strip(),item.group(5).strip()])else: contentForAll = getpage(contentUrl=item.group(2))patternForAll = re.compile('''<div class="article.*?<h2>(.*?)</h2>.*?'''+ '''<div class="content">(.*?)</div>.*?'''+ '''<span class="stats-vote"><i class="number">(.*?)</i>''',re.S)# patternForAll = re.compile('''<div class="article.*?<h2>(.*?)</h2>'''# + '''.*?<div class="content">(.*?)</div>'''# + '''.*?<i class="number">(.*?)</i>''', re.S)newitems = re.findall(patternForAll,contentForAll)result = re.sub("<br/>","\n",newitems[0][1])#print("發布人: %s\n內容:%s\n點贊數:%s\n" %(newitems[0][0].strip(),result.strip(),newitems[0][2].strip()))pageItems.append([newitems[0][0].strip(),result.strip(),newitems[0][2].strip()])return pageItems def getpage(index=None,contentUrl=None):response = Noneif index:request = urllib.request.Request(url + str(index),headers=header)response = urllib.request.urlopen(request)elif contentUrl:request = urllib.request.Request(mainurl + contentUrl,headers=header)response = urllib.request.urlopen(request)return response.read().decode("utf-8") def main():pageItems = []pageItems = init()for jokelist in pageItems:for content in jokelist:print(content) main()效果:
? 6.通過樸素貝葉斯判斷是成人笑話還是普通笑話。
用了一份停用表,感覺效果還很好。
之前與之后的對比:
關于樸素貝葉斯的寫法與推導,在之前的博客上:http://www.cnblogs.com/littlepear/p/8322251.html
?同時關于漢字的處理,參考:https://www.cnblogs.com/marc01in/p/4775440.html
?
from numpy import *#加載停用詞 stop_word = [] def loadword(text):word = []fr = open(text,'r')lines = fr.readlines()for line in lines:word.extend(line.strip())fr.close()return worddef bagOfWordsVec(vocabSet,inputSet):returnVec = [0]*len(vocabSet)for word in inputSet:if word in vocabSet:returnVec[vocabSet.index(word)] += 1return returnVecdef textParse(bigString,stop_word):listOfWord = []#print(stop_word)for word in bigString:if word not in stop_word:listOfWord.append(word)return listOfWord#創建一個詞匯的集合 def createVocabList(dataSet):vocabSet = set([]) #創建空集合for document in dataSet:vocabSet |= set(document)return list(vocabSet)def trainNB0(trainMatrix,trainCategory):numTrainDocs = len(trainMatrix) #有幾行話numWords = len(trainMatrix[0]) #每行的詞匯表的詞數# print(numTrainDocs)# print(numWords)pAbusive = sum(trainCategory)/float(numTrainDocs) #p(Ci) 算是垃圾郵件的概率p0Num = ones(numWords)p1Num = ones(numWords)# print(p0Num)#p0Denom = 2.0; p1Denom = 2.0 #書上是2.0 不知道為什么 p(x1|c1)= (n1 + 1) / (n + N) 看網上的,#為了湊成概率和是1,N應該是numWordsp0Denom = 1.0*numWords; p1Denom = 1.0*numWordsfor i in range(numTrainDocs):if trainCategory[i] == 1: #某句話是侮辱性的話p1Num += trainMatrix[i] #矩陣相加#print(p1Num)p1Denom += sum(trainMatrix[i])#print(p1Denom)else:p0Num += trainMatrix[i]p0Denom += sum(trainMatrix[i])p1Vect = log(p1Num/p1Denom)p0Vect = log(p0Num/p0Denom)return p0Vect,p1Vect,pAbusivedef classifyNB(vecOClassify,p0Vec,p1Vec,p1Class):p1 = sum(vecOClassify*p1Vec) + log(p1Class)p0 = sum(vecOClassify*p0Vec) + log(1 - p1Class)if p1 > p0:return 1else: return 0#進行測試 def jokeTest():stop_word = loadword('stopword1.txt')docList = [];classList = []for i in range(1,26): text = ('joke/adult/%d.txt' % i)wordList = loadword(text)wordList = textParse(wordList,stop_word)docList.append(wordList)classList.append(1)text = ('joke/normal/%d.txt' % i)wordList = loadword(text)wordList = textParse(wordList,stop_word)docList.append(wordList)classList.append(0)vocabList = createVocabList(docList)# 40個訓練集,10個測試集trainingSet = list(range(50));testSet = []for i in range(10):randIndex = int(random.uniform(0, len(trainingSet)))testSet.append(trainingSet[randIndex]) #保證隨機性,不管重復del(trainingSet[randIndex]) trainMax = []; trainClasses = []for docIndex in trainingSet:#print(docIndex) trainMax.append(bagOfWordsVec(vocabList, docList[docIndex]))trainClasses.append(classList[docIndex])p0V,p1V,pSpam = trainNB0(array(trainMax),array(trainClasses))errorCount = 0for docIndex in testSet:wordVector = bagOfWordsVec(vocabList, docList[docIndex])if classifyNB(array(wordVector), p0V, p1V, pSpam) != classList[docIndex]:errorCount += 1print("the text %s \n the result %s the true result %s " % (docList[docIndex],classifyNB(array(wordVector), p0V, p1V, pSpam),classList[docIndex]))print("error rate: %f " % (float(errorCount)/len(testSet))) # def main(): # stop_word = [] # stop_word = loadword('stopword.txt') # for item in stop_word: # print(item) #main() jokeTest()50個樣例采用交叉驗證的方法,40個訓練,10個測試,錯誤率在10%左右。
?
7.通過qq郵箱發送郵件
參考:https://www.cnblogs.com/xshan/p/7954317.html
import smtplib from email.mime.text import MIMEText from email.utils import formataddrmy_sender='xxxxxxxx@qq.com' # 發件人郵箱賬號 my_pass = 'xxxxxxxxx' # 發件人郵箱密碼(當時申請smtp給的口令) my_user='xxxxxxxxx@qq.com' # 收件人郵箱賬號 def mail():ret=Truetry:content = "I love you!"msg=MIMEText(content,'plain','utf-8')msg['From']=formataddr(["發件人昵稱",my_sender]) # 括號里的對應發件人郵箱昵稱、發件人郵箱賬號msg['To']=formataddr(["收件人昵稱",my_user]) # 括號里的對應收件人郵箱昵稱、收件人郵箱賬號msg['Subject']="郵件主題-測試" # 郵件的主題,也可以說是標題server=smtplib.SMTP_SSL("smtp.qq.com", 465) # 發件人郵箱中的SMTP服務器,端口是465server.login(my_sender, my_pass) # 括號中對應的是發件人郵箱賬號、郵箱密碼server.sendmail(my_sender,[my_user,],msg.as_string()) # 括號中對應的是發件人郵箱賬號、收件人郵箱賬號、發送郵件server.quit()# 關閉連接except Exception:# 如果 try 中的語句沒有執行,則會執行下面的 ret=Falseret=Falsereturn retret=mail() if ret:print("郵件發送成功") else:print("郵件發送失敗")
8.整合
所有代碼稍后給個github上的鏈接:
以下是正常笑話:
以下是成人笑話:
? 9.將.py文件打包成exe,在所有環境下執行
一直嘗試用py2exe來打包,一直出問題,看網上說,可能是不支3.4以上的版本,遂換成pyinstaller,安裝和使用參考下面的博客:
https://www.zhihu.com/question/54777137
?
??https://www.zhihu.com/question/52660083
小tips:如果打包后的exe出現問題,可以用控制臺程序來執行可以查看錯誤。
同時所用到的附件文件比如txt和圖片,必須拷到所在dist下。
10.用電腦定時執行exe.
(1)windows
遇到個坑:
幾個文件在同一目錄下,我之前設的相對路徑,直接點開文件,可以運行,如果讓計算機的任務計劃程序定時運行的話,一直找不到我的附件的
?很納悶,輸出絕對路徑查看了下,直接點開exe,
?如果任務計劃程序定時運行的話,路徑變成,
?網上也有解決方案:https://www.cnblogs.com/huoqs/p/5670216.html
http://blog.csdn.net/vic0228/article/details/61914425
(2)linux
轉載于:https://www.cnblogs.com/littlepear/p/8440939.html
總結
以上是生活随笔為你收集整理的朴素贝叶斯趣味挑战项目的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 想上云,请评估与思考上云目的
- 下一篇: C++11列表初始化