简介:跟紧作者步伐,看看如何利用本网站,在实际的爬虫项目中,起到的重要作用,帮助你采集数据,快人一步。
一、开发者工具抓包
抓包规则
在实际的采集项目中,想要采集到真正的数据,一般都是点击“下一页”来精准查看自己想要的接口。如果是通过刷新的方式,会加载处很多接口,一时间就会很难第一时间找到内容的接口是哪一个。
实际应用
https://api.mytoken.info/ticker/currencyranklist?pages=2%2C1&sizes=100%2C100&subject=market_cap&language=en_US&legal_currency=USD&code=68c1d781ee8c422a896f55d24e8e4aed×tamp=1774772411401&platform=web_pc&v=0.1.0&mytoken=
精准找到哦接口:可以看到,通过点击下一页的方式,开发者工具中加载出来的接口只有寥寥几个,从这几个接口中,只需稍微看一看,就能看到需要采集的数据在哪个接口当中
二、查看需要逆向的值
复制curl
在找到数据接口之后,在接口处鼠标“右键” - 复制 - 以cURL(bash)格式复制,然后再在本网站的首页 - curl转python ,直接将刚才复制的内容粘贴在文本框里面,不到一秒钟的时间,右侧就会同步输出python requests请求代码。
寻找逆向值
在右侧显示的python代码中,粗略一看,头部里面都是一些普通的内容。但在params中,一眼就看到了几个特别寻常的值
params = {
'pages': '2,1',
'sizes': '100,100',
'subject': 'market_cap',
'language': 'en_US',
'legal_currency': 'USD',
'code': '68c1d781ee8c422a896f55d24e8e4aed',
'timestamp': '1774772411401',
'platform': 'web_pc',
'v': '0.1.0',
'mytoken': '',
}
三、验证猜想
验证方式
将刚才网站生成的python代码复制到自己的代码编辑器里面,此时并不要急着运行代码。再去目标网站中点击下一页,并重复上面的两个步骤,重新复制curl,然后交给网站生成python代码,看看两次生成的代码中,有哪些发生了改变。
应对方案
params = {
'pages': '3,1',
'sizes': '100,100',
'subject': 'market_cap',
'language': 'en_US',
'legal_currency': 'USD',
'code': '59aeaccb2ffb02bf502ac56d4d435024',
'timestamp': '1774774532679',
'platform': 'web_pc',
'v': '0.1.0',
'mytoken': '',
}
文本对比:由于params中的内容比较少,可以清晰的看到,发生改变的就是pages、code、timestamp这三个值。pages和timestamp不用分析就知道是页数和时间戳,所以真正需要逆向的是code值
四、逆向分析
位置寻找
既然知道了code是需要逆向的参数,那就需要去目标网站中,找到code参数生成的位置。在实际的逆向项目中,找参数生成的方式一般有三种:
- 关键字搜索(在开发者工具的右上角有 ⋮ ,鼠标左键点击一下,在弹出的框中选择“搜索”,然后输入code关键字后,按下enter键就会出现源代码中有code这个关键字的地方)
- Hook方式(可以看到接口是get方式,code参数在url中,就可以采取hook url的方式,网上跟栈,寻找code加密的位置)
- XHR方式(这种方式可能是最慢找到的,但也是最稳妥能找到的方式,没有技巧,只能一步步网上跟栈)
目标定位
先尝试着用关键字搜索的方式,在搜索框中输入:code,发现出来的内容有很多,于是尝试着在后面添加一个英文状态下的冒号(:),再甄别里面的内容,将code:前面有多余内容的内容忽略掉,就可以看到只有几个位置符合我们的要求。不知道这几个位置哪一个才是真正需要的地方,就再每一个位置的前面打上断点,然后继续点击下一页。
通过加载下一页,就可以轻松的找到,我们目标参数的位置了。
var i = {
code: e,
timestamp: r,
platform: "web_pc",
v: "0.1.0",
mytoken: null !== n && void 0 !== n ? n : f()().get("mytoken_sid")
};
五、验证定位
虽然通过关键字搜索的方式,找到了几个code值生成的地方,也下了断点,但也不能保证断点停住的地方,真的就是params中code值生成的位置,所以还需要验证一下断点位置处。这里就可以在控制台中输入e值,然后让代码继续往下执行,去看看接口中code的值和控制台中的值是否一样。
控制台e值:59aeaccb2ffb02bf502ac56d4d435024
接口中code值:59aeaccb2ffb02bf502ac56d4d435024
六、参数逆向
在代码中code是通过e赋值得到的,那e是怎么来的呢,就不得不网上看。就能看到e生成的位置。
var r = Date.now().toString(), e = a()(r + "9527" + r.substr(0, 6))
将断点停留在e生成的位置处,可以看到a()是一个Function,而r + "9527" + r.substr(0, 6)就是一串字符串,就说明是a()方法中传入了r + "9527" + r.substr(0, 6)生成的字符串,得到了code值。
七、经验之谈
MD5基本了解
看到最后e的值的长度是32位,而且里面的内容似乎是从0-9a-f,这很符合MD5的特性。为了验证这里是不是真正的md5,可以在本网站 - 在线加解密 - 输入相同的字符串,可以看到得到的结果一模一样。这足以说明,这个e值就是用md5的方式,对r + "9527" + r.substr(0, 6)拼接的字符串进行处理得到的。
那么,r + "9527" + r.substr(0, 6)这个值又是怎么来的呢?不难看到,上一句var r = Date.now().toString(),就是将时间戳得到之后,再加9527,再加时间戳的(0, 6),得到md5加密实参。
八、本地复现
知道了加密原理之后,在本地用相同的方式得到code值,就算成功了一半。
本地代码
var crypto = require('crypto-js')
function get_code(timestamp) {
r = timestamp
e = crypto.MD5(r + "9527" + r.substr(0, 6)).toString()
return e
}
九、修改python代码
在python代码中,将e值替换成get_code(timestamp),就可以得到正确的code值了。
import requests
import execjs
import time
timestamp = str(int(time.time() * 1000))
js_code = execjs.compile(open('1.js','r',encoding='utf-8').read())
code = js_code.call('get_code', timestamp)
headers = {
'accept': '*/*',
'accept-language': 'zh-CN,zh;q=0.9',
'cache-control': 'no-cache',
'origin': 'https://www.mytokencap.com',
'pragma': 'no-cache',
'priority': 'u=1, i',
'referer': 'https://www.mytokencap.com/',
'sec-ch-ua': '"Chromium";v="146", "Not-A.Brand";v="24", "Google Chrome";v="146"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'cross-site',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36',
}
url = "https://api.mytoken.info/ticker/currencyranklist"
params = {
'pages': '3,1',
'sizes': '100,100',
'subject': 'market_cap',
'language': 'en_US',
'legal_currency': 'USD',
'code': code,
'timestamp': timestamp,
'platform': 'web_pc',
'v': '0.1.0',
'mytoken': '',
}
response = requests.get(url, params=params, headers=headers)
print(response.json())
总结
在实际的爬虫逆向过程中,很多的东西都是从猜开始的。大胆的猜,并去验证自己的猜想,是逆向过程中的关键。勇于试错,反正错了也没关系。
但是在猜的过程中,也需要有原理性的猜,并不是说看到哪里,就觉得哪里是我们逆向的目标。