免责声明
本教程仅用于教育目的,演示如何合法获取公开专利数据。在实际操作前,请务必:
1. 仔细阅读目标网站的robots.txt文件和服务条款
2. 控制请求频率,避免对服务器造成负担
3. 仅获取和使用公开数据
4. 不用于商业用途或大规模抓取
本次逆向查询药品接口:aHR0cHM6Ly93d3cubm1wYS5nb3YuY24vZGF0YXNlYXJjaC9kYXRhL25tcGFkYXRhL3NlYXJjaA==
1.打开控制台注入代码绕过无限debugger或者找调用堆栈使用本地替换js文件将循环创建debuger的部分删掉
let _Function = Function
Function = function (s) {
if(s==="debugger"){
return null
}
return _Function(s)
}
2.查找sign值加密位置 全局搜索检索到在ajax.js的getSign中
3.直接复制js再补环境
复制ajax.js、md5.js到本地项目,本地先运行看报错,注意看getSign函数调用了哪些方法,其他的不重要的报错可直接删除
最终项目结构:
//env.js
window = global
4.ajax.js中需要注意部分:
(1)getLoginToken
getCookie等方法node中没有,最快的方法就是直接删除或注释掉
(2)具体调用方法位置: 改写hasTokenGet函数
原方法返回值为
改写为返回加密后的sign值
'hasTokenGet': function(_0x194f10, _0x20d400) {
var _0x30b6f6 = {
'inoTo': _0xdfc7('f5', 'f[WA'),
'wyNxZ': function(_0x2d025f, _0x2003c1) {
return _0x2d025f + _0x2003c1;
},
'AlzcX': _0xdfc7('f6', 'C0n&'),
'rgvgy': function(_0x53dd9b, _0x31ed1e) {
return _0x53dd9b || _0x31ed1e;
},
'azOWI': function(_0x37bbec) {
return _0x37bbec();
},
'HUDdP': function(_0x3b1a0f, _0x198aca) {
return _0x3b1a0f === _0x198aca;
},
'kNYKd': _0xdfc7('f7', ')nUr'),
'AlUdj': 'pMSzI',
'GmLgF': function(_0x326050, _0x182779) {
return _0x326050(_0x182779);
},
'yWqYp': _0xdfc7('f8', 'A^Px'),
'ycJHx': function(_0x5e7cd7, _0x282811) {
return _0x5e7cd7(_0x282811);
}
};
_0x20d400 = _0x30b6f6[_0xdfc7('f9', '(TPJ')](_0x20d400, {});
var _0x37cd60 = false;
_0x20d400[_0xdfc7('fb', 'e4PG')] = _0x20d400['timestamp'];
let _0x2cd4d6 = getSign(_0x20d400);
for (let _0x1a609b in _0x2cd4d6) {
if (_0x30b6f6[_0xdfc7('fd', 'VfYA')](_0x30b6f6[_0xdfc7('fe', 'A8L]')], _0x30b6f6[_0xdfc7('ff', 'lios')])) {
app = _0x30b6f6[_0xdfc7('100', 'FE9r')];
let _0x3306b1 = _0x30b6f6[_0xdfc7('101', 'A8L]')](_0x30b6f6['wyNxZ'](app, _0x30b6f6['AlzcX']), _0x20d400);
location[_0xdfc7('102', 'n7gq')] = _0x3306b1;
} else {
if (_0x2cd4d6[_0x1a609b] == '') {
delete _0x2cd4d6[_0x1a609b];
}
}
}
let sign = _0x30b6f6[_0xdfc7('105', 'OmpI')](jsonMD5ToStr, _0x2cd4d6)
return sign
},
5.运行main.js
//main.js
require("./env")
require("./md5")
require("./ajax")
function get_sign(){
let url = 'https://www.nmpa.gov.cn/datasearch/data/nmpadata/search'
let params = {
'isSenior': 'N',
'itemId': 'ff80808183cad75001840881f848179f',
'pageNum': '1',
'pageSize': '10',
'searchValue': '国药准字H20063188',
'timestamp': 1749092062000,
}
let ops = {
url,
params
}
let e = pajax.hasTokenGet(ops.url, ops.params)
console.log(e)
}
get_sign()
返回结果与断点调试一致,说明加密破解完成
6.最后改写main.js传入搜索的动态参数(若需要查询其它参数可自行修改)
function get_sign(searchValue){
const timestamp = Math.floor(new Date().getTime() / 1000)*1000;
let url = 'https://www.nmpa.gov.cn/datasearch/data/nmpadata/search'
let params = {
'isSenior': 'N',
'itemId': 'ff80808183cad75001840881f848179f',
'pageNum': '1',
'pageSize': '10',
'searchValue': searchValue,
'timestamp': timestamp,
}
let ops = {
url,
params
}
let e = pajax.hasTokenGet(ops.url, ops.params)
return e
}
7.最后python中调用获取到的sign进行请求验证:
OK,本次逆向完成。