Python可视化近冬奥会开幕式BAIDU搜索指数 + 词云图
一、简介
在日常运营中, 我们通常会采用爬虫工具, 按照指定关键词来进行数据抓取, 获取百度搜索指数的历史数据, 然后对收集到的数据进行相应的分析与评估.

百度指数,体验大数据之美。但要获取百度指数相关的数据,困难如下:
该系统不支持静态网页功能,并且百度指数平台返回的URL请求地址返回的数据无法简单地通过JSON解析来提取数据内容;相反的是加密后的数据以及唯一标识符(uniqid),因此需要使用uniqid再次请求对应的URL以便获取用于解密所需的密钥;在前端页面完成数据解密后即可将其绘制到折线图上
必须要在百度指数页面登录百度账号(获取Cookie)。
将前端解密程序转换为可与Python后端集成的代码,或者直接通过execjs来运行原始JavaScript脚本
本文基于关键词(北京冬奥会、冬奥会开幕式)获取最近一段时间内的百度搜索指数数据作为研究案例。具体而言,在爬取过程中结合具体的冬奥会有助于更深入地分析其历史数据特征。接着对冬奥会近90天的搜索指数进行可视化展示,并同时采集相关媒体报道素材制作成词云图进行分析
环境:Anaconda + Pycharm
主要用到的库:requests、execjs、datetime、pandas、matplotlib、stylecloud
二、网页分析
没有百度账号的话需要先注册,然后进入百度指数官网:
https://www.baidu.com/s?wd=百度指数

搜索冬奥会,选择近 90 天,即可看到近 90 天冬奥会搜索指数的折线图:

最终要做的就是获取这些搜索指数数据,保存到本地Excel。
在登录之后,请详细说明如何获取 Cookie( cookie 必不可少,否则将无法获得所需数据),具体的操作流程如下图所示:

分析可以找到 json 数据的接口,如下所示:

在Request URL中, word参数后跟的是搜索关键词(其中汉字已被编码处理)。设置为90天的数据, 其意义是从当前日期的前一天向历史方向延伸一个月时间长度, 用户可以根据需求调整days值以获取更多或较少的数据量。将此Request URL复制到浏览器地址栏输入回车键打开(在JSON数据页面上安装如JSON Handle这样的插件将非常方便)。
    https://index.baidu.com/api/SearchApi/index?area=0&word[[%7B%22name%22:%22%E5%86%AC%E5%A5%A5%E4%BC%9A%22,%22wordType%22:1%7D]]&days=90
        
可以看到以下数据:

通过解密所有、PC以及wise对应的所有数据,并将其与搜索指数的折线图显示出来的数据进行比较分析可知,在'all'数据区域中存储的是搜索指数数据。本次请求返回的所有数据信息均包含在此处,并且能够查看到唯一标识符(UniqID)。需要注意的是,在每次刷新加密后的数据时都会更新唯一标识符(UniqID)。

经过多次分析发现,在请求数据的 URL 包含了一个称为 uniqid 的字段中存在该字段
为此必须首先从请求中提取与 URL 相关联的数据,并对该数据进行解析以便获得与搜索指数相关的加密信息及其唯一标识符。随后将提取的 URL 部分与已知的密钥信息进行结合以便生成完整的密钥路径。最后通过调用解密函数来处理这些信息并将结果恢复出所需的搜索指数数据。
    https://index.baidu.com/Interface/ptbk?uniqid=b92927de43cc02fcae9fbc0cee99e3a9
        获得了相应的URL地址。
其核心逻辑仍然遵循同样的流程。
首先向服务器发送请求。
服务器返回相应页面内容。
对返回的内容进行解析处理。
接下来会对获取的数据进行解密处理。
最后将处理后的信息存储到本地数据库中。
三、数据获取
Python代码:
 # -*- coding: UTF-8 -*-
    
 """
    
 @Author   :叶庭云
    
 @公众号    :AI庭云君
    
 @     :
    
 """
    
 import execjs
    
 import requests
    
 import datetime
    
 import pandas as pd
    
 from colorama import Fore, init
    
  
    
 init()
    
  
    
 # 搜索指数数据解密的Python代码
    
 def decryption(keys, data):
    
     dec_dict = {}
    
     for j in range(len(keys) // 2):
    
     dec_dict[keys[j]] = keys[len(keys) // 2 + j]
    
  
    
     dec_data = ''
    
     for k in range(len(data)):
    
     dec_data += dec_dict[data[k]]
    
     return dec_data
    
  
    
  
    
 if __name__ == "__main__":
    
  # 北京冬奥会  冬奥会开幕式
    
     keyword = '北京冬奥会'     # 百度搜索收录的关键词
    
     period = 90           # 时间  近90天
    
     start_str = 'https://index.baidu.com/api/SearchApi/index?area=0&word=[[%7B%22name%22:%22'
    
     end_str = '%22,%22wordType%22:1%7D]]&days={}'.format(period)
    
     dataUrl = start_str + keyword + end_str
    
     keyUrl = 'https://index.baidu.com/Interface/ptbk?uniqid='
    
     # 请求头
    
     header = {
    
     'Accept': 'application/json, text/plain, */*',
    
     'Accept-Encoding': 'gzip, deflate, br',
    
     'Accept-Language': 'zh-CN,zh;q=0.9',
    
     'Connection': 'keep-alive',
    
     'Cookie': '注意:换成你的Cookie',
    
     'Host': 'index.baidu.com',
    
     'Referer': 'https://index.baidu.com/v2/main/index.html',
    
     'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"',
    
     'sec-ch-ua-mobile': '?0',
    
     'Sec-Fetch-Dest': 'empty',
    
     'Sec-Fetch-Mode': 'cors',
    
     'Sec-Fetch-Site': 'same-origin',
    
     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36'
    
     }
    
     # 设置请求超时时间为16秒
    
     resData = requests.get(dataUrl,
    
                        timeout=16, headers=header)
    
  
    
     uniqid = resData.json()['data']['uniqid']
    
     print(Fore.RED + "uniqid:{}".format(uniqid))
    
     keyData = requests.get(keyUrl + uniqid,
    
                        timeout=16, headers=header)
    
     keyData.raise_for_status()
    
     keyData.encoding = resData.apparent_encoding
    
  
    
     # 解析json数据
    
     startDate = resData.json()['data']['userIndexes'][0]['all']['startDate']
    
     print(Fore.RED + "startDate:{}".format(startDate))
    
     endDate = resData.json()['data']['userIndexes'][0]['all']['endDate']
    
     print(Fore.RED + "endDate:{}".format(endDate))
    
     source = (resData.json()['data']['userIndexes'][0]['all']['data'])  # 原加密数据
    
     print(Fore.RED + "原加密数据:{}".format(source))
    
     key = keyData.json()['data']  # 密钥
    
     print(Fore.RED + "密钥:{}".format(key))
    
  
    
     res = decryption(key, source)
    
     # print(type(res))
    
     resArr = res.split(",")
    
     # 生成datetime
    
     dateStart = datetime.datetime.strptime(startDate, '%Y-%m-%d')
    
     dateEnd = datetime.datetime.strptime(endDate, '%Y-%m-%d')
    
     dataLs = []
    
     # 起始日期到结束日期每一天
    
     while dateStart <= dateEnd:
    
     dataLs.append(str(dateStart))
    
     dateStart += datetime.timedelta(days=1)
    
     # print(dateStart.strftime('%Y-%m-%d'))
    
  
    
     ls = []
    
     # 组织数据和遍历打印查看
    
     for i in range(len(dataLs)):
    
     ls.append([keyword, dataLs[i], resArr[i]])
    
  
    
     for i in range(len(ls)):
    
     print(Fore.RED + str(ls[i]))
    
  
    
     # 保存数据到Excel 设置列名
    
     df = pd.DataFrame(ls)
    
     df.columns = ["关键词", "日期", "百度搜索指数"]
    
     df.to_excel("北京冬奥会搜索指数数据 90天.xlsx", index=False)
        结果如下:

解密部分也可以直接利用 execjs 执行 JavaScript 代码实现,如下所示:
 # Python的强大之处就在于,拥有很强大的第三方库,可以直接执行js代码,即对解密算法不熟悉,你无法写Python代码时,直接执行js代码即可
    
 js = execjs.compile('''
    
         function decryption(t, e){
    
             for(var a=t.split(""),i=e.split(""),n={},s=[],o=0;o<a.length/2;o++)
    
                 n[a[o]]=a[a.length/2+o]
    
             for(var r=0;r<e.length;r++)
    
                 s.push(n[i[r]])
    
             return s.join("")
    
         }
    
     ''')
    
 res = js.call('decryption', key, source)  # 调用此方式解密
    
 res = decryption(key, source)
        Python爬虫成功运行,数据保存为冬奥会搜索指数数据 90 天.xlsx。
四、搜索指数可视化
 import numpy as np
    
 import pandas as pd
    
 import matplotlib as mpl
    
 import matplotlib.pyplot as plt
    
 import math
    
 import warnings
    
  
    
  
    
 warnings.filterwarnings("ignore")
    
 df1 = pd.read_excel("冬奥会开幕式搜索指数数据 90天.xlsx")
    
 df2 = pd.read_excel("北京冬奥会搜索指数数据 90天.xlsx")
    
  
    
 mpl.rcParams['font.family'] = 'SimHei'
    
  
    
 # 生成x轴数据  列表推导式
    
 # x_data = [i for i in range(1, len(df1) + 1)]
    
 x_data = [i for i in range(1, len(df1) - 1)]
    
 y_data1 = df1["百度搜索指数"][:-2]
    
 y_data2 = df2["百度搜索指数"][:-2]
    
  
    
 # 设置figure大小  像素
    
 fig, ax = plt.subplots(figsize=(6, 4), dpi=500)
    
  
    
 # 绘制三条折线  点的形状 颜色  标签:用于图例显示
    
 plt.plot(x_data, y_data1, 
    
     color="#FF1493", label="冬奥会开幕式")
    
 plt.plot(x_data, y_data2,
    
      color="#00BFFF", label="北京冬奥会")
    
  
    
  
    
 # x y 轴标签   字体大小
    
 plt.xlabel("时间顺序", 
    
        fontdict={"size": 15, "weight": "bold", "color": "black"})
    
 plt.ylabel("百度搜索指数",
    
        fontdict={"size": 15, "weight": "bold", "color": "black"}
    
       )
    
  
    
 # 设置坐标轴刻度标签的大小
    
 plt.tick_params(axis='x', direction='out',
    
            labelsize=12, length=4.6)
    
 plt.tick_params(axis='y', direction='out',
    
            labelsize=12, length=4.6)
    
  
    
 # 显示图例
    
 plt.legend(fontsize=15, frameon=False)
    
 labels = ax.get_xticklabels() + ax.get_yticklabels()
    
 [label.set_fontname('Times New Roman') for label in labels]
    
 [label.set_color('black') for label in labels]
    
 plt.grid(alpha=0.7, ls=":")
    
  
    
 # 展示show
    
 plt.show()
        结果如下:

请添加图片描述
冬季奥运会主火炬晚会、北京冬奥会的关注度近几天呈现直线上升趋势。大家对这一盛事的反应如何?



智慧与文明在此刻完美融合。
以奥运会精神为核心,
携手共创人类文明新纪元。
也祝愿我们今年北京冬奥会圆满落幕!🎉🎉❤️❤️
五、词云图
众多媒体纷纷报道着冬奥会的盛事。在这里我们可以收集一些原始文本数据,并通过生成词云图来进行分析观察
 with open("冬奥会开幕式.txt", encoding="utf-8") as f:
    
     data = f.read()
    
  
    
 # 文本预处理  去除一些无用的字符   只提取出中文出来
    
 new_data = re.findall('[\u4e00-\u9fa5]+', data, re.S)
    
 new_data = "/".join(new_data)
    
  
    
 # 文本分词  精确模式
    
 seg_list_exact = jieba.cut(new_data, cut_all=False)
    
  
    
 # 加载停用词
    
 with open('stop_words.txt', encoding='utf-8') as f:
    
     # 获取每一行的停用词 添加进集合
    
     con = f.read().split('\n')
    
     stop_words = set()
    
     for i in con:
    
     stop_words.add(i)
    
  
    
 # 列表解析式  去除停用词和单个词
    
 result_list = [word for word in seg_list_exact if word not in stop_words and len(word) > 1]
    
 print(result_list)
    
  
    
 # https://fontawesome.com/license/free
    
 # 个人推荐使用的palette配色方案  效果挺好看   其他测试过  感觉一般~~
    
 # colorbrewer.qualitative.Dark2_7
    
 # cartocolors.qualitative.Bold_5
    
 # colorbrewer.qualitative.Set1_8
    
 gen_stylecloud(
    
     text=' '.join(result_list),                   # 文本数据
    
     size=600,                                     # 词云图大小
    
     font_path='./font/猫啃网糖圆体.ttf',            # 中文词云  显示需要设置字体
    
     icon_name = "fas fa-grin-beam",               # 图标
    
     output_name='冬奥会开幕式.png',                 # 输出词云图名称
    
     palette='colorbrewer.qualitative.Set1_8',     # 选取配色方案
    
 )
        如果说某年的奥运会中国展现了深厚的文化底蕴!那么本届冬奥会中国以最卓越的表现向世界展示了科技日新月异与腾飞!

六、总结
今年冬奥会开幕式真的太好看啦,惊艳全球!
总结:
Python爬虫:根据关键词获取百度搜索指数历史数据
解析 JSON 数据,加密数据的解密,数据保存到Excel
matplotlib:百度搜索指数的可视化
stylecloud:绘制词云图
end:分享就到这了喜欢给小编个三连哦!
想获取丰富且高质量的源码及Python学习资料可通过点击这行字体进行获取。
