以
https://www.wjx.cn/jq/35713991.aspx
这个问卷页为例
填完问卷打开控制台,转到network并且勾选preserver log(不然等会儿提交的请求看不到),点提交,找到此次提交请求如下:
是post请求,转到下面查看请求参数和post表单提交携带的参数(问卷答案):
发现请求url里面带了9个参数。经过多次请求对比发现submittytype,curld,hlv没有变,其中不难发现curlid就是我们第一次请求
https://www.wjx.cn/jq/35713991.aspx
这个问卷页面的一个值,即代表了问卷id。
先说t和starttiem,爬虫参数多半是设置和时间有关,经过换算下当前时间毫秒数,基本接近t,因此判定t要么是出站时间要么是进站时间,经过下一次的对比(记录好进入问卷调查页面时间和点击提交的时间),确定了t是问卷提交时间的毫秒数,而starttime则是进入问卷调查页面的时间。
再说rn和jqnonce,我先爬取问卷页面,用jsoup解析返回的问卷html,在html中搜索得到了这两个值(在js中)。
最后一个jqsign,这个参数在js文件里面加密了。先来到问卷调查页面,打开控制台,选择提交按钮,定位到页面元素如下:
这是一个表单提交按钮,再次在控制台定位到右边资源,选择事件监听,打开click标签,发现了提交触发的js:
接着点进js文件,全部选中复制到站长这儿(
http://tool.chinaz.com/Tools/jsformat.aspx
)格式化之后在保存进自己的编辑器便于查看。接着在js文件里面搜关键字jqsign,如下图:
发现在拼接字符串,就是在拼接提交表单的url,jqsign的值是b经过url编码的,在java可以使用如下方式进行编码解码:
URLEncoder.encode("S","UTF-8");
URLDecoder.decode("S","UTF-8");
那么再看上图的3,发现b是经过dataenc这个函数得来的,传入的参数正是之前获取到的jqnonce。
接着在js文件搜关键字dataenc得到如下函数:
这即是jqsign参数加密的函数,先将ktime值取模,第二步我查了下优先级,发现是如果b为0那么就赋值为1,否则直接就使用b的值,然后紧接着for循环,charCodeAt和fromCharCode都是js的函数,分别是将字符串转为unicode编码和将unicode编码转为字符串。for循环第一步是将传入的a(即已知的jqnonce)每个字符转为unicode值之后再与b进行位运算,第二部是将位运算的结果转为字符串并且添加到d中,最后返回加密的字符串。在java中实现如下:(命名有点乱,测试用的)
public static String dataenc(String jqnonce) {
int ktime = 365;
// 模拟js算出jqsign
StringBuffer g = new StringBuffer();
String d[] = new String[]{};
for (int c = 0; c < jqnonce.length(); c++) {
int b = ktime % 10;
if (b == 0) b = 1;
char[] temp = jqnonce.toCharArray();
String unicodeValue = getUnicode(temp[c]);
int f = Integer.valueOf(unicodeValue.toString()).intValue() ^ b;
if (c != 0) {
g.append(",");
}
g.append(String.valueOf(f));
String h = asciiToString(g.toString());
}
String jqsign = d.toString();
System.out.println("rn " + rn + "jqnonce " + jqnonce + " jqsign " + jqsign);
}
//getUnicode函数
public static String getUnicode(char c) {
String returnUniCode = null;
returnUniCode = String.valueOf((int) c);
return returnUniCode;
}
/**
* Ascii转换为字符串
*
* @param value
* @return
*/
public static String asciiToString(String value) {
StringBuffer sbu = new StringBuffer();
String[] chars = value.split(",");
for (int i = 0; i < chars.length; i++) {
sbu.append((char) Integer.parseInt(chars[i]));
}
return sbu.toString();
}
最后再模拟个表单提交,基本上就能完成自动答卷了(注意ip最好轮换)
以上内容仅做学习用途