声明:本文仅供技术交流,切忌非法使用。
今天我们要抓取的是猪场某游收藏总榜的信息。
下图是收藏榜总榜的部分商品,一看这金额???果然是有钱人玩的游戏啊,到底是什么样的属性能让其价值连城?鼠标放到装备图标上,我们可以看到装备的详细信息,那么如何抓取下来呢?
我们从网页源代码中能清楚地看到价格的显示,根据英文猜测,具体的信息应该在这个"equip_desc"中,这一串字符串应该是加密之后的装备信息。
那么任务就是来解决这个加密的破解。根据equip_desc搜索相关信息
经过排查之后发现,decode_desc 这个名字翻译过来不就是“解密描述”吗?
看来解密的源头应该在这个js文件中,也就是util.js。我们打开这个js文件来进行分析。
打上断点之后发现这个decode_desc指的就是g函数
那么g函数是什么样的呢?
这个样子显然就是混淆加密了,把变量名、函数名、参数名给替换成诸如_0xcbc80b这样没有意义的表示,还利用了十六进制表示字母。
翻译成英文字母是不是看着顺眼多了呢?
从头逐步执行js代码,与此同时观察传入的值
具体的js也可以用python改写,但由于逻辑不够直观,可以利用execjs库执行js代码。
需要利用js调试工具WebStorm,改写部分js代码,可以把其用十六进制表示的字母转换过来,写成直观的函数。
比如
_0x36ab38['\x70\x75\x73\x68'](_0xcbc80b['\x53\x74\x72\x69\x6e\x67']['\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65'](_0xcbc80b['\x70\x61\x72\x73\x65\x49\x6e\x74'](_0x1c0cdf[_0x33c80e], 0x2)));
可以写成
_0x36ab38['\x70\x75\x73\x68'](String.fromCharCode(parseInt(_0x1c0cdf[_0x33c80e], 0x2)));
解决了js的问题,我们可以轻松的编写代码如下,利用简单的正则匹配提取加密后的内容,并利用js解密得到文字。
import requests
import re
import json
import execjs
from pymongo import MongoClient
import time
class CBG(object):
def __init__(self):
self.url='https://xyq.cbg.163.com/cgi-bin/equipquery.py?act=overall_rank&rank_type=31&page={}'
self.headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'}
self.conn=MongoClient('127.0.0.1', 27017)
self.db=self.conn.MHXY
def get_json(self,i):
r=requests.get(self.url.format(i),headers=self.headers)
js=re.findall(r"var data = (.*);",r.text)[0]
js=json.loads(js)
return js
def decode(self,data):
with open('test.js','r') as f:
javascript=f.read()
ctx=execjs.compile(javascript)
real_content=ctx.call('get_g',data)
return real_content
def get_highlights(self,data):
highlights=data.encode().decode("unicode_escape")
return highlights
def get_equip_info(self,i):
js=self.get_json(i)
equip_list=js["equip_list"]
for equip in equip_list:
gem_level=equip['gem_level']
large_equip_desc=self.decode(equip['large_equip_desc'])
sum_dex=equip['sum_dex']
create_time=equip['create_time']
collect_num=equip['collect_num']
highlights=self.get_highlights(equip['highlights'])
price=equip['price']
rank=equip['rank']
expire_time=equip['expire_time']
server_name=equip['server_name']
item={
'gem_level':gem_level,
'large_equip_desc':large_equip_desc,
'sum_dex':sum_dex,
'create_time':create_time,
'collect_num':collect_num,
'highlights':highlights,
'price':price,
'rank':rank,
'expire_time':expire_time,
'server_name':server_name
}
self.db['cbg'].insert_one(item)
if __name__=='__main__':
mhxycbg=CBG()
for i in range(1,11):
mhxycbg.get_equip_info(i)
time.sleep(1)
print("第{}页装备信息已存入数据库!".format(i))