有分析需求需要一个能够衡量歌星或乐队影响力的指标。首先爬取了新浪微博相关主体的粉丝数量,这里有一个问题就是有的明星影响力很大但并不用微博,导致微博的粉丝数量并不多,如:周杰伦。为解决这一问题,又去爬取了百度搜索和头条指数,在爬取过程中遇到一些问题,特此记录一下。
使用的是python的requests。
其中共有2个坑,1是url中的params的编码,另一个是请求头中的Cipher-Text参数。
先进行网页元素分析,这里以搜索周杰伦为例,选取时间为2018-01-01至2023-10-28,页面显示结果如下:
按F12,检查页面元素,找到需要的接口https://index.baidu.com/api/SearchApi/index?area=0&word=[[%7B%22name%22:%22%E5%91%A8%E6%9D%B0%E4%BC%A6%22,%22wordType%22:1%7D]]&startDate=2018-01-01&endDate=2023-11-26
查看请求如下:
可以看到是get请求,url加params的样式。
坑1:
解码后的payload如下:
area: 0
word: [[{"name":"周杰伦","wordType":1}]]
startDate: 2011-01-01
endDate: 2021-05-05
编码后如下:
area: 0
word: [[%7B%22name%22:%22%E5%91%A8%E6%9D%B0%E4%BC%A6%22,%22wordType%22:1%7D]]
startDate: 2011-01-01
endDate: 2021-05-05
这里有第一个坑,area和date都很简单,直接使用python的urllib中的parse方法都能够进行编码,如下:
from urllib import parse
params = {
"area": "0",
"startDate": "2018-01-01",
"endDate": "2023-11-26",
}
print(parse.urlencode(params))
##输出:'area=0&startDate=2018-01-01&endDate=2023-11-26'
如果使用同样的方法对word参数编码则会出现问题:
paras= {'word':[[{"name":"周杰伦","wordType":1}]]}
print(parse.urlencode(word))
# 输出:'word=%5B%5B%7B%27name%27%3A+%27%E5%91%A8%E6%9D%B0%E4%BC%A6%27%2C+%27wordType%27%3A+1%7D%5D%5D'
可以看到与网页的payload不符,将'[]'都进行了编码。
所以这里需要对内容单独来进行编码,最后再拼到一起加入url进行请求。(很简单,代码就不贴了。)
坑2:
应该是百度为了反扒,在请求头中特地加了一项clipher-text,如下:
笔者花了大量的时间尝试进行逆向js,但能力有限。最后发现,这一串跟实际的搜索内容没有关系,而开始的时间戳也有较长的失效时间,完全可以粘一个爬一些数据,歇一会再重粘一个。笔者就是用这种方法爬完了所需的数据,还好需求不大。
最后还有一点,如果一次爬太多,很容易被封,cookies最好也替换的勤一些。
如果有大神成功对百度指数进行了js逆向,还望不吝赐教。