1. 程式人生 > >水木社區

水木社區

one [] 定時 發布 items uid bubuko pri amp

任務背景:

爬取水木社區某位貼主在所有發帖版面的帖子,分析隨時間變化,貼主關註話題的變化。

主要步驟:

1.爬取帖子

這部分的實現源碼存於“水木爬蟲”文件夾中,運行環境為python3。

1)獲取發帖版面:首先是spiderman_007.py,在代碼中可設置待爬的貼主id。以貼主VChart為例,運行可得到該貼主發帖的版面及該版面的頁數,記錄在文件中“VChart.txt”中,

關鍵代碼:

技術分享圖片
 1         while page_num < url[topical]:
 2             content = get_url_content(now_url)
 3             print
(now_url) 4 page_num += 1 5 page_str = str(page_num) 6 now_url = base_url + page_str 7 soup = BeautifulSoup(content, html.parser) 8 i = 0 9 name = VChart 10 while i < 20: 11 new_name = soup.find_all("li
")[i].next_element.next_sibling.next_element.next_element.next_element 12 13 if new_name == name: 14 f.write("\‘" + topical + "\‘" + ": " + str(url[topical]) + ", ") 15 i = 21 16 page_num = url[topical] + 1 17 elif
new_name is None: 18 i = 21 19 i += 1
View Code

部分截圖如下:

技術分享圖片

2)爬取帖子:根據Vchart.txt中的信息,運行spiderman.py可得到該貼主截至目前發布的帖子,記錄在文件“VChart_texts.txt”中。

關鍵代碼:

技術分享圖片
 1 now_url = base_url + page_str
 2             soup = BeautifulSoup(content, html.parser)
 3             i = 0
 4             name = VChart
 5             while i < 20:
 6                 if soup.find_all("li")[i]:
 7                     test = soup.find_all("li")[i]
 8                 else:
 9                     i += 1
10                     continue
11 
12                 new_name = test.next_element.next_sibling.next_element.next_element.next_element
13 
14                 if new_name == name:
15                     new_url = base_url_+soup.find_all("li")[i].next_element.next_element.get(href)
16                     f.write(new_url)
17                     f.write("\n")
18                     # time.sleep(1)
19 
20                     content_ = get_url_content(new_url)
21                     soup1 = BeautifulSoup(content_, html.parser)
22                     # print(soup1.prettify())
23                     s = soup1.select(".sp")
24                     print(s[2].previous_sibling()[0].get_text())
25                     f.write(s[2].previous_sibling()[0].get_text())
26                     l = len(s)
27                     j = 2
28                     while j < l-2:
29                         s1 = s[j].get_text()
30                         j += 1
31                     # c ut=jieba.cut(s)
32                         print(s1)
33                         f.write(s1)
34                     time.sleep(1)
35                 i += 1
View Code

部分截圖如下:

技術分享圖片

2.對帖子進行排序、分詞、聚類

1)排序:對帖子按時間進行排序,運行sort_data.py可得VCharttexts_sorted.txt,

關鍵代碼:

技術分享圖片
 1 def list_sort(list1):
 2     pattern = re.compile("[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}")
 3 
 4     print(list1)
 5     list2 = re.findall(pattern, str(list1))
 6     list3 = list(zip(list2, list1))
 7     list3 = sorted(list3, key=lambda item: item[0])
 8     list4 = []
 9     for temp in list3:
10         list4.append(temp[1])
11     return list4
View Code

部分截圖如下:

技術分享圖片

2)分詞:將帖子按一定時間段分為不同文件,以每一年為一段為例,該貼主的帖子發帖時間為2004-2018年,共分為15個文件存於文檔->VChart->time中,運行fenci_time.py可以得到每一段時間文檔的分詞及詞頻結果,存於time文件下。

關鍵代碼:

技術分享圖片
 1 def segmented(file, text):
 2     ans = re.sub([^\w\u4e00-\u9fff]+, "", text)  # 正則表達式過濾出漢字
 3     ans = "".join(ans.split())
 4     # seg_list = jieba.cut(ans)  # 精確模式(默認是精確模式)
 5     # print("[精確模式]: ", "/ ".join(seg_list))
 6     words = jieba.cut(ans, cut_all=False)
 7     word_freq = {}
 8     stopwords = stopwordslist(ting.txt)
 9     for word in words:
10         if word in word_freq:
11             word_freq[word] += 1
12         else:
13             word_freq[word] = 1
14 
15     freq_word = []
16     for word, freq in word_freq.items():
17         freq_word.append((word, freq))
18     freq_word.sort(key=lambda x: x[1], reverse=True)
View Code

3)分詞:運行fenlegeci.py可以得到對所有貼子進行分詞、排序並統計詞頻的文件“fencihou.txt”。

4)取出無用詞:將fencihou.txt文件中的內容復制到Excel中,需要手動刪去一些無意義和體現不出貼主發貼話題的詞,例如“中”“提到”“大作”“水木”等。

5)計算百分比:運行cout_frequency&percent.py可以根據5)、6)中得到的結果得到每個詞在每個時間段的詞頻百分比,生成文件“統計.xls”。詞頻百分比=該詞的詞頻÷該時間段所有詞的詞頻總數×100%。

關鍵代碼:

技術分享圖片
1 readbook = xlrd.open_workbook(r統計_all.xlsx)
2 sheet = readbook.sheet_by_name(Sheet1)
3 nrows = sheet.nrows
4 f = xlwt.Workbook(encoding=utf-8)
5 table = f.add_sheet(data)
6 
7 table.write(i, j, 0)
8 f.save("統計.xls")
View Code

部分截圖如下:

技術分享圖片

6)生成.csv文件:在A1處填上“word”,將文件另存為“VChart時間詞頻百分比.csv”,即存為.csv格式的文件,註意編碼方式要選擇“UTF-8”。該文件可以被用於在weka軟件中進行聚類。

7)聚類:打開weka->Explorer->Open file,選則打開6)中的csv文件。

技術分享圖片

選則Cluster,點擊Choose選則SimpleKmeans算法進行聚類。

技術分享圖片

點擊下圖紅框處可以設置KMeans相關參數。選則“Classes to clusters evaluation”並按“word”聚類,點擊“Start”即可運行。

技術分享圖片

運行結束後,左下角會有運行記錄,右鍵選則Save result buffer可以得到結果文件。

技術分享圖片

為了方便查看內容,推薦使用Notepad++打開文件。

8)獲取聚類結果:weka的運行結果文件中有很多用不到的信息,運行clustering文件夾下的get_class_words.py文件可以得到每一類的詞的信息,形式如下:

技術分享圖片

3.展示

對每一類詞隨時間變化的展示,主要參考了https://github.com/TangliziGit/ColumnsAnimation.git中的項目。

1)統計每一類詞的詞頻百分比在各個時間段內的平均值,用於展示。

2)使用ColumnsAnimation->data中的getdata.py可以得到自己的展示數據的data.json文件。

3)在data.json文件開頭添加“var TotalData=”並另存為“data.js”放在ColumnsAnimation目錄下,打開animation.html即可看到展示效果。

 項目中的11-24.mp4為效果錄屏文件。

本項目地址:https://git.coding.net/Ruidxr/ShuiMu.git

水木社區