爬取博客园每周热点并试用jieba和wordcloud进行分词和生成词云

时间:2022-10-18 14:08:53

说来惭愧,来到博客园也好几年了,养成了时不时来刷刷首页,学习下先进知识的习惯,不过一直都是纯输入没有输出,今天才发现我竟然连博客都没开通。恰好这两天拿博客园练手做了个小项目,就以这个作为开始,写下在园子里的第一篇博客吧。

1. 项目背景

前阵子因为项目需要,学习了一段时间的知识图谱(Knowledge Graph)和自然语言处理NLP的一些知识。这两天项目上不那么忙了,又习惯性的点开博客园首页刷刷,看到“每周热点回顾”系列时,脑子一热,如果我把每周热点回顾系列爬下来做个简单的分析,看看大家都在关注啥,这些关注点会不会随时间变化呢?都有哪些作者不断霸榜呢?

说干就干,打开vscode,新建一个python环境,码起来。

2. 方案论证

爬取博客园每周热点并试用jieba和wordcloud进行分词和生成词云

如图所示,打开博客园团队的主页,标签里选择“每周热点回顾”,手一抖按个F12,查看了下请求URL和请求方法,得,有戏。

再看看页面源代码, 每一周的热点回顾都用entrylistItemTitle标好了,href里也放好了url链接。

爬取博客园每周热点并试用jieba和wordcloud进行分词和生成词云

 

 

第二步,打开上面提到的链接,就会进入详细的当周热点回顾。我们以22年9月的某一周为例。

爬取博客园每周热点并试用jieba和wordcloud进行分词和生成词云

 

 

 在HTML里,通过“noopener”也可以获取这些url的text。

爬取博客园每周热点并试用jieba和wordcloud进行分词和生成词云

 

 

 到这里,其实爬虫部分就结束了。我们的目标就是获取每周热点的链接,再进一步获取每周热点当中的随笔和新闻部份。

第三步,将获取的热点随笔和新闻,使用jieba进行分词,获得关键词。

第四步,使用wordcloud生成词云。

第五步,热点词跟踪(TBD)。

3. 代码详解

3.1 爬虫部分

直接使用了python的requests库和beautifulsoup,第一步获取所有“每周热点回顾”的链接,代码和效果如下。

urls = [f'https://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
    

爬取博客园每周热点并试用jieba和wordcloud进行分词和生成词云

 

 

 第二步进入每个热点回顾链接,获取其中的随笔和新闻,以及作者。代码和效果如下。

爬取博客园每周热点并试用jieba和wordcloud进行分词和生成词云

 

 

 至此爬虫部分结束。

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())

爬取博客园每周热点并试用jieba和wordcloud进行分词和生成词云

 

 有了词和词频,生成词云就很简单了。我们各取前50,画图。

随笔:

爬取博客园每周热点并试用jieba和wordcloud进行分词和生成词云

 

可以看到,通过自定义词典,.NET 和ASP.NET都很好的实现了分词。

 新闻:

爬取博客园每周热点并试用jieba和wordcloud进行分词和生成词云

 

热心的朋友可以试一下,其实新闻这部分的关键词变化非常大,但诸如“裁员”这种热门随着时间的走势很有意思。

 作者:

爬取博客园每周热点并试用jieba和wordcloud进行分词和生成词云

 

 感谢各位大佬的贡献。

4. 写在最后

也没用到啥高大上的技术,就是脑子一热,图个短平快,看个热闹,顺带练个手,留个小demo。

欢迎大家来我的Github给我小星星。代码在其中的ipynb文件里。