Python系列爬蟲之美團美食板塊商家數據抓取(三)


image.png

昨天分享了一個美團美食板塊的小爬蟲。很多人私信說不明白_token參數到底怎么來的,真的沒時間一一回復,干脆再推送一篇文章,來詳細講講_token參數到底是怎么搞出來的。這次,我盡量寫的詳細一些。

image

詳解

_token參數:

image

上回我們說到我們猜測_token參數是原數據先進行二進制壓縮然后進行base64編碼獲得的,反向操作一波:

image

證實了我們的猜測,即_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吧。所以我們可以搞個文件,保存這些參數的常見值:

image

然后每次隨機獲取一個就行了,代碼體現為:

'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進行了一樣的操作,試試看:

image

還真是。猜都可以猜到需要的變量是:

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代碼慢慢分析。大概就是這樣,完。

image

以上就是今天為大家帶來的Python爬蟲美團美食商家數據抓取的全部內容了,關注我持續輸出干貨,咱們下期內容再見。

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM