利用pyecharts绘制新浪微博传播图(文末附完整代码地址)
文章目录
- 任务
- 来龙去脉
- 过程
- 绘图代码
- 绘图参数分析
- 结点参数格式
- 联系参数格式
- 类别参数格式
- 总览
- 获取转发关系
- 构造数据结构
- 集成json文件
- 代码地址
任务
延续之前的爬虫任务,最初同学提出的设想是生成如下图所示:
来龙去脉
但彼时对爬虫还很陌生,对于如何构造这样的数据关系,利用何种包把数据展示出来都一无所知,因此先搁置了。
继分析完微博文本生成词云图后,想到将地区在地图上显示出统计图像应该是刚需,必定有现成的库可用。在广泛浏览相关信息后,决定选取pyecharts集成库。
但在下载安装后,发现网上现有的实例都无法使用,发现例子的版本普遍都是0.5,已经是老一代的。当然不甘于重装旧有的版本,追逐新潮。来到pyecharts的GitHub网站,
此前一直懵懂使用着GitHub,现在下决心掌握基本的使用。幸运看到了廖雪峰的Git教程,一两天的观摩与尝试基本了解,不再迷茫。
将项目clone到本地,成功运行出示例的地图后,在挖掘这个矿藏满满的宝库时,发现gallery中的关系图好像很贴切,在运行本地的Graph示例时,意外惊喜,正巧有我需要的图例:
真是“有心栽花花不开,无心插柳柳成荫”、“踏破铁鞋无觅处,得来全不费工夫”!(近日意识到自己语文能力骤降,需要常温习之)
于是,快马加鞭,开启逆向工程完成此项目。
过程
绘图代码
绘制图像的代码如下:
import json
import osfrom pyecharts.commons.utils import JsCode
from pyecharts import options as opts
from pyecharts.charts import Graph, Page
from pyecharts.faker import Collector
#可以在Jupyter Lab中渲染展示图片
from pyecharts.globals import CurrentConfig,NotebookType
CurrentConfig.NOTEBOOK_TYPE = NotebookType.JUPYTER_LABdef graph_weibo() -> Graph:with open(os.path.join("fixtures", "weibo.json"), "r", encoding="utf-8") as f:j = json.load(f)nodes, links, categories, cont, mid, userl = jc = (Graph().add("",nodes,links,categories,repulsion=50,linestyle_opts=opts.LineStyleOpts(curve=0.2),label_opts=opts.LabelOpts(is_show=False),#True),#).set_global_opts(legend_opts=opts.LegendOpts(is_show=False),#True),#title_opts=opts.TitleOpts(title="Graph-微博转发关系图"),))return c
分别运行
c = graph_weibo()
c.load_javascript()
c.render_notebook()
出现传播图:
绘图参数分析
绘图所需的参数通过读取json文件传递:
with open(os.path.join("fixtures", "weibo.json"), "r", encoding="utf-8") as f:j = json.load(f)
打开本地的weibo.json文件观察,如赋值的提示:
nodes, links, categories, cont, mid, userl = j
json文件由含六个元素的列表构成,分别包括了结点,联系,类别,微博文本,微博mid与博主昵称。
结点参数格式
每个结点由包括如下信息的字典组成
{"name": "Camel3942", //转发博主昵称"symbolSize": 5, //图中标志大小 "draggable": "False", //是否可拖动"value": 1, //被再次转发次数"category": "Camel3942", //被再次转发后,属于以本博主昵称命名的类,否则属于转发来源博主的类"label": { //此博主被再次转发后,含有此标签,否则不含"normal": {"show": "True"}}},……
对比一个没有被二次转发的博主结点格式:
{"name": "超昂闪存","symbolSize": 5,"draggable": "False","value": 0,"category": "重工组长于彦舒"},……
联系参数格式
此信息比较简明,一条转发微博的来源source以及该微博博主target。
具体来讲,如果此微博博主直接转发原文微博,则source为原文微博博主,如果二次转发其他人转发的该微博,则source为其他人。
{"source": "新浪体育","target": "Beijingold4"},{"source": "麻黑浮云","target": "X一块红布"},……
类别参数格式
更加简明,所有被二次转发过的博主昵称:
{"name": "Camel3942"},{"name": "Christinez"},{"name": "JoannaBlue"},……
分析,传入类别后能够将该类作为一个整体渲染效果,如下所示:
总览
获取转发关系
通过分析微博文本得知转发人信息的HTML文本基本结构如下:
// <a href=’/n/被转发博主昵称’>@被转发博主昵称:
例如一个含转发信息的微博正文
“//@宇字号汤包or汤圆:红十字会依然是当年的红十字会,郭美美事件一点都没有改变它”
的text内容为:
“//<a href=’/n/宇字号汤包or汤圆’>@宇字号汤包or汤圆:红十字会依然是当年的红十字会,郭美美事件一点都没有改变它”
利用之前对正则表达式的基础了解,书中涉及到python中的re模块具有功能。
最初的一个版本能够运行成功
但有一个出现问题,并未获得正确昵称:
这个问题在example的文件中也有体现,当时并未过分关心原因,只当笑话:
判断为字符匹配错误,将该用户文本调出。
根据编程报错的经验,猜测可能是中英文格式的字符原因,将文本中的 冒号:
替换至程序中的冒号:
,果然报出了之前让我摸不着头脑的错误类型:
这个错误应该是微博内部的错误。我需要将这个错误解决。即在字符匹配处增加筛选条件。英文的冒号字符和中文的冒号字符都做筛选。
最终代码如下,获取文本中含有的转发来源博主昵称:
import re
#工具类
class Tool: repostEN=re.compile('//<a.*?>@(.*?)</a>:')#英文字符冒号repostCN=re.compile('//<a.*?>@(.*?)</a>:')#中文字符冒号@classmethoddef findSource(cls,x):sourceName=''xEN=xCN=''xEN = re.findall(cls.repostEN,x)xCN = re.findall(cls.repostCN,x)#如果其中一者存在,另一者不存在,即返回该者if(len(xCN)==0 and len(xEN)>0):sourceName=xEN[0]#print(xEN[0])elif(len(xEN)==0 and len(xCN)>0):sourceName=xCN[0]#print(xCN[0]) #若二者都存在,则返回第一位置字符串较小的elif(len(xEN)>0 and len(xCN)>0):sourceName=xCN[0] if(len(xEN[0])>len(xCN[0])) else xEN[0]return sourceName
构造数据结构
沿用自制集成的爬取工具,通过修改配置就可以得到需要的数据。
提取关键的数据,并存储在字典中,设计为Categories类方便集成调用
choice='转发'#'原文'#
categories=Categories()for name,text in zip(dataDict[choice+'screen_name'],dataDict[choice+'text']):if categories.nameExist(name) is False:categories.add(name)sourceName=(Tool.findSource(text))if sourceName is not '': categories.addTarget(sourceName,name)else:categories.addTarget(tweeter,name)
由于统计每个结点的转发量为转发后所有结点总合,故需要在结束统计后进行全局运算,加入countAll(self,name)
方法;
由于删博及爬取的时效性等多种原因,有的微博出现数据缺失情况,加入fillSource(self,tweeter)
方法解决。
最终Categories类如下:
class Categories:def __init__(self):self.compose={}def add(self,name):self.compose[name]={}category=self.compose[name]category['value']=0 #记录被转次数category['target']={}category['source']={}def nameExist(self,name):if self.compose.get(name) is None: return Falseelse:return Truedef addTarget(self,sourceName,targetName):if self.nameExist(sourceName) is False:self.add(sourceName)if self.nameExist(targetName) is False:self.add(targetName)##防止循环调用 if sourceName == targetName:#print(sourceName)return if self.compose[targetName]['source'].get(sourceName) is not None:#print(sourceName)self.compose[targetName]['source'].pop(sourceName)if self.compose[targetName]['source'].get(sourceName) is None:self.compose[targetName]['source'][sourceName]=1else:self.compose[targetName]['source'][sourceName]+=1 if self.compose[sourceName]['target'].get(sourceName) is None:self.compose[sourceName]['target'][targetName]=1else:self.compose[sourceName]['target'][targetName]+=1self.compose[sourceName]['value']+=1 def countAll(self,name): targets=self.compose[name]['target']if targets == {}:self.compose[name]['value']=0else:for targetName in targets:if self.compose[targetName]['target']=={}:self.compose[targetName]['value']=0#self.compose[name]['value']+=1else:self.countAll(targetName)self.compose[name]['value']+=self.compose[targetName]['value']#数据缺失补充 假定为转发原博主 def fillSource(self,tweeter):for item in self.compose:source=self.compose[item].get('source')if (len(source))!=1 and item !=tweeter:self.addTarget(tweeter,item)
集成json文件
此后便是根据获取的数据构建json文件
nodes=[]
links=[]
category=[]for i in categories.compose:value=categories.compose[i]['value']try:source=list(categories.compose[i]['source'])[0]except:source=tweeternode={ "name":i,"symbolSize": 5,"draggable": "False","value": value,"category": source}if value > 0:if i==tweeter:node["category"]=i#change nodeif source !=tweeter:#print(i)node["category"]=isymbolSize=value//10 if symbolSize>5:node['symbolSize']=symbolSizenode['label']={"normal": {"show": "True"}}#add linktargets=categories.compose[i]['target']if targets != {}:for target in targets:links.append({'source':i,'target':target})#归入categorycategory.append({'name':i})nodes.append(node)content='wuhan'
mid='4444444444444'
tweeter=tweeterjsonData=[nodes,links,category,content,mid,tweeter]
写入文件:
import jsontestFile=addrFile(tweeter,'.json')
with open(testFile,'w',encoding='utf-8') as file_obj:json.dump(jsonData,file_obj)
file_obj.close()
至此,以该文件替换文章开头处的文件地址即可得到新的数据图像。
当然,调整图像结点的大小还需要进一步修正以获取美观图像。
代码地址
将可运行的完整jupyter notebook文件上传至我的GitHub测试项目中,方便有需要者自取。
利用pyecharts绘制新浪微博传播图(文末附完整代码地址)相关推荐
- 吴恩达机器学习python实现(6):SVM支持向量机(文末附完整代码)
所有的数据来源:链接:https://pan.baidu.com/s/1vTaw1n77xPPfKk23KEKARA 提取码:5gl2 1 Support Vector Machines 1.1 Pr ...
- 【控制系统数字仿真与CAD——实验报告】实验三:离散相似法数字仿真(文末附完整代码 + 实验结果)
一.实验目的 1. 了解离散相似法的基本原理 2. 掌握离散相似法仿真的基本过程 3. 应用离散相似法仿真非线性系统 4. MATLAB实现离散相似法的非线性系统仿真 5. 掌握SIMULINK仿真方 ...
- 【控制系统数字仿真与CAD——实验报告】实验四:黄金分割法最优化PI调节器参数(文末附完整代码 + 实验结果)
一.实验目的 掌握控制系统计算机辅助设计的原理与方法: 掌握黄金分割法的基本原理: 掌握黄金分割法在参数优化中的应用: 掌握MATLAB的基本编程,实现闭环系统的数字仿真,并增加参数优化过程: 掌握M ...
- python下载某短视频平台音视频、评论、点赞数(详细教程,文末附完整代码
前言 整理一下python在抖音网页版的应用 以抓取一个视频及评论为例进行讲解 获取视频 url 随便找一个视频,点击进入详情,页面中地址栏里就是该视频的 url . 手机端复制链接后,先粘到浏览器地 ...
- echarts 折现图和柱状图 样式修改 设置折线样式 背景(文末附带完整代码)
1.设置折线图样式(修改后)(背景竖条纹间隔,去掉边框,设置折线和节点颜色,设置数据字体颜色) 设置折线样式: 设置折线图的背景样式: 2.设置柱状图样式(修改后) 设置柱子的样式 设置柱状图背景 完 ...
- CVE-2020-1938漏洞复现(文末附EXP代码)
CVE-2020-1938 Apache Tomcat 文件包含漏洞复现 1 环境搭建 1.1 Vulhub靶机搭建 1.1.1 环境安装 (1)安装docker $ curl -fsSL https ...
- echarts 三种数据双y轴显示 (文末附带完整代码)
说明:网络引用echarts.js和直接下载echarts引用的样式可能会不一致,需要对折线的样式和字体进行修改的请参考我的另外一篇文章https://blog.csdn.net/Wangwangwa ...
- 分布式数据库九大发展趋势|文末附完整报告下载
随着数据成为第五大生产要素,新兴软硬件技术快速发展,各行各业的数据呈指数式增长,传统集中式数据库面对海量数据存储.高并发等场景的局限性愈发凸显.分布式数据库凭借高可用.高可扩展性.高性价比等优势,已经 ...
- 入门C语言第三话:数组之实战篇——扫雷(进阶版——图形化界面,递归展开,播放音乐与音效,标记取消雷,记录雷的个数,鼠标点击,文末附有完整代码)
文章目录 前言 每日鸡汤 基本思路 衔接基础班扫雷 准备阶段 正文 一.雷盘信息的存储 1.设置雷盘11*11与初始化 2.放置雷 3.放置雷周围的信息 二.图形化界面 1.创建与初始化窗口 2.加载 ...
最新文章
- javascript跨域解决方案
- boost::math::quadrature::tanh_sinh用法的测试程序
- ITK:标记连接组件的轮廓
- 买了台任天堂Switch
- oracle导入del数据文件,pl/sql,Oracle数据库中,不小心delete数据并递交后如何恢复被删数据...
- 生成验证码图片的Java代码
- VB6.0操作SQL Server——增删改查
- 域名型通配符ssl证书_西部数码使用指南:申请了主域名SSL证书,是否还需要申请www域名的...
- Matlab之数据的输入与输出
- uva11992-Fast Matrix Operations(区间增值、改值)
- 0x0000006B蓝屏解决方法
- Dapr+Net6 服务调用09:集群指标收集-普罗米修斯
- FPGA VerilogHDL语言 数字钟 按键消抖
- 一、微信小程序拼团项目简介
- 一级建造师考试备考顺序
- linux shell翻译英文脚本
- 计算机专业选择福大还是南邮,48所院校考研历年报录比汇总,21考研可参考!...
- 商业银行表内业务与表外业务
- 2021.3.12日报:修复miniblink vip版本的性能问题
- 阅读笔记——2019_004 A SURVEY OF TECHNIQUES FOR EVENT DETECTION IN TWITTER
热门文章
- 大学计算机基础专升本复习提纲
- 锐安信sslTrus 5年期证书订阅套餐 简化SSL证书管理
- 微信公众号主体注销了,如何办理账号迁移?
- 网站如何锁定用户,超级浏览器有办法解决吗?
- 百度坐标转WGS84
- arm汇编中DCB、DCW、DCD、DCQ指令
- centos7磁盘清理方法
- 我可以处理Flutter集成百度地图问题解决
- because it violates the following Content Security Policy directive: “default-src ‘none‘“
- BZOJ5185: [Usaco2018 Jan]Lifeguards