[Pyhon大数据分析] 五.人民网新闻话题抓取及Gephi构建主题知识图谱
该系列文章是Python大数据分析系列博客,包括网络爬虫、可视化分析、GIS地图显示、情感分析、舆情分析、主题挖掘、威胁情报溯源、知识图谱、预测预警及AI和NLP应用等。希望该系列文章对您有所帮助。
前文分享了采用SnowNLP对微博话题进行简单的情感分析及文本挖掘。这篇文章将讲解Python抓取人民网新闻,并利用Gephi构建主题知识图谱,发现各主题关键词的关联。希望这篇基础性文章对您有所帮助,也非常感谢参考文献中老师的分享!如果您有想学习的知识或建议,可以给作者留言~
本文的重点不是数据抓取,请读者结合自己的需求和数据进行分析,也可以直接使用作者的数据集,希望给大家知识图谱提供一点思路。就作者而言,知识图谱包括两种类型,一种是Google于2012年提出的Knowledge Graph(下一代搜索引擎),另一种是图书情报和文献分析的知识图谱,这里其实介于两者之间,也建议读者结合自己领域理解。
代码下载地址:https://github.com/eastmountyxz/Wuhan-data-analysis
CSDN下载地址:https://download.csdn.net/download/Eastmount/12323815
文章目录
同时推荐前面作者另外五个Python系列文章。从2014年开始,作者主要写了三个Python系列文章,分别是基础知识、网络爬虫和数据分析。2018年陆续增加了Python图像识别和Python人工智能专栏。
- Python基础知识系列:Python基础知识学习与提升
- Python网络爬虫系列:Python爬虫之Selenium+BeautifulSoup+Requests
- Python数据分析系列:知识图谱、web数据挖掘及NLP
- Python图像识别系列:Python图像处理及图像识别
- Python人工智能系列:Python人工智能及知识图谱实战
前文阅读:
[Pyhon大数据分析] 一.腾讯实时数据爬取、Matplotlib和Seaborn可视化分析全国各地区、某省各城市、新增趋势
[Pyhon大数据分析] 二.PyEcharts绘制全国各地区、某省各城市地图及可视化分析
[Pyhon大数据分析] 三.新闻信息抓取及词云可视化、文本聚类和LDA主题模型文本挖掘
[Pyhon大数据分析] 四.微博话题抓取及新冠肺炎文本挖掘和情感分析
一.人民网数据抓取
本文抓取数据为人民网某专栏的新闻数据。数据包括重要新闻、人民评论、实况武汉、各地动态、八方支援等专栏,通过抓取新闻数据进行主题关键词分析和知识图谱构建。下面以YQ快速为例,先进行网页分析,再抓取相关的新闻数据。
http://society.people.com.cn/GB/369130/431577/431608/index.html
本文采用Selenium和BeautifulSoup进行抓取,定位网页节点关键代码如下:
- 标题:titles = driver.find_elements_by_xpath(’//div[@class=" p2j_list_lt fl"]/ul/li’)
- 链接:links = driver.find_elements_by_xpath(’//div[@class=" p2j_list_lt fl"]/ul/li/a’)
获取标题、时间、链接之后,我们通过访问链接获取正文信息,核心代码如下:
- zw = soup.find(attrs={“class”:“box_con”})
完整代码:
# -*- coding: utf-8 -*- import os import re import csv import time import json import random import urllib.request from lxml import etree from bs4 import BeautifulSoup from selenium import webdriver from selenium.webdriver.chrome.options import Options #-------------------------------------------------写入文件------------------------------------------------- path = os.getcwd() + "/yqkx_data.csv" csvfile = open(path, 'a', newline='', encoding = 'utf-8-sig') writer = csv.writer(csvfile) writer.writerow(('序号','文章标题','发布时间','文章链接','文章内容')) #--------------------------------------------YQ快讯-数据抓取--------------------------------------------- url = "http://society.people.com.cn/GB/369130/431577/431608/index.html" driver = webdriver.Chrome() #chromedriver.exe置于python37根目录 driver.implicitly_wait(5) chrome_option = webdriver.ChromeOptions() driver.get(url) #打开网页网页 driver.implicitly_wait(6) #等待加载六秒 #-------------------------------------------------获取标题------------------------------------------------- titles = driver.find_elements_by_xpath('//div[@class=" p2j_list_lt fl"]/ul/li') for t in titles: print(t.text) links = driver.find_elements_by_xpath('//div[@class=" p2j_list_lt fl"]/ul/li/a') for link in links: print(link.get_attribute('href')) print("\n\n==========================================================") #-------------------------------------------------获取正文------------------------------------------------- def get_content(url): print(url) try: content = urllib.request.urlopen(url).read() soup = BeautifulSoup(content,"html.parser") #来源 ly = soup.find(attrs={"class":"fl"}).get_text() #print(ly) #正文 zw = soup.find(attrs={"class":"box_con"}) #防止某些文章仅图片 if zw is not None: zw = zw.get_text() zw = zw.replace("\n", "") else: zw = "" print(zw) print("succeed") return ly,zw except Exception as e: zw = e.partial ly = "" print("except") print(zw) return ly, page #-------------------------------------------------写入文件------------------------------------------------- k = 0 while k<len(titles): #序号 num = str(k+1) #文章标题和发布时间 value = titles[k].text.split('\n') con_title = value[0] con_time = value[1] #文件链接 url = links[k].get_attribute('href') #获取来源和正文 ly,zw = get_content(url) content = (num, con_title, con_time, url, zw) #文件写入操作 writer.writerow((content)) k = k + 1 #文件关闭 csvfile.close()
数据抓取如下图所示:
存储至CSV文件如下图所示:
二.文本关键词提取
作者抓取了多个专栏,汇总相关数据如下图所示(可从github下载)。由于论文原因,作者仅公开每个专栏的50篇新闻,包括:八方支援、各地动态、抗疫英雄、权威解读、人民网评、实况武汉、一线守护等。
数据如下图所示:
作者提取新闻正文内容或新闻标题进行词频分析,存储为“all-data.txt”。
接下来的代码是中文分词,并提取每条新闻排名前50的关键词,作为后续的共现分析和知识图谱构建。
# coding=utf-8 import jieba import re import time from collections import Counter from snownlp import SnowNLP #------------------------------------中文分词------------------------------------ cut_words = "" all_words = "" f = open('all-data-key.txt', 'w', encoding='utf-8') for line in open('all-data.txt', encoding='utf-8'): line = line.strip('\n') #停用词过滤 line = re.sub('[0-9’!"#$%&\'()*+,-./:;<=>?@,。?★、…【】《》?“”‘’![\\]^_`{|}~\s]+', "", line) seg_list = jieba.cut(line, cut_all=False) cut_words = (" ".join(seg_list)) #计算关键词 all_words = cut_words.split() c = Counter() for x in all_words: if len(x)>1 and x != '\r\n': c[x] += 1 #Top50 output = "" #print('\n词频统计结果:') for (k,v) in c.most_common(50): #print("%s:%d"%(k,v)) output += k + " " f.write(output+"\n") else: f.close()
运行结构如下图所示,每一行表示一条新闻的Top50关键词,接下来需要计算它们的共现矩阵。
三.共现矩阵
引文分析常见的包括两类,一种是共现关系,另一种是引用和被引用关系。本文主要讲解共现关系,假设现在存在三篇文章,如下所示:
文章标题 作者 大数据发展现状分析 A,B,C Python网络爬虫 A,D,C 贵州省大数据战略 D,B
(1) 首先写代码抓取该领域文章的所有作者或关键词,即:A、B、C、D。
(2) 接着获取对应的共现矩阵,比如文章“大数据发展现状分析”,则认为A、B、C共现,在他们之间建立一条边。共现矩阵如下所示:
[−ABCDA0121B1011C2101D1110](1) \left[ \begin{matrix} -& A & B & C & D \\ A & 0 & 1 & 2 & 1 \\ B & 1 & 0 & 1 & 1 \\ C & 2 & 1 & 0 & 1 \\ D & 1 & 1 & 1 & 0 \end{matrix} \right] \tag{1} ⎣⎢⎢⎢⎢⎡−ABCDA0121B1011C2101D1110⎦⎥⎥⎥⎥⎤(1)
(3) 通过共现矩阵分别获取两两关系及权重,再写入CSV或Excel文件中,如下所示。
[SourceTargetWeightAB1AC2AD1BC1BD1CD1](2) \left[ \begin{matrix} Source & Target & Weight \\ A & B & 1 \\ A & C & 2 \\ A & D & 1 \\ B & C & 1 \\ B & D & 1\\ C & D & 1 \end{matrix} \right] \tag{2} ⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡SourceAAABBCTargetBCDCDDWeight121111⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤(2)
(4) 将该CSV文件导入Gephi中,并绘制相关的图形。因为该实例节点比较少,下面是Pyhton调用Networkx绘制的代码及图形。
# -*- coding: utf-8 -*- import networkx as nx import matplotlib.pyplot as plt #定义有向图 DG = nx.Graph() #添加五个节点(列表) DG.add_nodes_from(['A', 'B', 'C', 'D']) print(DG.nodes()) #添加边(列表) DG.add_edge('A', 'B', weight=1) DG.add_edge('A', 'C', weight=2) DG.add_edge('A', 'D', weight=1) DG.add_edge('B', 'C', weight=1) DG.add_edge('B', 'D', weight=1) DG.add_edge('C', 'D', weight=1) #DG.add_edges_from([('A', 'B'), ('A', 'C'), ('A', 'D'), ('B','C'),('B','D'),('C','D')]) print(DG.edges()) #绘制图形 设置节点名显示\节点大小\节点颜色 colors = ['red', 'green', 'blue', 'yellow'] nx.draw(DG,with_labels=True, node_size=900, node_color = colors) plt.show()
绘制图形如下所示:
大家也可以采用PyEcharts绘制网络图、Neo4j图数据库绘制关系图。由于我们的数据集比较多,故推荐大家使用Gephi软件绘制相关图形,而且图形比较美观。
四.主题关键词共现分析
下面的代码是获取每条新闻主题关键词的共现矩阵,代码如下:
# -*- coding: utf-8 -*- """ @author: eastmount CSDN 2020-04-12 """ import pandas as pd import numpy as np import codecs import networkx as nx import matplotlib.pyplot as plt import csv from scipy.sparse import coo_matrix #---------------------------第一步:读取数据------------------------------- word = [] #记录关键词 f = open("all-data-key.txt", encoding='utf-8') line = f.readline() while line: #print line line = line.replace("\n", "") #过滤换行 line = line.strip('\n') for n in line.split(' '): #print n if n not in word: word.append(n) line = f.readline() f.close() print(len(word)) #关键词总数 #--------------------------第二步 计算共现矩阵---------------------------- a = np.zeros([2,3]) print(a) #共现矩阵 #word_vector = np.zeros([len(word),len(word)], dtype='float16') #MemoryError:矩阵过大汇报内存错误 #采用coo_matrix函数解决该问题 print(len(word)) #类型<type 'numpy.ndarray'> word_vector = coo_matrix((len(word),len(word)), dtype=np.int8).toarray() print(word_vector.shape) f = open("all-data-key.txt", encoding='utf-8') line = f.readline() while line: line = line.replace("\n", "") #过滤换行 line = line.strip('\n') #过滤换行 nums = line.split(' ') #循环遍历关键词所在位置 设置word_vector计数 i = 0 j = 0 while i<len(nums): #ABCD共现 AB AC AD BC BD CD加1 j = i + 1 w1 = nums[i] #第一个单词 while j<len(nums): w2 = nums[j] #第二个单词 #从word数组中找到单词对应的下标 k = 0 n1 = 0 while k<len(word): if w1==word[k]: n1 = k break k = k +1 #寻找第二个关键字位置 k = 0 n2 = 0 while k<len(word): if w2==word[k]: n2 = k break k = k +1 #重点: 词频矩阵赋值 只计算上三角 if n1<=n2: word_vector[n1][n2] = word_vector[n1][n2] + 1 else: word_vector[n2][n1] = word_vector[n2][n1] + 1 #print n1, n2, w1, w2 j = j + 1 i = i + 1 #读取新内容 line = f.readline() f.close() #--------------------------第三步 TXT文件写入-------------------------- res = open("word_word_weight.txt", "a+", encoding='utf-8') i = 0 while i<len(word): w1 = word[i] j = 0 while j<len(word): w2 = word[j] #判断两个词是否共现 共现&词频不为0的写入文件 if word_vector[i][j]>0: #print w1 +" " + w2 + " "+ str(int(word_vector[i][j])) res.write(w1 +" " + w2 + " "+ str(int(word_vector[i][j])) + "\n") j = j + 1 i = i + 1 res.close() #--------------------------第四步 CSV文件写入-------------------------- c = open("word-word-weight.csv","w", encoding='utf-8', newline='') #解决空行 #c.write(codecs.BOM_UTF8) #防止乱码 writer = csv.writer(c) #写入对象 writer.writerow(['Word1', 'Word2', 'Weight']) i = 0 while i<len(word): w1 = word[i] j = 0 while j<len(word): w2 = word[j] #判断两个词是否共现 共现词频不为0的写入文件 if word_vector[i][j]>0: #写入文件 templist = [] templist.append(w1) templist.append(w2) templist.append(str(int(word_vector[i][j]))) #print templist writer.writerow(templist) j = j + 1 i = i + 1 c.close()
输出结果如下所示:
5267 [[0. 0. 0.] [0. 0. 0.]] 5267 (5267, 5267)
生成如下图所示共现关系,主题词word1和word2共现weight词,共计33,0341条关系。
由于主题关系较多会影响绘制的知识图谱,而我们的分析目的是提取核心关键词的关联关系。因此接下来需要进行数据预处理,将关系权重(Weight)小于等于9的都过滤。最终得到“word-word-weight-gl9.csv”文件,共计3177条关系。
五.Gephi绘制主题知识图谱
1.数据准备
实体构建:324个主题关键词或实体
构建实体表“entity.csv”,包括id编号和label类标名称,共324个主题关键词(实体),如下图所示。这里采用的方法是将“word-word-weight-gl9.csv”文件的Word1和Word2关键词复制至一列并删除重复项,而真实的知识图谱需要通过命令实体识别来提取,如果想知道这部分内容,后续我也可以尝试分享。
关系构建:3177条关系
构建关系表“relationship.csv”,包括Source起始实体、Target目标实体、Type类型(无方向)和Weight权重,共3177条三元关系<实体,关系,实体>,如下图所示。
2.导入数据
第一步,新建工程,并选择“数据资料”,输入电子表格。
第二步,导入节点表格,选择entity实体表。
第三步,导入数据如下图所示,设置为“边表格”,注意CSV表格数据一定设置为 Source(起始点)、Target(目标点)、Weight(权重),这个必须和Gephi格式一致,否则导入数据会提示错误。
导入数据如下图所示,它们是无向图。
第四步,导入成功后点击“概览”显示如下所示,接着就是调整参数。
3.调整参数绘制图谱
设置外观如下图所示,主要包括颜色、大小、标签颜色、标签尺寸。
第一步,设置节点大小和颜色。
选中颜色,点击“数值设定”,选择渲染方式为“度”。
显示结果如下所示:
接着设置节点大小,数值设定为“度”,最小尺寸为20,最大尺寸为120。
第二步,设置模块化。
在右边统计中点击“运行”,设置模块性。
第三步,设置平均路径长度。
在右边统计中点击“运行”,设置边概述。
第四步,重新设置节点属性。
节点大小数值设定为“度”,最小值还是20,最大值还是120。节点颜色数值设定为“Modularity Class”,表示模块化。
第五步,设置边大小和颜色。
设置边颜色的数值设定为“边的权重”,如下图所示。
设置边的大小数值设定为“边的权重”。
第六步,在布局中选择“Fruchterman Reingold”。
调整区、重力和速度。
显示结果如下所示:
第七步,点击预览。
设置宋体字,显示标签,透明度调整为20,如下图所示。
最终结构如下图所示。
导出PNG、PDF、SVG如下图所示。
4.图谱优化
第一步,图谱调整。
选择喜欢的颜色。
边的厚度调整。
最终显示结果如下图所示:
第二步,权重过滤。
我们可以使用滤波功能过滤一些不重要的点,让重要的点清晰可见。滤波可以对节点做过滤,也可以对边做过滤。节点过滤:在属性中,可以做到节点的过滤,可以通过节点的lable、weight做等于、范围值、非空等过滤。如下图,就是通过节点的weight进行了范围的过滤,过滤掉了低weight值的节点,让这个图形不重要的节点变少。
在右上有一个“上下文”,展示的节点量、边量,做完过滤之后,这块会展示过滤后的量和占比。
做完了过滤之后,仍然可以继续执行布局的自动运行,直到节点的排列符合你的目的。
从下图可以看到一个大的社群,由三个小社群组成(粉色圈、黑色圈和部分灰色圈),他们之间通过两个uid彼此链接在了一起。将一个粉圈的头目和一个黑圈头目,看似一点也不相关的账户给联系在了一起。是不是就达到了通过一个用户查找到群体的目的呀~
最后删除掉无关联的节点,可以移动到一起区域删除,最终得到如下图所示的知识图谱。不知道是否有更好的方法?
最终得到如下图所示的知识图谱。
我们也可以设置其他布局,如下图所示:
最终如下图所示,如果增加停用词过滤效果更好些。
六.总结
写到这里,第五篇YQ分析的文章就讲解完毕,希望对您有所帮助,尤其是想写文本挖掘论文的读者。后续还会分享舆情分析、威胁情报溯源、预测预警及AI和NLP应用等。如果文章对您有所帮助,将是我写作的最大动力。作者将源代码上传至github,大家可以直接下载。你们的支持就是我撰写的最大动力,加油~
同时,向钟院士致敬,向一线工作者致敬。侠之大者,为国为民。咱们中国人一生的最高追求,为天地立心,为生民立命,为往圣继绝学,为万世开太平。以一人之力系万民康乐,以一身犯险保大业安全。他们真是做到了,武汉加油,中国加油!
(By:Eastmount 2020-04-12 周末下午5点于贵阳 http://blog.csdn.net/eastmount/)
参考文献:
[1] [关系图谱] 一.Gephi通过共现矩阵构建知网作者关系图谱
[2] [关系图谱] 二.Gephi导入共线矩阵构建作者关系图谱
[3] [Python知识图谱] 一.哈工大pyltp安装及中文分句、中文分词、导入词典基本用法
[4] [Python知识图谱] 二.哈工大pyltp词性标注、命名实体识别、依存句法分析和语义角色标注
[5] [Python知识图谱] 三.Jieba工具中文分词、添加自定义词典及词性标注详解
[6] [Python知识图谱] 四.Python和Gephi实现中国知网合作关系知识图谱
[7] 知识图谱相关会议之观后感分享与学习总结
[8] 中文知识图谱研讨会的学习总结 (上) 图谱引入、百度知心、搜狗知立方
[9] 搜索引擎和知识图谱那些事 (上).基础篇
[10] Gephi的使用–以社交网络图为例 - Yan Li
[11] Gephi简易学习[六]———— 拓展分析红楼梦数据
- 点赞 8
- 收藏
- 分享
- 文章举报
- [Pyhon疫情大数据分析] 三.新闻信息抓取及词云可视化、文本聚类和LDA主题模型文本挖掘
- [Pyhon疫情大数据分析] 四.微博话题抓取及新冠肺炎疫情文本挖掘和情感分析
- 大数据项目实战之新闻话题统计分析
- 利用Python+Gephi构建金庸人物知识图谱
- 大数据项目实战之新闻话题的实时统计分析
- 知识图谱构建摸索
- 程序员如何构建知识图谱,让自己更值钱?
- 知识图谱构建技术综述
- 知识图谱构建3——使用D2RQ将mysql数据转换成RDF数据
- 【知识图谱】杨娟:告别传统,基于知识图谱技术构建智能CRM
- [知识图谱实战篇] 一.数据抓取之Python3抓取JSON格式的电影实体
- 中文知识图谱构建方法研究2
- CCKS-2017 行业知识图谱构建与应用-下篇
- 大规模知识图谱的构建、推理及应用
- 知识图谱构建_百度文库
- 知识图谱构建5——Jena 和 Fuseki安装与SPARQL查询
- 【构建知识图谱neo4j】
- 3-知识图谱构建-知识图谱-自然语言处理
- 《基于Apache Kylin构建大数据分析平台》
- 中文知识图谱构建方法研究3