1.選一個自己感興趣的主題(所有人不能雷同)。
2.用python 編寫爬蟲程序,從網絡上爬取相關主題的數據。
3.對爬了的數據進行文本分析,生成詞雲。
4.對文本分析結果進行解釋說明。
5.寫一篇完整的博客,描述上述實現過程、遇到的問題及解決辦法、數據分析思想及結論。
6.最后提交爬取的全部數據、爬蟲及數據分析源代碼。
1.我選取的是糗事百科里面的 24小時專欄 網址是:https://www.qiushibaike.com/hot/,編譯語言是 python,工具是pycharm
2.爬取過程
F12打開開發者工具 找到需要的內容
可以清晰的看到信息都包含在<div class="content-block clearfix"></div> 中所以我們從其中找需要的內容
這里我選取段子內容和up主截圖分別如下
這里可以清楚的知道 'up主'信息和'段子內容'都包含在<div id="content-left" class="col1"></div>中
其中‘up主’信息包含在 <h2>標簽中,並且包含在<div class="article block untagged mb15 typs_long"></div>中,所以我們獲取 'up主'信息的代碼可以寫為:
1 up = soup.select('#content-left')[0].select('.article')[index].select('.author')[0].select('a')[1].text.strip('\n')
而 '段子內容'包含在<div class="content"></div>的盒子中,並且包含在<div class="article block untagged mb15 typs_long"></div>中,所以我們獲取'段子內容'信息的代碼可以寫為:
content = soup.select('#content-left')[0].select('.article')[index].select('.content')[0].select('span')[0].text.strip('\n')
但是呢,有的用戶會以匿名方式發段子(大概害羞吧!!),會出現 一個錯誤:list out if range,那么該怎么辦呢?
答案在最后。
獲取完單個需要的信息之后就是獲取整頁信息,想法是利用for循環獲取,因為上述內容都包含在<div class="article block untagged mb15 typs_long"></div>中,代碼如下:
1 for content_nums in range(sum_contents): 2 time.sleep(0.2) 3 duanzi_list.append(getContet(url, content_nums))
獲取總的內容數目,思路是看HTML代碼,發現每個子項目都包含在<div id="content-left" class="col1"></div>中,所以可以得到其長度確定一頁的總子項目數目代碼如下:
1 def getAllContents(url): 2 # global onePage_AllContents 3 request = requests.get(url) 4 request.encoding = 'utf-8' 5 soup = BeautifulSoup(request.text,'html.parser') 6 7 #一頁總內容數 8 onePage_AllContents = soup.select('#content-left')[0].select('.mb15').__len__() 9 return onePage_AllContents
獲取完單頁,接下來就應該獲取所有頁面,
1 #獲取總頁數 2 def getAllPages(url): 3 request = requests.get(url) 4 request.encoding = 'utf-8' 5 soup = BeautifulSoup(request.text,'html.parser') 6 7 number = int(soup.select('.page-numbers')[-1].text) 8 return number
將上述綜合起來,寫到一個function中,獲取所有up主信息和段子內容:
def dict_Contents(url): request = requests.get(url) request.encoding = 'utf-8' soup = BeautifulSoup(request.text, 'html.parser') # time.sleep(1) duanzi_list = [] sum_pages = getAllPages(url) # 總頁數 sum_contents = getAllContents(url) for page_nums in range(1, 4): url = 'http://www.qiushibaike.com/hot/page/{0}/'.format(page_nums) time.sleep(1) for content_nums in range(sum_contents): time.sleep(0.2) duanzi_list.append(getContet(url, content_nums)) # for news in duanzi_list: # print(news) return duanzi_list
由於我怕頁面未完全加載,可能會出現信息獲取錯誤,就添加一個time.sleep作為延遲,由於頁面較多,所以值選取了(1,4)的值。
之后呢,應該生成Excel表,所以利用pandas第三方類庫生成Excel表
import pandas df = pandas.DataFrame(list_Allduanzi) df.to_excel('duanzi.xlsx', engine='xlsxwriter')
截圖:
將要分詞的內容放進duanzi.txt中,代碼如下:
1 def writeNewsDetail(content): 2 f = open('duanzi.txt', 'a', encoding='utf-8') 3 f.write(content) 4 f.close()
截圖如下:
有了內容之后,接下來就是分詞,我分詞的類庫選擇的是jieba分詞,是一個比較好的分詞,在pycharm中可以直接搜索添加,也可以在命令行中添加 指令是'pip install jieba',但是在命令行中添加需先配置環境變量。那么分詞的話,首先,要去掉標點符號。將內容中的標點符號等分隔符全部替換為空格。接着,進行分詞切割,(同時我們可以去掉我們不需要的信息放在一個集合里)進行詞頻統計。並保存在文件中,代碼如下:
1 import jieba 2 file = open('duanzi.txt', 'r', encoding='utf-8') 3 duanzi = file.read() 4 file.close() 5 6 sep = '''-/.。""'',!?;:~`·[] \ ,:;“”?!-、}{【】‘’''' 7 exclude = {' ','\ue412','\x01','我','了','的','你','來','我們','被','……','…'} 8 9 for char in sep: 10 duanzi = duanzi.replace(char,'') 11 duanziList = list(jieba.cut(duanzi))#分詞 12 duanziDict = {} 13 duanzis = list(set(duanziList)-exclude)#刪除非中國漢語字符 14 15 for d in range(0,len(duanzis)): 16 duanziDict[duanzis[d]] = duanzi.count(str(duanzis[d])) 17 18 dictList = list(duanziDict.items()) 19 dictList.sort(key=lambda x:x[1],reverse=True) 20 21 f = open('count.txt','a',encoding='utf-8') 22 for i in range(150): 23 print(dictList[i]) 24 f.write(dictList[i][0] + ':' + str(dictList[i][1]) + '\n') 25 f.close()
截圖結果如下:
最后一步就是生成詞雲了。首先是下載,但是呢在pycharm和命令行下載是行不通的需要通過下載被的文件在使用命令行才行,問題解決有提及。那么代碼是:
1 #生成詞雲 2 from PIL import Image, ImageSequence 3 import numpy as np 4 import matplotlib.pyplot as plt 5 from wordcloud import WordCloud, ImageColorGenerator 6 7 font = r'C:\Windows\Fonts\simhei.TTF' 8 image = Image.open('./qiushibaike.jpg') 9 graph = np.array(image) 10 wc = WordCloud(font_path=font, background_color='White', max_words=50, mask=graph) 11 wc.generate_from_frequencies(duanziciyun) 12 image_color = ImageColorGenerator(graph) 13 plt.imshow(wc) 14 plt.axis("off") 15 plt.show()
詞雲圖片形狀是(根據那個糗事百科的背景圖):
生成的詞雲截圖如下:
總的代碼如下:
1 # -*- coding: UTF-8 -*- 2 import requests 3 import re 4 from bs4 import BeautifulSoup 5 import time 6 import openpyxl 7 import xlsxwriter 8 9 #保存到文本 10 def writeNewsDetail(content): 11 f = open('duanzi.txt', 'a', encoding='utf-8') 12 f.write(content) 13 f.close() 14 15 #獲取 16 def getContet(url,index): 17 global up, content 18 request = requests.get(url) 19 request.encoding = 'utf-8' 20 soup = BeautifulSoup(request.text,'html.parser') 21 22 duanzi = {} # 用字典存放信息 23 24 #up主 25 try: 26 up = soup.select('#content-left')[0].select('.article')[index].select('.author')[0].select('a')[1].text.strip('\n') 27 #內容 28 content = soup.select('#content-left')[0].select('.article')[index].select('.content')[0].select('span')[0].text.strip('\n') 29 except IndexError: 30 up = soup.select('#content-left')[0].select('.article')[index].select('.author')[0].select('h2')[0].text.strip('\n') 31 content = soup.select('#content-left')[0].select('.article')[index].select('.content')[0].select('span')[0].text.strip('\n') 32 duanzi['up主'] = up 33 duanzi['段子內容'] = content 34 writeNewsDetail(content) 35 return duanzi 36 37 #獲取總頁數 38 def getAllPages(url): 39 request = requests.get(url) 40 request.encoding = 'utf-8' 41 soup = BeautifulSoup(request.text,'html.parser') 42 43 number = int(soup.select('.page-numbers')[-1].text) 44 return number 45 46 #獲取總的段子數目 47 def getAllContents(url): 48 # global onePage_AllContents 49 request = requests.get(url) 50 request.encoding = 'utf-8' 51 soup = BeautifulSoup(request.text,'html.parser') 52 53 #一頁總內容數 54 onePage_AllContents = soup.select('#content-left')[0].select('.mb15').__len__() 55 return onePage_AllContents 56 57 # 將所有段子存放到字典中 58 def dict_Contents(url): 59 request = requests.get(url) 60 request.encoding = 'utf-8' 61 soup = BeautifulSoup(request.text, 'html.parser') 62 # time.sleep(1) 63 duanzi_list = [] 64 sum_pages = getAllPages(url) # 總頁數 65 sum_contents = getAllContents(url) 66 for page_nums in range(1, 4): 67 url = 'http://www.qiushibaike.com/hot/page/{0}/'.format(page_nums) 68 time.sleep(1) 69 for content_nums in range(sum_contents): 70 time.sleep(0.2) 71 duanzi_list.append(getContet(url, content_nums)) 72 # for news in duanzi_list: 73 # print(news) 74 return duanzi_list 75 76 77 if __name__ == '__main__': 78 url = 'http://www.qiushibaike.com/hot/' 79 # request = requests.get(url) 80 # request.encoding = 'utf-8' 81 # soup = BeautifulSoup(request.text, 'html.parser') 82 list_Allduanzi = [] 83 list_Allduanzi = dict_Contents(url) 84 #生成excel表 85 import pandas 86 df = pandas.DataFrame(list_Allduanzi) 87 df.to_excel('duanzi.xlsx', engine='xlsxwriter') 88 89 import jieba 90 file = open('duanzi.txt', 'r', encoding='utf-8') 91 duanzi = file.read() 92 file.close() 93 94 sep = '''-/.。""'',!?;:~`·[] \ ,:;“”?!-、}{【】‘’''' 95 exclude = {' ','\ue412','\x01','我','了','的','你','來','我們','被','……','…'} 96 97 for char in sep: 98 duanzi = duanzi.replace(char,'') 99 duanziList = list(jieba.cut(duanzi))#分詞 100 duanziDict = {} 101 duanzis = list(set(duanziList)-exclude)#刪除非中國漢語字符 102 103 for d in range(0,len(duanzis)): 104 duanziDict[duanzis[d]] = duanzi.count(str(duanzis[d])) 105 106 dictList = list(duanziDict.items()) 107 dictList.sort(key=lambda x:x[1],reverse=True) 108 duanziciyun = {} 109 f = open('count.txt','a',encoding='utf-8') 110 for i in range(150): 111 f.write(dictList[i][0] + ':' + str(dictList[i][1]) + '\n') 112 duanziciyun[dictList[i][0]] = dictList[i][1] 113 f.close() 114 115 #生成詞雲 116 from PIL import Image, ImageSequence 117 import numpy as np 118 import matplotlib.pyplot as plt 119 from wordcloud import WordCloud, ImageColorGenerator 120 121 font = r'C:\Windows\Fonts\simhei.TTF' 122 image = Image.open('./qiushibaike.jpg') 123 graph = np.array(image) 124 wc = WordCloud(font_path=font, background_color='White', max_words=50, mask=graph) 125 wc.generate_from_frequencies(duanziciyun) 126 image_color = ImageColorGenerator(graph) 127 plt.imshow(wc) 128 plt.axis("off") 129 plt.show()
3.遇到的問題以及解決辦法
第一個問題是:上述一開始提及到的,有些up主並非公開的,是匿名用戶,它的結構和非匿名用戶不一樣,那么,我就點擊查看,發現只有<span>標簽並沒<h2>標簽,所以我的代碼修改如下:
1 #up主 2 try: 3 up = soup.select('#content-left')[0].select('.article')[index].select('.author')[0].select('a')[1].text.strip('\n') 4 #內容 5 content = soup.select('#content-left')[0].select('.article')[index].select('.content')[0].select('span')[0].text.strip('\n') 6 except IndexError: 7 up = soup.select('#content-left')[0].select('.article')[index].select('.author')[0].select('h2')[0].text.strip('\n') 8 content = soup.select('#content-left')[0].select('.article')[index].select('.content')[0].select('span')[0].text.strip('\n')
問題就解決了,其中還學習到了,當 出現錯誤 'list out of range'時,可以運用try except IndexEorro 處理和尋找問題的根源。
第二個問題是:在利用pandas庫生成excel表時,產生了錯誤 'openpyxl.utils.exceptions.IllegalCharacterError',我解決的辦法是在google搜索該問題,然后在stackflow中找到了答案,下載並且導入 ‘import xlsxwriter’ 然后修改導入數據到excel的代碼 ‘df.to_excel('duanzi.xlsx', engine='xlsxwriter')’就OK了。
第三個問題是:詞雲wordcloud載pycharm下載不成功,原因是找不到該文件的詳情信息,估計是該工具引進python第三方類庫有問題,利用pip進行安裝也不成功,那么問題就漸漸浮出水面了,就是匹配不到該文件的版本號,所以,我們需要知道該版本號,上網查了下,因為我的python是3.6版本,所以對應cp36,然后我的是windows系統,所以在LDF中下windows版本的,鏈接是:https://www.lfd.uci.edu/~gohlke/pythonlibs/#wordcloud,下載amd的,拖入你的python路徑中,具體文件目錄就自行百度吧(我忘記了!!!)。
我是用anacanda 進行引進該第三方類庫的,參考鏈接:https://www.jianshu.com/p/e4b24a734ccc。
問題大概就這么多了。
4.數據分析思想以及結論
獲取段子內容並且進行詞頻統計,就可以了解現在的人說的是什么梗,或者有什么關鍵詞特別突出即,當你講笑話或者處於尷尬情況是可以將一兩個笑話和諧一下氣氛,也可以用這寫梗去交朋友或者哄別人開行,(哄女孩子什么的我沒說。。哈),總之是很有用的,但是呢,我不曉得為什么生成的都是一個一個詞的,並沒有很多詞組,不知道是不是結巴分詞的一個缺點。