1. 写在前面

  最近有位读者找上了作者,需要采集易车网上面一些汽车相关的数据,用以毕业设计使用。据了解读者的情况会一点Python,也懂一点爬虫(但是到什么程度不详~~

使用Python爬取易车网汽车信息(含x-sign参数逆向分析)-LMLPHP

按照描述的话,应该是说在获取详情页数据的时候,接口有参数加密?接下来将本次的分析分享出来供大家参考学习,难度算是入门级,适合各位学习爬虫技术的新手小伙伴们!最后完整的代码也提供给了读者

2. 接口分析

老规矩,这里的话更多车型需要登录才可显示更多数据,打开详情页面,监测一下请求发包,请求头内X-sign应该是加密生成的,如下所示:

使用Python爬取易车网汽车信息(含x-sign参数逆向分析)-LMLPHP

X-User-Guid参数的话看着像是用户唯一标识的值,可固定!后面断点分析的时候发现这个参数在CK信息内获取就可以了,如下所示:

使用Python爬取易车网汽车信息(含x-sign参数逆向分析)-LMLPHP

然后详情接口buy_car_calculator_info跟同系二手车推荐接口get_recommend_ucar_list只需提交两个参数,分别是cidparam,参数在响应接口内均可找到,如下所示:

?cid=508&param={"serialId":"7350"}
?cid=508&param={"cityId":"201","serialId":"7219","type":1,"count":8}

3. 断点分析

X-sign参数32位,这里大概率还是MD5加密,先全局搜索一下参数,可以直接在JS文件找到,下个断刷新一下,如下所示:

使用Python爬取易车网汽车信息(含x-sign参数逆向分析)-LMLPHP

单步跟到s方法内,这个方法是加密核心位置,我们直接把代码拿下来分析一下,如下所示:

function s(e, t) {
	var n = "";
	if ("headers" == e.encryptType) {
	    var i = e.data ? JSON.stringify(e.data) : "{}"
	      , o = r(e, t);
	    n = "cid=" + t.cid + "&param=" + i + o + t.timestamp
	} else {
	    var a = [];
	    a.push("cid=" + t.cid),
	    a.push("uid=" + t.uid),
	    a.push("ver=" + t.ver),
	    a.push("devid=" + (e.deviceId || "")),
	    a.push("t=" + t.timestamp),
	    a.push("key=" + t.paramsKey),
	    n = a.join(";")
	}
	var s = yicheUtils.md5(n);
	return s
	}

相信到这里,有经验的小伙伴都知道如何还原了,MD5加密,然后n是加密的对象,其中o是一个固值,请求参数加上o跟时间戳加密生成最终签名,如下所示:

使用Python爬取易车网汽车信息(含x-sign参数逆向分析)-LMLPHP

3. 算法还原

下面我们分别使用多种语言来还原一下上面sign加密算法,首先使用Python进行实现,如下所示:

import hashlib
import time

timestamp = str(int(time.time() * 1000))
param = '' # 请求参数
cid = ''
o = '19DDD1FBDFF065D3A4DA777D2D7A81EC'
n = f'cid={cid}&param={param}{o}{timestamp}'

obj = hashlib.md5()
obj.update(n.encode('utf-8'))
sign = obj.hexdigest()

print(sign)

NodeJS实现方式如下:

const crypto = require('crypto');

const timestamp = new Date().getTime().toString();
const param = '';
const cid = '';
const o = '19DDD1FBDFF065D3A4DA777D2D7A81EC';
const n = `cid=${cid}&param=${param}${o}${timestamp}`;

const hash = crypto.createHash('md5');
hash.update(n);
const sign = hash.digest('hex');

console.log(sign);

Golang实现方式如下:

package main

import (
    "crypto/md5"
    "encoding/hex"
    "fmt"
    "strconv"
    "time"
)

func main() {
    timestamp := strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10)
    param := ""
    o := "19DDD1FBDFF065D3A4DA777D2D7A81EC"
    cid := ""
    n := "cid=" + cid + "&param=" + param + o + timestamp

    hash := md5.New()
    hash.Write([]byte(n))
    sign := hex.EncodeToString(hash.Sum(nil))

    fmt.Println(sign)
}

最后作者也是编写了一个完整的爬虫Demo发送给了那位读者,测试结果如下所示:

使用Python爬取易车网汽车信息(含x-sign参数逆向分析)-LMLPHP

04-21 11:38