文章目录

  • 任务
  • 来龙去脉
  • 过程
    • 绘图代码
    • 绘图参数分析
      • 结点参数格式
      • 联系参数格式
      • 类别参数格式
      • 总览
    • 获取转发关系
    • 构造数据结构
    • 集成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绘制新浪微博传播图(文末附完整代码地址)相关推荐

  1. 吴恩达机器学习python实现(6):SVM支持向量机(文末附完整代码)

    所有的数据来源:链接:https://pan.baidu.com/s/1vTaw1n77xPPfKk23KEKARA 提取码:5gl2 1 Support Vector Machines 1.1 Pr ...

  2. 【控制系统数字仿真与CAD——实验报告】实验三:离散相似法数字仿真(文末附完整代码 + 实验结果)

    一.实验目的 1. 了解离散相似法的基本原理 2. 掌握离散相似法仿真的基本过程 3. 应用离散相似法仿真非线性系统 4. MATLAB实现离散相似法的非线性系统仿真 5. 掌握SIMULINK仿真方 ...

  3. 【控制系统数字仿真与CAD——实验报告】实验四:黄金分割法最优化PI调节器参数(文末附完整代码 + 实验结果)

    一.实验目的 掌握控制系统计算机辅助设计的原理与方法: 掌握黄金分割法的基本原理: 掌握黄金分割法在参数优化中的应用: 掌握MATLAB的基本编程,实现闭环系统的数字仿真,并增加参数优化过程: 掌握M ...

  4. python下载某短视频平台音视频、评论、点赞数(详细教程,文末附完整代码

    前言 整理一下python在抖音网页版的应用 以抓取一个视频及评论为例进行讲解 获取视频 url 随便找一个视频,点击进入详情,页面中地址栏里就是该视频的 url . 手机端复制链接后,先粘到浏览器地 ...

  5. echarts 折现图和柱状图 样式修改 设置折线样式 背景(文末附带完整代码)

    1.设置折线图样式(修改后)(背景竖条纹间隔,去掉边框,设置折线和节点颜色,设置数据字体颜色) 设置折线样式: 设置折线图的背景样式: 2.设置柱状图样式(修改后) 设置柱子的样式 设置柱状图背景 完 ...

  6. CVE-2020-1938漏洞复现(文末附EXP代码)

    CVE-2020-1938 Apache Tomcat 文件包含漏洞复现 1 环境搭建 1.1 Vulhub靶机搭建 1.1.1 环境安装 (1)安装docker $ curl -fsSL https ...

  7. echarts 三种数据双y轴显示 (文末附带完整代码)

    说明:网络引用echarts.js和直接下载echarts引用的样式可能会不一致,需要对折线的样式和字体进行修改的请参考我的另外一篇文章https://blog.csdn.net/Wangwangwa ...

  8. 分布式数据库九大发展趋势|文末附完整报告下载

    随着数据成为第五大生产要素,新兴软硬件技术快速发展,各行各业的数据呈指数式增长,传统集中式数据库面对海量数据存储.高并发等场景的局限性愈发凸显.分布式数据库凭借高可用.高可扩展性.高性价比等优势,已经 ...

  9. 入门C语言第三话:数组之实战篇——扫雷(进阶版——图形化界面,递归展开,播放音乐与音效,标记取消雷,记录雷的个数,鼠标点击,文末附有完整代码)

    文章目录 前言 每日鸡汤 基本思路 衔接基础班扫雷 准备阶段 正文 一.雷盘信息的存储 1.设置雷盘11*11与初始化 2.放置雷 3.放置雷周围的信息 二.图形化界面 1.创建与初始化窗口 2.加载 ...

最新文章

  1. javascript跨域解决方案
  2. boost::math::quadrature::tanh_sinh用法的测试程序
  3. ITK:标记连接组件的轮廓
  4. 买了台任天堂Switch
  5. oracle导入del数据文件,pl/sql,Oracle数据库中,不小心delete数据并递交后如何恢复被删数据...
  6. 生成验证码图片的Java代码
  7. VB6.0操作SQL Server——增删改查
  8. 域名型通配符ssl证书_西部数码使用指南:申请了主域名SSL证书,是否还需要申请www域名的...
  9. Matlab之数据的输入与输出
  10. uva11992-Fast Matrix Operations(区间增值、改值)
  11. 0x0000006B蓝屏解决方法
  12. Dapr+Net6 服务调用09:集群指标收集-普罗米修斯
  13. FPGA VerilogHDL语言 数字钟 按键消抖
  14. 一、微信小程序拼团项目简介
  15. 一级建造师考试备考顺序
  16. linux shell翻译英文脚本
  17. 计算机专业选择福大还是南邮,48所院校考研历年报录比汇总,21考研可参考!...
  18. 商业银行表内业务与表外业务
  19. 2021.3.12日报:修复miniblink vip版本的性能问题
  20. 阅读笔记——2019_004 A SURVEY OF TECHNIQUES FOR EVENT DETECTION IN TWITTER

热门文章

  1. 大学计算机基础专升本复习提纲
  2. 锐安信sslTrus 5年期证书订阅套餐 简化SSL证书管理
  3. 微信公众号主体注销了,如何办理账号迁移?
  4. 网站如何锁定用户,超级浏览器有办法解决吗?
  5. 百度坐标转WGS84
  6. arm汇编中DCB、DCW、DCD、DCQ指令
  7. centos7磁盘清理方法
  8. 我可以处理Flutter集成百度地图问题解决
  9. because it violates the following Content Security Policy directive: “default-src ‘none‘“
  10. BZOJ5185: [Usaco2018 Jan]Lifeguards