问卷星反爬手段越来越丧心病狂,截至目前2021.10.18,提交参数已有13个之多,肝了几天,终于把最恶心的jqParam参数搞定,顺便记录下其他相关参数的生成及获取过程
提交参数分析
https://ks.wjx.top/joinnew/processjq.ashx?shortid=PpH6DjX&starttime=2021%2F10%2F18%2014%3A37%3A56&source=directphone&submittype=1&ktimes=79&hlv=1&rn=1975429446.43363516&jqpram=MHieF5pMt&jcn=%E5%A7%9A%E5%90%84&iwx=1&t=1634539304658&jqnonce=daa66ca2-ed5b-4434-85df-9c4a4ed13ee2&jqsign=mhh%3F%3Fjh%3B%24lm%3Ck%24%3D%3D%3A%3D%241%3Cmo%240j%3Dh%3Dlm8%3All%3B
如上是一次提交的相关参数,其中包括shortId
、starttime
、source
、submittype
、ktimes
、hlv
、rn
、jqpram
、jcn
、iwx
、t
、jqnonce
以及jqsign
,不过令人庆幸的是,相当一部分参数是可以直接在页面中获取或是固定值的,给我们减少了很大的工作量!泪目!
参数分类
上述13个参数大致可分为三大类,分别是:固定参数
、可从页面获取参数
及计算参数
固定参数
此类参数在自己测试过程中发现其值为固定值,到目前为止还没有发现有变化的情况,大佬们仅供参考,它们分别是:
submittype
:固定值为1 (tips: 此参数好像是标识问卷类型,自己一直做的是“考试、试卷”类型,因此该值并未发现有变化,如是其他类型答卷请自行调整)hlv
:固定值1iwx
:固定值1
可从页面获取参数
此类参数在请求页面时会附加在页面中,可以通过xpath
定位或正则表达式自行获取,它们分别是:
shortid
source
starttime
jqnonce
rn
activityId
(此参数并未在提交参数中,但是后续计算需要该数据进行运算)
该类参数在不同的设备(如微信和PC)下其定位方式(xpath
路径)不同,如做通用类爬虫请注意
计算参数
此类参数并不能直接获取,需要通过一定的运算才能获取
ktimes
:随机数(此数据较为特殊,建议10-300内任意整数即可)t
:时间戳(毫秒级时间戳,暂没发现有何特殊时间,可以使用当前时间的时间戳)jcn
jqsign
jqpram
:最头疼的参数,代码混淆,需要花时间自己好好摸索
jcn
及jqsign
的计算相对较为简单,其计算方式如下
ctx = execjs.compile('''function dataenc(a, ktimes) {
var c, d, e, b = ktimes % 10;
for (0 == b && (b = 1),
c = [],
d = 0; d < a.length; d++)
e = a.charCodeAt(d) ^ b,
c.push(String.fromCharCode(e));
return c.join("")
}''')
# jqsign
jqsign = ctx.call("dataenc", jqnonce, ktimes)
# jcn计算
jcn = ctx.call("dataenc", '姓名', ktimes)
jqpram
的运算过程较为复杂,因为需要处理代码混淆,其js
代码逻辑如下
function abcd3(_0x420610, _0x1b425f) {
if (_0x420610 - 62 < 0) {
var _0xea36a8 = _0x1b425f['substr'](_0x420610, 1);
return _0xea36a8;
}
var _0x45571c = _0x420610 % 62;
var _0x4e6181 = parseInt(_0x420610 / 62);
return abcd3(_0x4e6181, _0x1b425f) + _0x1b425f['substr'](_0x45571c, 1);
}
function abcdx() {
var _0x5314ef = ['3', '4', '2', '0', '1']
, _0xbb87ee = 0x0;
while (!![]) {
switch (_0x5314ef[_0xbb87ee++]) {
case '0':
if (undefined || undefined)
return ![];
continue;
case '1':
return !![];
case '2':
if (false)
return ![];
continue;
case '3':
if (false)
return ![];
continue;
case '4':
if (undefined)
return ![];
continue;
}
break;
}
}
function abcd4(_0x11dbf0, _0x1558df) {
var _0x24b247 = ['1', '3', '0', '4', '2', '5']
, _0x505c79 = 0;
while (!![]) {
switch (_0x24b247[_0x505c79++]) {
case '0':
var _0x27312b = _0x1558df.length;
continue;
case '1':
if (!abcdx())
return;
continue;
case '2':
_0x1558df = _0x556c7b.join('');
continue;
case '3':
var _0x556c7b = _0x1558df.split('');
continue;
case '4':
for (var _0x107cfb = 0; _0x107cfb < _0x11dbf0.length; _0x107cfb++) {
var _0x172a4c = ['0', '3', '2', '1', '4']
, _0x5ca706 = 0;
while (!![]) {
switch (_0x172a4c[_0x5ca706++]) {
case '0':
var _0x410c33 = parseInt(_0x11dbf0[_0x107cfb]);
continue;
case '1':
_0x556c7b[_0x410c33] = _0x433a77;
continue;
case '2':
var _0x433a77 = _0x556c7b[_0x27312b - 1 - _0x410c33];
continue;
case '3':
var _0x43a652 = _0x556c7b[_0x410c33];
continue;
case '4':
_0x556c7b[_0x27312b - 1 - _0x410c33] = _0x43a652;
continue;
}
break;
}
}
continue;
case '5':
return _0x1558df;
}
break;
}
}
function abcd2(_0x1b1e02, _0x23f273) {
var _0x303591 = "9|5|2|3|0|7|6|1|8|4".split('|')
, _0x15e51e = 0x0;
while (!![]) {
switch (_0x303591[_0x15e51e++]) {
case '0':
var _0x470088 = ~~(_0x23f273 / _0x1f9ba1);
continue;
case '1':
var _0x353774 = _0x4ad458 ^ _0x470088;
continue;
case '2':
var _0x3b83ae = 2147483647;
continue;
case '3':
var _0x4ad458 = ~~(_0x1b1e02 / _0x1f9ba1);
continue;
case '4':
return _0x353774 * _0x1f9ba1 + _0x4a742c;
case '5':
var _0x1f9ba1 = 2147483648;
continue;
case '6':
var _0x35dfa5 = _0x23f273 & _0x3b83ae;
continue;
case '7':
var _0x5bc159 = _0x1b1e02 & _0x3b83ae;
continue;
case '8':
var _0x4a742c = _0x5bc159 ^ _0x35dfa5;
continue;
case '9':
if (!abcdx())
return;
continue;
}
break;
}
}
function abcd1(_0x17164c) {
return abcd2(_0x17164c, 3597397)
}
function abcd5(_0x5565b6) {
var _0x3260f4 = "7|5|2|8|3|1|4|0|6|9".split('|')
, _0x56f3ce = 0;
while (!![]) {
switch (_0x3260f4[_0x56f3ce++]) {
case '0':
for (var _0x28a6c3 = _0x5258e0; _0x28a6c3 < _0x5af006; _0x28a6c3++) {
_0x2b24c5.push(_0x5ed7b1[_0x28a6c3]);
}
continue;
case '1':
var _0x5258e0 = _0x546e81 % _0x5af006;
continue;
case '2':
var _0x5ed7b1 = _0x5565b6.split('');
continue;
case '3':
var _0x5af006 = _0x5565b6.length;
continue;
case '4':
var _0x2b24c5 = [];
continue;
case '5':
var _0x546e81 = 0;
continue;
case '6':
for (var _0x28a6c3 = 0; _0x28a6c3 < _0x5258e0; _0x28a6c3++) {
_0x2b24c5.push(_0x5ed7b1[_0x28a6c3]);
}
continue;
case '7':
if (!abcdx())
return;
continue;
case '8':
for (var _0x28a6c3 = 0; _0x28a6c3 < _0x5ed7b1.length; _0x28a6c3++) {
_0x546e81 += _0x5ed7b1[_0x28a6c3].charCodeAt();
}
continue;
case '9':
return _0x2b24c5.join('');
}
break;
}
}
function get_jqParam(activityId, rndnum, time) {
var _0x3098bf = rndnum.split('.')[0]
var _0x4aaf4a = abcd1(parseInt(_0x3098bf))
var _0x4eae39 = time // 当前时间时间戳
var _0x5050a2 = _0x4eae39 + ''
if (_0x4eae39 % 10 > 0)
_0x5050a2 = _0x5050a2.split('').reverse().join('')
_0xd16fcc = parseInt(_0x5050a2 + '89123')
_0x149db2 = _0xd16fcc + '' + 1971866899 + ''
_0x149db2 = _0x149db2.split('')
_0x1b3de6 = abcd4(_0x149db2, 'kgESOLJUbB2fCteoQdYmXvF8j9IZs3K0i6w75VcDnG14WAyaxNqPuRlpTHMrhz')
var _0x3a5cf2 = _0xd16fcc + _0x4aaf4a + parseInt(activityId ^ 2130030173)
jqParam = abcd3(_0x3a5cf2, _0x1b3de6);
_0x5d90fd = abcd5(jqParam)
jqParam = _0x5d90fd
return jqParam
}
计算时直接调用函数get_jqParam
,其三个参数activityId
、rndnum
(就是之前获取的参数rn
)及time
(就是之前获取的参数t
)