利用搜索指数窥探舆情

新冠病毒全球蔓延,你知道人民最关注的是什么吗?最近股市大爆,你知道人们相关搜索最多的内容是什么吗?特不靠谱天天嘴炮,你知道他最引人注目的特征是什么吗?如果你对这些感兴趣,那么请跟随我的脚步去看看吧!

百度指数

什么是百度指数?

百度指数是以百度海量网民行为数据为基础的数据分享平台。在这里,你可以研究关键词搜索趋势、洞察网民需求变化、监测媒体舆情趋势、定位数字消费者特征;还可以从行业的角度,分析市场特点。

我们可以简单理解为,百度指数是百度官方提供的一个数据参考平台。特别是平台中提供的搜索指数,是以网民对关键词的搜索量作为基础来计算的。搜索指数反应的是网民在过去一个月内,对关键词搜索量的加权和。

我们知道,百度是国内最大的搜索引擎,也是世界最大的中文搜索引擎,所以我们所关心的关键词搜索基本上可以用百度指数体现出来。

这个指数对于运营人员或者市场营销人员应该很有用,精准地捕捉人们关注的事件关键词可以更好地帮助他们进行关键词购买或者投放。

百度指数的首页地址是:http://index.baidu.com/v2/index.html#/ ,首页页面为:

在这里我们可以直接输入关键词进行搜索。例如,我输入“蔡徐坤”进行搜索,结果页面如下:

这里可以看到对应日期的关键词搜索指数。

利用百度指数

如果感兴趣的话,大家可以自己研究一下百度指数的功能,这里就不介绍了。

下面进入本文的正题。虽然百度指数页面可以比较直观地看到我们关键词的搜索结果,但是我们看不到这些结果背后的数据。作为一个程序员,我还是觉得我需要看到具体的数据,所谓“数据在手,天下我有”,有了数据,我们可以根据数据自由使用,想画成曲线也好,想做成直方图也罢,都凭自己喜好。

基于这个需求,我的程序步骤分为两步:第一步是获取数据,第二步是将获取到的数据做成酷酷的词云。

获取数据

我们先来看看百度指数页面是怎么查询的:

首先选择“需求图谱”栏目,然后输入关键词“新冠病毒”,点击“确定”按钮,下方就展示了结果了。

我们打开开发者工具,找到搜索关键词指数的请求如下图所示:

有了这个请求,我们就可以通过代码来获取数据了,关键代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 搜索指数URL
    data_url = 'http://index.baidu.com/api/WordGraph/multi?wordlist[]={keyword}'
    
headers = {
        "User-Agent": 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36',
        "Cookie": 'PSTM=1579955530; BAIDUID=C98F0EF9DCB3FC7E06D3B0FA63695787:FG=1; BIDUPSID=1FB86823BF26D806A0117921DBD66135; BDSFRCVID=bpFOJeC62ZTm5dnuEvqKKASNJe3SOxnTH6aoprlQ5IIcI75XA-7tEG0P_U8g0KubIXdfogKKLgOTHPIF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tJkf_D8XtK83fP36q470htFjMfQXetJyaR3UWpQvWJ5TMC_whlOFK-I0XHLjWUPf-eOW3C5dLxQ8ShPC-tnZ56Lv5tRT-xb83JbnbxO83l02VM7ae-t2ynLVbNJ324RMW23r0h7mWUJzsxA45J7cM4IseboJLfT-0bc4KKJxbnLWeIJIjjCajTcQjN_qq-JQa5TbstbHaJOqD4-k-PnVHPKXhUce2bQHKKI_0-3LK-0_hC_lD6LKjI6XDGLHJ6DfHJuHoC_htD0tftbzBPcqb-F0hHc2bP0hb6nLMbTeqR3bJRO6q6KKDjjLDGtXJjDDtJCH_5u-tDDKhD_6eTONjbtpbtbmhU-e56vQ3-5SWfK2sKTn0qjTD5v3hh6aaTv45J7ZVDKbtI8MbDLrMRoVK-A0hxLXt6kXKKOLVb6Eb4OkeqOJ2Mt5bjFihp_O0PrXB6bCQCoTKlvRjPbzX4Oo0jtpeG_DtjFqtJksL-35HtnheJ54KPu_-P4DeU8eaMRZ5mAqoqOoyI_bO45ODtD2yU_9X467K5btX5rnaIQqabIMeMJFbnOIjqDNbbPtafc43bRT0xKy5KJvfjCx-UAMhP-UyPvMWh37Lg5lMKoaMp78jR093JO4y4Ldj4oxJpOJ5JbMopCafD_2MCD6DTLhen-W5gTEaPoX5Kj-WjrJabCQHnnph4Tqhh4ShUO-f6_jtnuf8JOSKRr_eJR3MPoB5P4XbacKJT3-5RPt3RLKfnD5MD89epDh0btpbtbmhU-e3TrOb45vK-oGbKjCKqo-2t0F-xbW2PkfaR7ZVD_ytCL-bK_GenJb5ICEbfreanLXKK_s3tJIBhcqEIL4WlOVjt0H5toqbxni0G7waJKbLh7WDxbSj4QoKbDj0HoAB4JAJbTv56C5bp5nhMJ33j7JDMP0-4rvKP5y523i2n3vQpnmOqQ3DRoWXPIqbN7P-p5Z5mAqKl0MLPbtbb0xXj_0-nDSHHuOJjOP; BDUSS=UJsNmwzSnVwLWJ6eGJiTGtBMXRxVkNVVHFYOEgzZ0NMemo0V2o4dG9RaH5xbmxlRVFBQUFBJCQAAAAAAAAAAAEAAAArVO4Kzt7D-3ZpcGVyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH8dUl5~HVJee; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; Hm_lvt_d101ea4d2a5c67dab98251f0b5de24dc=1582632851; bdshare_firstime=1582719699670; bdindexid=lbhlaubfjakm0eklbjbislhal1; Hm_lpvt_d101ea4d2a5c67dab98251f0b5de24dc=1582940553; delPer=0; PSINO=6; H_PS_PSSID=1445_21119_30790_30905_30823_26350; RT="sl=2&ss=k771w9qf&tt=1yz&bcn=https%3A%2F%2Ffclog.baidu.com%2Flog%2Fweirwood%3Ftype%3Dperf&z=1&dm=baidu.com&si=0pgwidvcjf8&ld=1ab9"',
        "Host": "index.baidu.com",
        "Referer": "http://index.baidu.com/v2/main/index.html"
    }

# 获取指数数据
def get_index(self, params):
    url = self.data_url.format(**params)
    response = requests.get(url, headers=self.headers)

    data = json.loads(response.text)['data']
    print(data)

获取到数据之后,我们打印一下返回结果:

1
2
{'period': '20190303|20200223', 'wordlist': [{'keyword': '新冠状病毒', 'wordGraph': [{'word': '新冠状病毒症状', 'pv': 695686, 'ratio': 81, 'sim': 1585}, {'word': '冠状病毒肺炎最新消息', 'pv': 169160, 'ratio': 54, 'sim': 1386}, {'word': '新型冠状病毒图片', 'pv': 183956, 'ratio': 74, 'sim': 1067}, {'word': '新冠状病毒最新消息', 'pv': 144624, 'ratio': 82, 'sim': 695}, {'word': '新冠状病毒手抄报', 'pv': 77286, 'ratio': 99, 'sim': 580}, {'word': '新冠状病毒肺炎', 'pv': 32124, 'ratio': 68, 'sim': 568}, {'word': '新型冠状病毒', 'pv': 15874090, 'ratio': 72, 'sim': 509}, {'word': 'MERS病毒', 'pv': 162990, 'ratio': 111, 'sim': 480}, {'word': '新冠', 'pv': 135256, 'ratio': 92, 'sim': 457}, {'word': '武汉新冠状病毒', 'pv': 6166, 'ratio': 35, 'sim': 407}, {'word': '什么是新型冠状病毒', 'pv': 498628, 'ratio': 83, 'sim': 390}, {'word': '冠状病毒是什么引起的', 'pv': 42766, 'ratio': 113, 'sim': 290}, {'word': '冠状病毒', 'pv': 2201280, 'ratio': 62, 'sim': 248}, {'word': '犬冠状病毒病', 'pv': 45364, 'ratio': 51, 'sim': 242}, {'word': '第一个被感染新型冠状的人', 'pv': 14776, 'ratio': 105, 'sim': 234}, {'word': '新型冠状病毒传播途径', 'pv': 278268, 'ratio': 59, 'sim': 232}, {'word': '新冠状病毒的症状', 'pv': 118890, 'ratio': 66, 'sim': 231}, {'word': '新冠病毒', 'pv': 379066, 'ratio': 99, 'sim': 219}, {'word': '新冠状病毒死亡率', 'pv': 1494, 'ratio': 56, 'sim': 207}, {'word': '冠状病毒几天会死', 'pv': 74046, 'ratio': 89, 'sim': 206}, {'word': '中东呼吸系统综合征冠状病毒', 'pv': 8062, 'ratio': 63, 'sim': 199}, {'word': '新型冠状病毒的特征', 'pv': 1326910, 'ratio': 22, 'sim': 194}, {'word': '新冠状病毒肺炎症状', 'pv': 187512, 'ratio': 44, 'sim': 192}, {'word': '新型艾滋病', 'pv': 140, 'ratio': 97, 'sim': 189}, {'word': '冠状病毒症状早期表现', 'pv': 1178282, 'ratio': 52, 'sim': 185}, {'word': '冠形病毒', 'pv': 19760, 'ratio': 75, 'sim': 175}, {'word': 'SARS病毒', 'pv': 176732, 'ratio': 45, 'sim': 174}, {'word': '非典', 'pv': 625846, 'ratio': 53, 'sim': 164}, {'word': '新冠肺炎', 'pv': 782614, 'ratio': 111, 'sim': 161}]}]}

结果是 json 格式,从结果中,我们可以获取到我们搜索的关键词以及与之关联的关键词的热度(pv)、搜索变化率(ratio)、相关性(sim)。

这里有一点需要注意,不是我们输入的所有关键词都有结果的,因为百度也是根据大家在搜索框输入的关键词来做统计,所以大家没有输入的关键词在这里是查询不出来的,例如,我查询“新冠状肺炎”,页面返回的结果是这样的:

我们再仔细查看页面开发者工具,会发现每次查询关键词前,都会做一个 checkWordsExists 的请求,目的是查找关键词是否收录。请看下图:

当关键词存在时,返回的结果是:

1
{"status":0,"data":{"result":[]},"logid":2886305955,"message":""}

当关键词不存在时,返回的结果是:

1
{"status":0,"data":{"result":[{"word":"新冠状肺炎","status":10003}],"addWordsNum":0,"addWordsLeft": "", "addWordsTimeout": ""},"logid":3072538578,"message": ""}

根据这两个结果,我们就可以做一个简单的判断了:

1
2
3
4
5
6
    # 检查关键词是否存在
    def check_word(self, kw):
        url = self.check_url % kw
        response = requests.get(url, headers=self.headers)
        data = json.loads(response.text)['data']
        return not len(data['result'])

如果存在关键词我们才进行指数请求,不存在直接返回。

制作词云

得到百度指数结果后,我们选取热度和搜索变化率分别来制作成词云。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    # 获取指数数据
    def get_index(self, params):
        url = self.data_url.format(**params)
        response = requests.get(url, headers=self.headers)

        data = json.loads(response.text)['data']
        print(data)

        pv_dict = {}
        ratio_dict = {}
        for item in data['wordlist'][0]['wordGraph']:
            pv_dict[item['word']] = item['pv']
            ratio_dict[item['word']] = item['ratio']

        # 生成词云
        self.gen_wc_tags(pv_dict)
        self.gen_wc_tags(ratio_dict)
    # 生成词云
    def gen_wc_tags(self, tags):
        # 设置一个底图
        # mask = np.array(Image.open('./bf.jpg'))
        wordcloud = WordCloud(background_color='black',
                              mask=None,
                              max_words=100,
                              max_font_size=100,
                              width=800,
                              height=600,
                              # 如果不设置中文字体,可能会出现乱码
                              font_path='/System/Library/Fonts/PingFang.ttc').generate_from_frequencies(tags)

        # 展示词云图
        plt.imshow(wordcloud, interpolation='bilinear')
        plt.axis('off')
        plt.show()

        # 保存词云图
        wordcloud.to_file('./gzbd_wc.png')

我们搜索关键词“新冠状病毒”,运行程序,得到热度词云图是:

变化率词云图是:

从词云图中,我们可以看到大家搜索“新光状病毒”,相关查询最多的是病毒的特征以及早期症状,这两个是大家最关心的内容。而从变化率的词云图来看,变化最大的还是我们平时看到的一些标题党喜欢用的词语,这类词语一般过一段时间就会出来一个,然后又迅速消退。

我们再来看看关键词“股市”的词云图:

最吸引我注意的是“1万炒股一年最多挣多少”,看来好多人还是想着一夜暴富啊!当然我也想知道呢!所谓“有事问百度”,其他的一些相关关键词完美地提现了韭菜的特质,都是一些股市新手爱问的问题。

最后,我们再看看关键词“特朗普”的词云图:

映入眼帘的大多数是一些人名,应该基本上是跟特朗普有关的政治家吧。所以想知道谁跟特不靠谱打交道最多,从这张图上可以窥见一二吧。

总结

本文主要通过爬取百度指数的关键词搜索数据,制作成词云图,来展现关键词相关词的搜索情况,从而找到人们对于某一个热点的关注点集中在哪里。

文中示例代码:python-100-days

Python Geek Tech wechat
欢迎订阅 Python 技术,这里分享关于 Python 的一切。