【Python基础】第四十一课:聚类算法实战---找出文章主题

jieba,CountVectorizer()

Posted by x-jeff on December 15, 2022

本文为原创文章,未经本人允许,禁止转载。转载请注明出处。

1.爬取新闻信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# Topical Clustering of News : 1
import requests
import json
from bs4 import BeautifulSoup
import pandas

def getArticle(url):
    res = requests.get(url)
    res.encoding = 'utf-8'
    soup = BeautifulSoup(res.text, 'html.parser')
    return ' '.join([p.text.strip() for p in soup.select('#article p')])

df = pandas.DataFrame()
for page in range(1, 11):
    url = 'https://feed.mix.sina.com.cn/api/roll/get?pageid=153&lid=2669&k=&num=50&page=' + str(
        page) + '&r=0.1534653757567701'
    res = requests.get(url)
    data = json.loads(res.content)

    ary = []
    for rec in data['result']['data']:
        try:
            ary.append({'title': rec['title'], 'url': rec['url'], 'content': getArticle(rec['url'])})
        except:
            print(rec['ext_3'])

    if df.empty:
        df = pandas.DataFrame(ary)
    else:
        df = df.append(pandas.DataFrame(ary), ignore_index=True)
df.to_excel('news.xlsx')

网络爬虫相关知识请见:【Python基础】第八课:网络爬虫

我们最终爬取了500条新闻的标题,链接和内容(前6条见下):

2.新闻主题聚类分析

首先安装结巴分词:pip install jieba

👉加载要用的包:

1
2
3
4
5
6
import pandas
import jieba
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.cluster import KMeans
import numpy

👉读取收集到的新闻数据:

1
2
# 读取新闻数据
df = pandas.read_excel('news.xlsx')

👉使用jieba分词:

1
2
3
4
5
6
7
8
9
10
11
# 使用jieba断词
titles   = []
articles = []
for rec in df.iterrows():
    articles.append(' '.join(jieba.cut(rec[1].content)))
    titles.append(rec[1].title)
#看下分词的效果
print(len(articles))
print(len(titles))
print(titles[0])
print(articles[0])
1
2
3
4
500
500
梅米租借期满转投阿联酋,外援补强成国安当务之急
新 京报 讯   ( 记者 周萧 ) 尽管 2022 中超联赛 结束 时 , 北京国安 希望 留下 租借 加盟 的 波黑 外援 梅米舍 维奇 , 但 北京 时间 1 月 14 日晚 , 梅米 以 自由 身 正式 加盟 阿联酋 迪拜 胜利 , 双方 未能 继续 合作 。   2022 年 4 月 , 梅米舍 维奇 由 河北 队 租借 加盟 北京国安 , 开启 其 在 中超 的 第三个 赛季 , 作为 一名 中后场 球员 , 攻防兼备 的 他 向来 被 球迷 们 称为 “ 带刀 后卫 ” 。 接过 昔日 马季奇 、 奥古斯 托 5 号 球衣 的 梅米 这 一 赛季 的 表现 不负众望 , 他 代表 国安 出场 28 次 , 贡献 了 4 球 4 助攻 , 被 认为 是 国安队 2022 年 的 “ 最靠 谱 外援 ” 。   由于 健康 原因 , 北京国安 无奈 放弃 中超 最后 两轮 联赛 , 梅米 也 提前 回国 。 按 当时 计划 , 俱乐部 希望 能 在 新 赛季 正式 引进 波黑 外援 , 但 因 双方 谈判 未能 达成 一致 , 梅米 最终 选择 加盟 阿联酋 迪拜 胜利 。   未能 与 梅米 继续 合作 是 国安俱乐部 的 遗憾 , 毕竟 在 去年 加盟 球队 的 4 名 外援 中 , 他 的 表现 最为 稳定 , 并 在 中后场 起到 关键作用 。 国安队 新 赛季 将 重返 工体 , 而 能否 完成 外援 补强 成为 俱乐部 面临 的 问题 之一 。     责任编辑 : 祝加贝

👉建立词频矩阵:

1
2
3
4
# 建立词频矩阵
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(articles)
print(X.shape) #输出为:(500, 38318)

500条新闻通过jieba分词一共得到38318个不重复的词语。矩阵X统计了每个词语在每条新闻中出现的频次。接下来通过一个例子说明下CountVectorizer的用法:

1
2
3
4
from sklearn.feature_extraction.text import CountVectorizer
X_test = ['you are good and we like you','but we do not fit']
vectorizer = CountVectorizer()
count = vectorizer.fit_transform(X_test)

vectorizer.get_feature_names()可以查看文本有哪些词汇,按首字母排序(去重之后):

1
['and', 'are', 'but', 'do', 'fit', 'good', 'like', 'not', 'we', 'you']

vectorizer.vocabulary_返回文本中每个单词(去除重复)的索引:

1
2
3
4
5
6
7
8
9
10
{'you': 9,
 'are': 1,
 'good': 5,
 'and': 0,
 'we': 8,
 'like': 6,
 'but': 2,
 'do': 3,
 'not': 7,
 'fit': 4}

count.toarray()输出每条文本中单词的词频:

1
2
array([[1, 1, 0, 0, 0, 1, 1, 0, 1, 2],
       [0, 0, 1, 1, 1, 0, 0, 1, 1, 0]], dtype=int64)

print(count)输出为:

1
2
3
4
5
6
7
8
9
10
11
  (0, 6)	1 #第0个文本索引为6的单词,即like,出现了一次。其余类似。
  (0, 8)	1
  (0, 0)	1
  (0, 5)	1
  (0, 1)	1
  (0, 9)	2 #第0个文本索引为9的单词,即you,出现了两次。
  (1, 4)	1 #第1个文本索引为4的单词,即fit,出现了一次。
  (1, 7)	1
  (1, 3)	1
  (1, 2)	1
  (1, 8)	1

👉计算余弦距离

1
2
# 计算余弦距离(Cosine Similarity)
cosine_similarities  = cosine_similarity(X, X)

cosine_similarities.shape为(500,500)。

👉使用k-means++聚类

1
2
3
# 使用KMeans++聚类
c = KMeans(n_clusters=10, init = 'k-means++', random_state=123)
k_data = c.fit_predict(cosine_similarities)

我们一共聚了10类。

👉产生聚类结果:

1
2
3
# 产生聚类结果
titles_ary = numpy.array(titles)
print(titles_ary[k_data == 9])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
['梅米租借期满转投阿联酋,外援补强成国安当务之急' '首钢大面积轮换不敌吉林,琼斯50分赛季第12次三双'
 '归化国脚洛国富:在中国效力8年后已无赚大钱念头' '首钢末节逆转“双杀”同曦,利夫两双丘天“最拼命”' '北京足球艰难中孕育希望'
 '2023,北京国安将如何踏入新工体?' '“北京爷们儿”马布里在中国这些年' '首钢2分险胜天津,解立彬为最后攻防担责'
 '北控不敌福建,张劲松执教首秀未能止住连败' '高开低走 马布里的第一段执教生涯交足了“学费”'
 '北京国安本赛季排名第七,年轻球员成长提速未来可期' '首钢不敌广东6连胜被终结,马尚无解让解立彬无奈' '张云松继续主管北京首钢队相关工作'
 '战海港人员困难未缓解,国安继续“小鬼当家”' '秦晓雯发文致谢:过去六年的经历让我收获满满' 'CBA | 首钢内线双剑合璧 利夫准绝杀立大功'
 '范子铭解释缺席原因:头疼得厉害' '利夫、丘天撑起内线 北京首钢四连胜势头正猛' '北京国安3比1逆转广州队 张玉宁打进第19球'
 '曾凡博30分,首钢连场得分破百42分大胜福建' '首钢大胜天津,全员轮转演练进攻有成效' '摸底世界杯赌球,揭露庄家稳赢的秘密'
 '葡萄牙队出局后,主教练回应:不后悔让C罗坐替补席' '国安不敌大连人遭遇两连败,斯坦利:输球并不意外'
 '英雄 |“魔笛”优雅依然 一个人扛着克罗地亚前行' '“用手跑完”的马拉松:一支年轻队伍和久违的比赛'
 'CBA公司公布常规赛第二阶段赛程 北京首钢队赛程艰巨' '一支县级业余足球队爆冷战胜北京国安背后'
 '林高远、陈幸同出局,亚洲杯国乒首轮意外折俩大将' '李景亮:“八角笼”里站得最久的中国人' '国安逆转武汉长江重回正轨,足协杯将给年轻人机会'
 '把金腰带“带回中国”,张伟丽就是牛!' '霍华德油箱还没空,他怎么就去中国台湾联赛打球了?' '刘晓宇加盟北控只待官宣 马布里得到后卫强援'
 '老将威猛,新人亮眼,CBA“大乱斗”时代来了']

可以看到,第9个类别都是体育相关的新闻。

3.代码地址

  1. 聚类算法实战—找出文章主题

4.参考资料

  1. CountVectorizer详解