爬取部落格園每周熱點並試用jieba和wordcloud進行分詞和生成詞雲

說來慚愧,來到部落格園也好幾年了,養成了時不時來刷刷首頁,學習下先進知識的習慣,不過一直都是純輸入沒有輸出,今天才發現我竟然連部落格都沒開通。恰好這兩天拿部落格園練手做了個小項目,就以這個作為開始,寫下在園子里的第一篇部落格吧。

1. 項目背景

前陣子因為項目需要,學習了一段時間的知識圖譜(Knowledge Graph)和自然語言處理NLP的一些知識。這兩天項目上不那麼忙了,又習慣性的點開部落格園首頁刷刷,看到「每周熱點回顧」系列時,腦子一熱,如果我把每周熱點回顧系列爬下來做個簡單的分析,看看大家都在關注啥,這些關注點會不會隨時間變化呢?都有哪些作者不斷霸榜呢?

說干就干,打開vscode,新建一個python環境,碼起來。

2. 方案論證

如圖所示,打開部落格園團隊的主頁,標籤里選擇「每周熱點回顧」,手一抖按個F12,查看了下請求URL和請求方法,得,有戲。

再看看頁面源程式碼, 每一周的熱點回顧都用entrylistItemTitle標好了,href里也放好了url鏈接。

 

 

第二步,打開上面提到的鏈接,就會進入詳細的當周熱點回顧。我們以22年9月的某一周為例。

 

 

 在HTML里,通過「noopener」也可以獲取這些url的text。

 

 

 到這裡,其實爬虫部分就結束了。我們的目標就是獲取每周熱點的鏈接,再進一步獲取每周熱點當中的隨筆和新聞部份。

第三步,將獲取的熱點隨筆和新聞,使用jieba進行分詞,獲得關鍵詞。

第四步,使用wordcloud生成詞雲。

第五步,熱點詞跟蹤(TBD)。

3. 程式碼詳解

3.1 爬虫部分

直接使用了python的requests庫和beautifulsoup,第一步獲取所有「每周熱點回顧」的鏈接,程式碼和效果如下。

urls = [f'//www.cnblogs.com/cmt/category/218599.html?page={page}' for page in range(1, 32)]

headers = {
	"content-type": "application/json",
	"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30"
}

# 這函數用來發送請求,注意實際傳遞的url值
def craw(url):

	payload = {
		"CategoryType": "SiteHome",
		"ParentCategoryId": 0,
		"CategoryId": 808,
		"TotalPostCount": 4000,

	}
    # 發送的是get請求
	r = requests.get(url, data=json.dumps(payload), headers=headers)
	return r.text

# 解析html,獲取url,text和時間戳三部分
def parse(html):
    soup = BeautifulSoup(html, "html.parser")
    links = soup.find_all("a", class_="entrylistItemTitle")
    times=soup.find_all("a",title="permalink")
    temp=[]
    for i in range(0,len(links)):
        url=links[i]["href"]
        text= links[i].get_text().replace("\n","").strip()
        ts=times[i].get_text()
        temp.append((url,text,ts))
    # return [(link["href"], link.get_text()) for link in links]
    return temp
    

 

 

 第二步進入每個熱點回顧鏈接,獲取其中的隨筆和新聞,以及作者。程式碼和效果如下。

 

 

 至此爬虫部分結束。

3.2 jieba分詞與wordclou生成詞雲

其實從上一個圖也可以看出來,為了省事我用了一個dataframe,這也是為了後續能夠按時間(月,年)分析熱點詞變化做準備,可惜因為懶,只分析了22年的文本。

jieba和wordcloud就不介紹了,這裡想強調的是為了修正一些分詞效果,我使用了

  • 哈工大版本的停用詞表,停用詞本質上是使用txt文件維護一個列表,分詞後通過差集運算去除感染的雜項。
  • 用戶詞典。比如.NET這種詞,很容易就被jieba分成了.和NET兩個詞,因此需要在用戶詞典中維護一下。
  • 手動去除分詞後長度為1的漢字,去除停用詞表中漏掉的干擾詞。

此外,作者部分不需要進行分詞,直接count就行。

# 使用自定義詞典
jieba.load_userdict('userdict.txt')
# 需要添加stopwords
def stopwordslist():
    stopwords = [line.strip() for line in open('哈工大停用詞表.txt',encoding='UTF-8').readlines()]
    return stopwords
sw=stopwordslist()

選擇22年之後的每周熱點做樣本,使用pandas中的value_counts()生成一個包含隨筆,新聞,作者和各自詞頻的dict。程式碼和效果如下。

# 把每周的熱點隨筆和新聞進行分詞,分詞後保存到新建的兩列
# 使用stopwords去除掉標點符號和無意義詞
ds=[]
for col_index in range(3,5):
    res_full=[]
    for i in range(0,len(df22)):
        temp=df22.iloc[i][col_index].split(',')
        for t in temp:
            cut=jieba.lcut(t)
            # 去掉停用詞
            cut_res=[i for i in cut if not i in sw]
            # 去掉長度為1的詞,比如「個」,「人」
            cut_res=[i for i in cut if not len(i)==1]
            res_full.extend(cut_res)
    ds.append(pd.Series(res_full).value_counts())

 

 有了詞和詞頻,生成詞雲就很簡單了。我們各取前50,畫圖。

隨筆:

 

可以看到,通過自定義詞典,.NET 和ASP.NET都很好的實現了分詞。

 新聞:

 

熱心的朋友可以試一下,其實新聞這部分的關鍵詞變化非常大,但諸如「裁員」這種熱門隨著時間的走勢很有意思。

 作者:

 

 感謝各位大佬的貢獻。

4. 寫在最後

也沒用到啥高大上的技術,就是腦子一熱,圖個短平快,看個熱鬧,順帶練個手,留個小demo。

歡迎大家來我的Github給我小星星。程式碼在其中的ipynb文件里。