Python系列爬虫之美团美食板块商家数据抓取(三)
昨天分享了一个美团美食板块的小爬虫。很多人私信说不明白_token参数到底怎么来的,真的没时间一一回复,干脆再推送一篇文章,来详细讲讲_token参数到底是怎么搞出来的。这次,我尽量写的详细一些。
详解
_token参数:
上回我们说到我们猜测_token参数是原数据先进行二进制压缩然后进行base64编码获得的,反向操作一波:
证实了我们的猜测,即_token参数包括以下内容:
"rId":100900,
"ver":"1.0.6",
"ts":1559028105019,
"cts":1559028105097,
"brVD":[1536,150],
"brR":[[1536,864],[1536,824],24,24],
"bI":["https://bj.meituan.com/meishi/","https://bj.meituan.com/"],
"mT":[],
"kT":[],
"aT":[],
"tT":[],
"aM":"",
"sign":"eJwljk1uwjAQhe/CwkvHSZNAkLyoWCGh7jiATSYwbfyj8bgSd2DPJTgB52nvgYHdp6dP772FITDbUStxMAxvQD5/GQf6/3L9u9/EiN4DbUL2/MlMxREhMrqcNmEEXYtAeES/p1mfmGNaV5X9lg6Qs/HyEFxVOJ2wEtEcn340xKVR100v4mx4CuRKTJh+dvALc+EUiLXICV5zOWM5ZtXQttOwbHvbjoNdTXYl664bVNP1zYespZJq8QBcYkdy"
一共13个变量,刷新几次并结合相关的js源码(在rohr.min.js文件夹中,上一篇文章也截图了):
var iP = {
rId: Rohr_Opt.Flag,
ver: _$_543c[138],
ts: new Date().getTime(),
cts: new Date().getTime(),
brVD: iN(),
brR: iM(),
bI: iL(),
mT: [],
kT: [],
aT: [],
tT: [],
aM: iK()
};
我们推断不变量为:
--rId:
刷新几次发现都不变;
--ver:
刷新几次发现都不变;
--mT:
显然是[];
--kT:
显然是[];
--aT:
显然是[];
--tT:
显然是[];
--aM:
找到函数iK:
var iK = function() {
if (window._phantom || window.phantom || window.callPhantom) {
return _$_543c[135]
}
;return iQ.getWebdriver()
};
所以我们可以直接把aM当作不变量""。
至于ts和cts,很显然是时间戳嘛。不过测试之后发现cts一直比ts大一丢丢。所以ts和cts的获取方式可以写成这样:
ts = int(time.time() * 1000)
cts = ts + random.randint(100, 120)
至于为什么cts比ts大一丢丢,好像是因为后面代码又执行了一次:
iP.cts = newDate().getTime();
接下来考虑brVD和brR这两个参数,其生成函数分别为iN()和iM()。在同一个js文件里搜索一下可以发现以下代码:
var iN = function() {
var hR = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
var hK = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
return [hR, hK]
};
var iM = function() {
var iZ = [screen.width, screen.height];
var iW = [screen.availWidth, screen.availHeight];
var iX = screen.colorDepth;
var iY = screen.pixelDepth;
return [iZ, iW, iX, iY]
};
很显然,iM就是返回你用的电脑屏幕的一些信息,其含义分别为:
screen.availWidth:屏幕可用工作区宽度
screen.availHeight:屏幕可用工作区高度
screen.width:屏幕分辨率的宽
screen.height:屏幕分辨率的高
screen.colorDepth:屏幕的颜色深度,根据CSSOM(CSS对象模型)视图,为兼容起见,该值总为24。
screen.pixelDepth:返回屏幕的位深度/色彩深度,根据CSSOM(CSS对象模型)视图,为兼容起见,该值总为24。
iN也差不多,具体什么含义自己Google吧。所以我们可以搞个文件,保存这些参数的常见值:
然后每次随机获取一个就行了,代码体现为:
'brVD': info.get('barVD'),
'brR': [info.get('brR_one'), info.get('brR_two'), 24, 24],
接下来看bI的生成函数iL:
var iL = function() {
var jb = document.referrer;
var ja = window.location.href;
return [ja, jb]
};
其含义为(Google一大堆,随手复制粘贴一个):
document.referrer:获取前一个访问页面的URL地址
window.location.href:返回当前页面的URL
当时忘记加第二个了,不过按我之前的代码那么写似乎也没出错:
'bI': ['https://{}.meituan.com/meishi/'.format(city_code),''],
OK,目前为止,我们已经知道了:
rId
ver
ts
cts
brVD
brR
bI
mT
kT
aT
tT
aM
唯独不知道sign的:
eJwljk1uwjAQhe/CwkvHSZNAkLyoWCGh7jiATSYwbfyj8bgSd2DPJTgB52nvgYHdp6dP772FITDbUStxMAxvQD5/GQf6/3L9u9/EiN4DbUL2/MlMxREhMrqcNmEEXYtAeES/p1mfmGNaV5X9lg6Qs/HyEFxVOJ2wEtEcn340xKVR100v4mx4CuRKTJh+dvALc+EUiLXICV5zOWM5ZtXQttOwbHvbjoNdTXYl664bVNP1zYespZJq8QBcYkdy
看sign这个鬼样子估计是和_token进行了一样的操作,试试看:
还真是。猜都可以猜到需要的变量是:
uuid:上篇文章已经说了获取方式了
cityname:显然是城市名
page:显然是页码
originUrl:显然就是诸如https://{城市拼音缩写}.meituan.com/meishi/&page=1,按以往经验,这个page有没有其实无所谓。
于是获取sign参数的函数可写为:
def getSIGN(cityname, page, uuid, city_code):
url = 'https://{}.meituan.com/meishi/'.format(city_code)
sign = 'areaId=0&cateId=0&cityName={}&dinnerCountAttrId=&optimusCode=1&originUrl={}&page={}&partner=126&platform=1&riskLevel=1&sort=&userId=&uuid={}'
sign = sign.format(cityname, url, page, uuid)
return sign
当然你也可以在那个js文件里搜索sign,然后看js代码慢慢分析。大概就是这样,完。
以上就是今天为大家带来的Python爬虫美团美食商家数据抓取的全部内容了,关注我持续输出干货,咱们下期内容再见。