总览:
*输入:*关键词
*输出:*分日期情感均值折线图,主题词云,分省市情感均值折线图

一、微博数据爬取

1.爬取指定关键词相关的微博
2.根据爬取到的微博信息爬取到相关的评论数据
这里主要借鉴了

https://github.com/dataabc/weibo-crawler

3.将零散的单个微博下的所有评论整合在一个excel文件中,这里利用我的上一篇博客中的方法进行合并,得到总体的数据。

二、百度情感分析

我使用的是Python的SDK,详细使用见百度。
在配置好baidu-aip后,直接提取上一步获取到的评论数据进行百度情感分析,并写入新的excel文件中,代码如下,涉及微博表情字符化处理、提取excel文件中的一列、处理baidu-aip的并发限制问题等内容。

#coding=utf-8
from aip import AipNlp
import xlrd
import re
import xlwt
import time as t
""" 
你的 APPID AK SK 
每秒钟只能调用两次
"""
APP_ID = ''
API_KEY = ''
SECRET_KEY = ''
client = AipNlp(APP_ID, API_KEY, SECRET_KEY)

def filter_emoji(content):
	try:
	    # Wide UCS-4 build
	    cont = re.compile(u'['u'\U0001F300-\U0001F64F' u'\U0001F680-\U0001F6FF'u'\u2600-\u2B55]+')
	except re.error:
	    # Narrow UCS-2 build
	    cont = re.compile(u'('u'\ud83c[\udf00-\udfff]|'u'\ud83d[\udc00-\ude4f\ude80-\udeff]|'u'[\u2600-\u2B55])+')
	return cont.sub (u'', str(content))

def extract(inpath):
    """提取数据"""
    data = xlrd.open_workbook(inpath, encoding_override='utf-8')
    table = data.sheets()[0]#选定表
    nrows = table.nrows#获取行号
    ncols = table.ncols#获取列号
    numbers=[]
    for i in range(1, nrows):#第0行为表头
        alldata = table.row_values(i)#循环输出excel表中每一行,即所有数据
        result_1 = alldata[1]#取出评论内容
        result_2 = alldata[2]#取出日期
        result_3 = alldata[3]#取出地区
        numbers.append([result_1,result_2,result_3])
    return numbers

def run(inpath):
    "运行程序,返回一个嵌套小列表的大列表"
    alls=[]#大列表
    all=extract(inpath)
    for i in all:#i是三个元素的小列表
        c=i[2]#日期
        b=i[1]#地区
        a=i[0]#评论内容
        a=filter_emoji(a)#表情过滤
        #a=re.sub(r'[^\u4e00-\u9fa5]','',str(a))#保证只有中文
        p = re.findall(r'回复@.*?:',a) #去除前面的无用文本
        if len(p) != 0:
            p=str(p[0])
            a=a.replace(p,'')
        else:
            pass
        if a.strip()=='':#如果a为空,就结束本次循环开始下次循环
            continue

        while True:#处理aps并发异常
            judge=client.sentimentClassify(a)#获取评论,进行情感判断
            if judge=={'error_code': 18, 'error_msg': 'Open api qps request limit reached'}:
                t.sleep(1)
                continue
            else:
                break
        if 'error_msg' in judge:#如果出现意外的报错,就结束本次循环
            continue
        print(judge)
        print(a)
        pm=judge['items'][0]['sentiment']#情感分类
        print(pm)
        pp=judge['items'][0]['positive_prob']#正向概率
        np=judge['items'][0]['negative_prob']#负向概率
        alls.append([c,b,a,pm,pp,np])
    return alls

def save_file(alls,name):
    """将一个时间段的所有评论数据保存在一个excle
    """
    f=xlwt.Workbook()
    sheet1=f.add_sheet(u'sheet1',cell_overwrite_ok=True)
    sheet1.write(0,0,'评论日期')
    sheet1.write(0,1,'所属地区')
    sheet1.write(0,2,'评论内容')
    sheet1.write(0,3,'情感极性')
    sheet1.write(0,4,'正向概率')
    sheet1.write(0,5,'负向概率')
    i=1
    #for all in alls:#遍历每一页
    for data in alls:#遍历每一行
        for j in range(len(data)):#取每一单元格
            sheet1.write(i,j,data[j])#写入单元格
        i=i+1#往下一行
    f.save(str(name))

if __name__ == "__main__":
    save_file(run('数据.xls'),'情感分析.xls')

三、绘制分日期正负情感均值折线图

1.在上一步我们得到了评论的情感值文件,因此需要进一步计算情感均值。
这里有两种算法:

  1. 将情感倾向为正的情感数值取为其正向概率[0.5-1],情感倾向为负的情感数值亦取其正向概率[0,0.5)。每日的正向情感均值为所有正向倾向的评论对应的正向概率之和除以其评论数量,负向情感均值同理。
  2. 将情感倾向为正的情感数值取为其正向概率[0-1],情感倾向为负的情感数值取其负向概率[0,1]。每日的正向情感均值为其所有正向倾向的评论对应的正向概率之和除以其评论数量再乘以正向评论数量在当日总评论数量(包含中性)的比重,负向情感均值同理。

我采用的是第二种。在对比了两个算法绘制出的折线图之和发现第二种更适合折线图分析。
有必要提一下,第一种算法是《重大公共卫生事件中的舆情分析方法研究——以新冠肺炎疫情为例》中应用的,第二种是我推敲出来的。
这里特别感谢该篇论文的作者团队于百忙之中给予的热心指导!
2.进行分日期的情感均值的计算,就要先进行日期的合并,这里使用datafrme方式进行日期的合并计算。

#coding='utf-8'
import xlrd
import xlwt
import datetime
import re
import pandas as pd
import numpy as np
import time

def avg(data,rate):
    #求列表的均值
    #第一个是列表,第二个是比率
    sum=0
    for i in data:
        sum=sum+i
    av=(sum/len(data))*rate
    return av
def avg_y(data):
    #求列表的均值
    #第一个是列表,第二个是比率
    sum=0
    for i in data:
        sum=sum+i
    av=sum/len(data)
    return av
def trans(date):
    """日期,必须是字符串"""
    #原算法适宜绘制地图,我的算法适宜折线图
    #算均值的算法有问题
    #尝试使用比例作为权重
    #原作者的算法:对于正向倾向文本取其正向概率,位于(0.5,1];对于负向倾向文本亦取其正向概率,位于[0,0.5)。
    #均值是将正向倾向的正向概率相加平均,负向倾向也是正向概率相加平均。
    c=[]#正向列表
    d=[]#负向列表
    e=[]#中性列表
    a=data.loc[str(date)]#选定索引为该日期的所有行
    #print(a)
    for row in a.itertuples(index=True, name='Pandas'):
        #print(getattr(row, "极性"), getattr(row, "正向概率"),getattr(row, "负向概率"))
        if getattr(row, "极性")==2:
            c.append(getattr(row, "正向概率"))#正向的概率值列表
        elif getattr(row, "极性")==3:
            d.append(getattr(row, "负向概率"))#负向的概率值列表
        elif getattr(row, "极性")==1:
            e.append(1)#中性列表,纯用作计数
        else:
            pass

    sum_0=len(c)+len(d)+len(e)#评论总数量
    rate_c=len(c)/sum_0#正向评论于该天占比
    rate_d=len(d)/sum_0#负向评论于该天占比
    d_c=avg(c,rate_c)
    d_d=avg(d,rate_d)
    print("正向均值:"+str(d_c))
    print("负向均值:"+str(d_d))
    nums=[date,d_c,d_d]
    return nums
def save_afile(all,file):
    """将降维后的数据保存在一个excle
        传递给一个列表的列表,和一个文件名
    """
    f=xlwt.Workbook()
    sheet1=f.add_sheet(u'sheet1',cell_overwrite_ok=True)
    sheet1.write(0,0,'日期')
    sheet1.write(0,1,'正向均值')
    sheet1.write(0,2,'负向均值')
    i=1
    for data in all:#遍历每一行
            for j in range(len(data)):#取每一单元格
                sheet1.write(i,j,data[j])#写入单元格
            i=i+1#往下一行
    f.save(file+'.xls')
def dates(start,end):
    """生成时间序列
          输入起止日期
    """
    d=[]
    a=pd.date_range(start,end,freq='D')
    for i in a:
        i=str(i).replace('00:00:00','')
        i=i.strip()
        d.append(i)
    return d

'''
trans函数得出一天的列表,
可不做中性的情感均值
生成两年的日期,遍历
汇总并写入新的excel
'''
if __name__ == '__main__':
    data_1=pd.read_excel(r'')#文件路径
    data = pd.DataFrame(data_1)#将excel文件读取并转换为dataframe格式
    print(data)
    data['日期'] = pd.to_datetime(data['日期'])
    data.set_index("日期", inplace=True)
    print(data)
    dates_0=dates('2020-01-10','2021-03-09')#日期序列生成
    #print(dates_0)
    alls=[]
    for i in dates_0:
        try:
            alls.append(trans(str(i)))
        except:
            continue
    print(alls)
    save_afile(alls,'每日评论情感值')
    print('OVER!')

3.获得每日的情感均值文件后,开始绘制折线图,由于我采用第二种算法,因此沿x轴对称的折线图更合适些。参照:

https://gallery.pyecharts.org/#/Line/rainfall_and_water_flow

绘制折线图代码如下:

#coding='utf-8'
import xlrd
import pyecharts.options as opts
from pyecharts.charts import Line, Grid

def extract(col):
    """提取数据
          路径+列号
    """
    data = xlrd.open_workbook(r'', encoding_override='utf-8')#文件
    table = data.sheets()[0]#选定表
    nrows = table.nrows#获取行号
    ncols = table.ncols#获取列号
    numbers=[]
    for i in range(1, nrows):#第0行为表头
        alldata = table.row_values(i)#循环输出excel表中每一行,即所有数据
        result_1 = alldata[col]#取出评论内容
        numbers.append(result_1)
    return numbers

dates=extract(0)#日期
pos=extract(1)#正向倾向
neg=extract(2)#负向倾向

l1 = (
    Line()
    .add_xaxis(xaxis_data=dates)
    .add_yaxis(
        series_name="正向情感",
        y_axis=pos,
        symbol_size=8,
        is_hover_animation=False,
        label_opts=opts.LabelOpts(is_show=False),
        linestyle_opts=opts.LineStyleOpts(width=1.5),
        is_smooth=True,
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(
            title="离婚冷静期前后公众正负向情感均值", subtitle="数据来自微博", pos_left="center"
        ),
        tooltip_opts=opts.TooltipOpts(trigger="axis"),
        axispointer_opts=opts.AxisPointerOpts(
            is_show=True, link=[{"xAxisIndex": "all"}]
        ),
        datazoom_opts=[
            opts.DataZoomOpts(
                is_show=True,
                is_realtime=True,
                start_value=30,
                end_value=70,
                xaxis_index=[0, 1],
            )
        ],
        xaxis_opts=opts.AxisOpts(
            type_="category",
            boundary_gap=False,
            axisline_opts=opts.AxisLineOpts(is_on_zero=True),
        ),
        yaxis_opts=opts.AxisOpts(max_=1, name="情感值"),
        legend_opts=opts.LegendOpts(pos_left="left"),
        toolbox_opts=opts.ToolboxOpts(
            is_show=True,
            feature={
                "dataZoom": {"yAxisIndex": "none"},
                "restore": {},
                "saveAsImage": {},
            },
        ),
    )
)

l2 = (
    Line()
    .add_xaxis(xaxis_data=dates)
    .add_yaxis(
        series_name="负向情感",
        y_axis=neg,
        xaxis_index=1,
        yaxis_index=1,
        symbol_size=8,
        is_hover_animation=False,
        label_opts=opts.LabelOpts(is_show=False),
        linestyle_opts=opts.LineStyleOpts(width=1.5),
        is_smooth=True,
    )
    .set_global_opts(
        axispointer_opts=opts.AxisPointerOpts(
            is_show=True, link=[{"xAxisIndex": "all"}]
        ),
        tooltip_opts=opts.TooltipOpts(trigger="axis"),
        xaxis_opts=opts.AxisOpts(
            grid_index=1,
            type_="category",
            boundary_gap=False,
            axisline_opts=opts.AxisLineOpts(is_on_zero=True),
            position="top",
        ),
        datazoom_opts=[
            opts.DataZoomOpts(
                is_realtime=True,
                type_="inside",
                start_value=30,
                end_value=70,
                xaxis_index=[0, 1],
            )
        ],
        yaxis_opts=opts.AxisOpts(is_inverse=True, name="情感值"),
        legend_opts=opts.LegendOpts(pos_left="7%"),
    )
)

(
    Grid(init_opts=opts.InitOpts(width="1200px", height="720px"))
    .add(chart=l1, grid_opts=opts.GridOpts(pos_left=50, pos_right=50, height="35%"))
    .add(
        chart=l2,
        grid_opts=opts.GridOpts(pos_left=50, pos_right=50, pos_top="55%", height="35%"),
    )
    .render("情感均值走势图.html")
)

四、制作主题词云

1.事先根据需要将评论内容依据时间段以及正负倾向划分为十个不同的txt文件。
2.准备好自建词表、停用词表文件。我会另发一篇帖子免费发布我整理的中文停用词表。这里记录一下词表去重代码:

#coding='utf-8'

list01 = []
for i in open('停用词表.txt',encoding='utf-8'):
    if i in list01:
        continue
    list01.append(i)
with open('停用词表去重.txt', 'w') as handle:
    handle.writelines(list01)
# test.txt 源文件
# test01.txt 输出文件

3.之后就是制作词云。本来是准备用BTM主题分析,但只迭代了6次就花费了15分钟,一个文件至少得迭代数百次,时间耗费太长,关于这部分的内容可以参见上文所述的论文。
因此我使用词频统计制作,代码如下:

#coding='utf-8'
import jieba  # 分词
import re
from wordcloud import WordCloud  # 词云图相关
import matplotlib.pyplot as plt
import matplotlib.colors as colors  # 处理图片相关内容
import numpy
from PIL import Image

# 创建停用词list
def stopwordslist(filepath):
    stopwords = [line.strip() for line in open(filepath, 'r', encoding='utf-8').readlines()]
    return stopwords
# 对句子进行分词
def seg_sentence(sentence):
    sentence_seged = jieba.cut(sentence.strip())
    stopwords = stopwordslist('停用词表.txt')  # 这里加载停用词的路径
    outstr = ''
    for word in sentence_seged:
        if word not in stopwords:
            word=re.sub(r'[^\u4e00-\u9fa5]','',str(word))#保证只有中文
            if word != '\t':
                outstr += word
                outstr += " "
    return outstr


def get_wcloud(file):
    tokenstr=[]
	# 读取文件内容
    inputs=open(file, 'r', encoding='utf-8') 
    # 加载词典
    jieba.load_userdict('自建词表.txt')
    # 也可以添加自定义词典
    for line in inputs:
        line_seg = seg_sentence(line)  # 这里的返回值是字符串
        tokenstr.append(line_seg)

    tokenstr=' '.join(tokenstr)
    print(tokenstr)
    # 打开背景图片
    color_mask = numpy.array(Image.open('圆.png'))
    # 自定义文字颜色
    colormaps = colors.ListedColormap(['#FF0000','#FF7F50','#FFE4C4'])
    # 生成词云(默认样式)
    # mywc1 = WordCloud().generate(tokenstr)
    # 生成词云(自定义样式)
    mywc1 = WordCloud(
        scale=10, #这个数值越大,产生的图片分辨率越高,字迹越清晰,最好不要超过64,运行很慢
        max_words=50, 
        mask=color_mask,  # 指定背景图形状
        colormap=colormaps,  # 指定颜色
        font_path='C:\Windows\Fonts\simhei.ttf',  # 指定字体
        background_color='white',  # 指定背景颜色,默认黑色
        width=1200,  # 指定宽度
        height=900  # 指定高度
    ).generate(tokenstr)
    # 显示词云
    plt.imshow(mywc1)
    plt.axis('off')
    #plt.show()
    mywc1.to_file(r'主题词云/负向/'+str(file).replace('负向语料/','')+'.png')  # 生成词云图片

if __name__ == '__main__':
    nams=['1.1-1.5.txt','1.5-3.8.txt','5.28-12.4.txt','5.28及以前.txt','12.4-次年1.1.txt']
    for i in nams:
        get_wcloud(r'负向语料/'+i)

五、绘制分省情感均值地图

上面实现了时间序列下的情感变动分析,最后来实现空间位置的情感均值分布可视化。
每个省市都有若干条评论,和绘制分日期的情感均值折线图一样,需要合并地区的情感值。
1.对省市的情感值计算其均值。同样使用第二种算法。代码如下:

#coding='utf-8'
import xlrd
import xlwt
import datetime
import re
import pandas as pd
import numpy as np
import time

def avg(data,rate):
    #求列表的均值
    #第一个是列表,第二个是比率
    sum=0
    for i in data:
        sum=sum+i
    av=(sum/len(data))*rate
    return av
def avg_y(data):
    #求列表的均值
   
    sum=0
    for i in data:
        sum=sum+i
    av=sum/len(data)
    return av
def trans(pro):
    """省份,必须是字符串"""
    #原算法适宜绘制地图,我的算法适宜折线图
    #算均值的算法有问题
    #尝试使用比例作为权重
    #原作者的算法:对于正向倾向文本取其正向概率,位于(0.5,1];对于负向倾向文本亦取其正向概率,位于[0,0.5)。
    #均值是将正向倾向的正向概率相加平均,负向倾向也是正向概率相加平均。
    c=[]#正向列表
    d=[]#负向列表
    e=[]#中性列表
    a=data.loc[str(pro)]#选定索引为该日期的所有行
    #print(a)
    for row in a.itertuples(index=True, name='Pandas'):
        #print(getattr(row, "极性"), getattr(row, "正向概率"),getattr(row, "负向概率"))
        if getattr(row, "极性")==2:
            c.append(getattr(row, "正向概率"))#正向的概率值列表
        elif getattr(row, "极性")==3:
            d.append(getattr(row, "负向概率"))#负向的概率值列表
        elif getattr(row, "极性")==1:
            e.append(1)#中性列表,纯用作计数
        else:
            pass

    sum_0=len(c)+len(d)+len(e)#评论总数量
    rate_c=len(c)/sum_0#正向评论于该天占比
    rate_d=len(d)/sum_0#负向评论于该天占比
    d_c=avg(c,rate_c)
    d_d=avg(d,rate_d)
    print("正向均值:"+str(d_c))
    print("负向均值:"+str(d_d))
    nums=[pro,d_c,d_d]
    return nums
def save_afile(all,file):
    """将降维后的数据保存在一个excle
        传递给一个列表的列表,和一个文件名
    """
    f=xlwt.Workbook()
    sheet1=f.add_sheet(u'sheet1',cell_overwrite_ok=True)
    sheet1.write(0,0,'省份')
    sheet1.write(0,1,'正向均值')
    sheet1.write(0,2,'负向均值')
    i=1
    for data in all:#遍历每一行
            for j in range(len(data)):#取每一单元格
                sheet1.write(i,j,data[j])#写入单元格
            i=i+1#往下一行
    f.save(file+'.xls')



if __name__ == '__main__':
    data_1=pd.read_excel(r'')#文件
    data = pd.DataFrame(data_1)#将excel文件读取并转换为dataframe格式
   # data['地区'] = pd.to_datetime(data['地区'])
    data.set_index("地区", inplace=True)
    """
    provinces=['湖南','湖北','广东','广西','河南','河北','山东','山西',
                        '江苏','浙江','江西','黑龙江','新疆','云南','香港','澳门',
                        '贵州','福建','吉林','安徽','四川','西藏','宁夏','辽宁',
                        '青海','甘肃','陕西','内蒙古','台湾','北京','上海','天津',
                        '重庆','海南']
    """

    cities=['西安','铜川','宝鸡','咸阳','渭南','延安','汉中','榆林','安康','商洛']
    alls=[]
    for i in cities:
        try:
            alls.append(trans(str(i)))
        except:
            continue
    save_afile(alls,'陕西省分市评论情感值')
    print('OVER!')

这里的代码是我在处理省内的各市的均值使用的,如果是省份的话将其注释掉,利用provinces。
2.根据得到的均值文件绘制情感均值地图。代码如下:

#coding='utf-8'
from pyecharts.charts import Map,Geo
from pyecharts import options as opts
import xlrd

def extract(inpath):
    """提取数据"""
    data = xlrd.open_workbook(inpath, encoding_override='utf-8')
    table = data.sheets()[0]#选定表
    nrows = table.nrows#获取行号
    ncols = table.ncols#获取列号
    numbers=[]
    for i in range(1, nrows):#第0行为表头
        alldata = table.row_values(i)#循环输出excel表中每一行,即所有数据
        result_1 = alldata[0]#取出省份
        result_2 = alldata[1]#取出正向均值
        result_3 = alldata[2]#取出负向均值
        numbers.append([result_1,result_2,result_3])
    return numbers
datas=extract('分省份评论情感值.xls')
data=[]
for i in datas:
    data.append((i[0],i[1]))

map=(
    Map( )
    .add("",data,"china")
    .set_global_opts(
        title_opts=opts.TitleOpts(title="",subtitle="",pos_right="center",pos_top="5%"),
        visualmap_opts=opts.VisualMapOpts(
            # 是否显示视觉映射配置
            is_show = True,
            # 映射过渡类型,可选,"color", "size"  (颜色映射还是大小映射)(重要!!!)
            type_ = "color",
            # 指定 visualMapPiecewise 组件的最小值。
            min_ = 0,
            # 指定 visualMapPiecewise 组件的最大值。
            max_ = 1,
            # 两端的文本,如['High', 'Low'],(自定义) range_text: Union[list, tuple] = None,
            #range_text = ['高', '低'],
            # visualMap 组件过渡颜色 (可以自定义)(颜色从淡到深) range_color: Union[Sequence[str]] = None,
            #range_color = ['#CCEBFF','#22DDDD','#0099FF','#003D66'],
            # visualMap 组件过渡 symbol 大小.range_size: Union[Sequence[int]] = None,
            #range_size = None,
            # visualMap 图元以及其附属物(如文字标签)的透明度。range_opacity: Optional[Numeric] = None,
            #range_opacity = None,
            # 如何放置 visualMap 组件,水平('horizontal')或者竖直('vertical')。
            orient = 'vertical',
            # visualMap 组件离容器左侧的距离。
            # left 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比,
            # 也可以是 'left', 'center', 'right'。
            # 如果 left 的值为'left', 'center', 'right',组件会根据相应的位置自动对齐。
            pos_left = '8%',
            # visualMap 组件离容器右侧的距离(同上)。
            # right 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比。
            pos_right = None,
            # visualMap 组件离容器上侧的距离(同上)。
            # top 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比,
            # 也可以是 'top', 'middle', 'bottom'。
            # 如果 top 的值为'top', 'middle', 'bottom',组件会根据相应的位置自动对齐。
            pos_top ='60%',
            # visualMap 组件离容器下侧的距离(同上)。
            # bottom 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比。
            pos_bottom = '30%',
            # 对于连续型数据,自动平均切分成几段。默认为5段。连续数据的范围需要 max 和 min 来指定
            #split_number = 5,
            # 指定取哪个系列的数据,默认取所有系列。series_index: Union[Numeric, Sequence, None] = None,
            series_index = None,
            # 组件映射维度Optional[Numeric]
            dimension = None,
            # 是否显示拖拽用的手柄(手柄能拖拽调整选中范围)。
            #is_calculable = True,
            # 是否为分段型
            is_piecewise = True,
            # 是否反转 visualMap 组件(默认False)
            #is_inverse = True,     
            # 自定义的每一段的范围,以及每一段的文字,以及每一段的特别的样式。例如:
            pieces=[{"max": 0, "min": -1, "label": "无数据", "color":"#eeeeee"},
                {"max": 0.350, "min": 0, "label": "0~0.350","color":"#a3cf62"},
                  {"max": 0.400, "min": 0.350, "label": "0.350~0.400","color":"#fedcbd"},
                  {"max": 0.450, "min": 0.400, "label": "0.400~0.450","color":"#faa755"},
                  {"max": 0.500, "min": 0.450, "label": "0.450~0.500","color":"#f47920"},
                  {"max": 1, "min": 0.500, "label": "0.500~1.000", "color":"#d71345"},
                  ],

            #pieces = None,
            # 定义 在选中范围外 的视觉元素。(用户可以和 visualMap 组件交互,用鼠标或触摸选择范围)
            #  可选的视觉元素有:
            #  symbol: 图元的图形类别。
            #  symbolSize: 图元的大小。
            #  color: 图元的颜色。
            #  colorAlpha: 图元的颜色的透明度。
            #  opacity: 图元以及其附属物(如文字标签)的透明度。
            #  colorLightness: 颜色的明暗度,参见 HSL。
            #  colorSaturation: 颜色的饱和度,参见 HSL。
            #  colorHue: 颜色的色调,参见 HSL。
            #out_of_range = None,
            # 图形的宽度,即长条的宽度。
            #item_width = 0,
            # 图形的高度,即长条的高度。
            #item_height = 0,
            # visualMap 组件的背景色。
            #background_color = '#CCCC33',
            # visualMap 组件的边框颜色。
            #border_color = '#EE1111',
            # visualMap 边框线宽,单位px。
            #border_width = 2,
            # 文字样式配置项,参考 `series_options.TextStyleOpts`
            #textstyle_opts = None,
            ) ,       
    )
    )  

map.render('正向均值地图.html')

3.这里也把我绘制陕西省的地图的代码分享一下,大家看看有什么不同吧。

#coding='utf-8'
from pyecharts.charts import Map,Geo
from pyecharts import options as opts
import xlrd

def extract(inpath):
    """提取数据"""
    data = xlrd.open_workbook(inpath, encoding_override='utf-8')
    table = data.sheets()[0]#选定表
    nrows = table.nrows#获取行号
    ncols = table.ncols#获取列号
    numbers=[]
    for i in range(1, nrows):#第0行为表头
        alldata = table.row_values(i)#循环输出excel表中每一行,即所有数据
        result_1 = alldata[0]#取出省份
        result_2 = alldata[1]#取出正向均值
        result_3 = alldata[2]#取出负向均值
        numbers.append([result_1,result_2,result_3])
    return numbers
datas=extract('陕西省分市评论情感值.xls')
data=[]
for i in datas:
    data.append((i[0],i[1]))

map=(
    Map( )
    .add("",data,"陕西")
    .set_global_opts(
        title_opts=opts.TitleOpts(title="",subtitle="",pos_right="center",pos_top="5%"),
        visualmap_opts=opts.VisualMapOpts(
            # 是否显示视觉映射配置
            is_show = True,
            # 映射过渡类型,可选,"color", "size"  (颜色映射还是大小映射)(重要!!!)
            type_ = "color",
            # 指定 visualMapPiecewise 组件的最小值。
            min_ = 0,
            # 指定 visualMapPiecewise 组件的最大值。
            max_ = 1,
            # 两端的文本,如['High', 'Low'],(自定义) range_text: Union[list, tuple] = None,
            #range_text = ['高', '低'],
            # visualMap 组件过渡颜色 (可以自定义)(颜色从淡到深) range_color: Union[Sequence[str]] = None,
            #range_color = ['#CCEBFF','#22DDDD','#0099FF','#003D66'],
            # visualMap 组件过渡 symbol 大小.range_size: Union[Sequence[int]] = None,
            #range_size = None,
            # visualMap 图元以及其附属物(如文字标签)的透明度。range_opacity: Optional[Numeric] = None,
            #range_opacity = None,
            # 如何放置 visualMap 组件,水平('horizontal')或者竖直('vertical')。
            orient = 'vertical',
            # visualMap 组件离容器左侧的距离。
            # left 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比,
            # 也可以是 'left', 'center', 'right'。
            # 如果 left 的值为'left', 'center', 'right',组件会根据相应的位置自动对齐。
            pos_left = '20%',
            # visualMap 组件离容器右侧的距离(同上)。
            # right 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比。
            pos_right = None,
            # visualMap 组件离容器上侧的距离(同上)。
            # top 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比,
            # 也可以是 'top', 'middle', 'bottom'。
            # 如果 top 的值为'top', 'middle', 'bottom',组件会根据相应的位置自动对齐。
            pos_top ='60%',
            # visualMap 组件离容器下侧的距离(同上)。
            # bottom 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比。
            pos_bottom = '30%',
            # 对于连续型数据,自动平均切分成几段。默认为5段。连续数据的范围需要 max 和 min 来指定
            #split_number = 5,
            # 指定取哪个系列的数据,默认取所有系列。series_index: Union[Numeric, Sequence, None] = None,
            series_index = None,
            # 组件映射维度Optional[Numeric]
            dimension = None,
            # 是否显示拖拽用的手柄(手柄能拖拽调整选中范围)。
            #is_calculable = True,
            # 是否为分段型
            is_piecewise = True,
            # 是否反转 visualMap 组件(默认False)
            #is_inverse = True,     
            # 自定义的每一段的范围,以及每一段的文字,以及每一段的特别的样式。例如:
            pieces=[
                  {"max": 0.300, "min": 0, "label": "0~0.300","color":"#a3cf62"},
                  {"max": 0.400, "min": 0.300, "label": "0.300~0.400","color":"#fedcbd"},
                  {"max": 0.500, "min": 0.400, "label": "0.400~0.500","color":"#faa755"},
                  {"max": 0.600, "min": 0.500, "label": "0.500~0.600","color":"#f47920"},
                  {"max": 1, "min": 0.600, "label": "0.600~1.000", "color":"#d71345"},
                  ],

            #pieces = None,
            # 定义 在选中范围外 的视觉元素。(用户可以和 visualMap 组件交互,用鼠标或触摸选择范围)
            #  可选的视觉元素有:
            #  symbol: 图元的图形类别。
            #  symbolSize: 图元的大小。
            #  color: 图元的颜色。
            #  colorAlpha: 图元的颜色的透明度。
            #  opacity: 图元以及其附属物(如文字标签)的透明度。
            #  colorLightness: 颜色的明暗度,参见 HSL。
            #  colorSaturation: 颜色的饱和度,参见 HSL。
            #  colorHue: 颜色的色调,参见 HSL。
            #out_of_range = None,
            # 图形的宽度,即长条的宽度。
            #item_width = 0,
            # 图形的高度,即长条的高度。
            #item_height = 0,
            # visualMap 组件的背景色。
            #background_color = '#CCCC33',
            # visualMap 组件的边框颜色。
            #border_color = '#EE1111',
            # visualMap 边框线宽,单位px。
            #border_width = 2,
            # 文字样式配置项,参考 `series_options.TextStyleOpts`
            #textstyle_opts = None,
            ) ,       
    )
    )  

map.render('陕西省正向均值地图.html')

六、完结

以上大多是关于我国的,如果是单个省市的话,只需要将其提取出来再处理一遍就行了,大家这么聪明就不赘述了。
总体来说,完成这一个工作花费了近20天的时间,主要是在评论爬取、数据清洗和日期合并上花费了不少精力,以后还得多多努力。
欢迎大家交流!(泠鸢镇楼)
泠鸢镇楼

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐