言成言成啊 | Kit Chen's Blog

今日校园实现自动监测并提交最新表单

发布于2020-05-06 20:06:46,更新于2021-02-10 23:08:01,标签:java open spider  文章会持续修订,转载请注明来源地址:https://meethigher.top/blog

站在巨人的肩膀上,我所写的东西,也会开源分享出来!

授人以鱼不如授人以渔,我把思路分享出来。

将源码放在这里今日校园实现自动检测并提交最新表单,也可以来这里给我的视频点个赞吖!

一、抓包(重点)

1.1 如何抓包

Fiddler4电脑端与手机端抓包的教程,我不多bb了。点这个链接里面有具体步骤,这个大佬是专门学习机器学习的,他的博客放到这里

一开始,我是用的Fiddler4来进行抓包的,但是涉及到ssl-pinning的问题。导致抓包失败,也就是抓取过程中,一堆灰色链接。同时,手机上的网路也会被断开。

fiddler抓包中遇到的问题

无法抓https

android7+用户级证书不被信任

fiddler使用介绍

之后,我就开始考虑,要不用手机抓包,就下载了HttpCannary,HttpCanary有普通版和高级版之分,建议下载高级版,同样会遇到ssl-pinning的问题,具体解决方法请移步到系统证书的安装,解决APP抓不到包,下载软件点这里

如果碰到HttpCanary强制更新,可以参照我的这篇文章来自穷逼对HttpCanary的蹂躏,当然了,如果有全球通用的信用卡的话,支持正版哦!

1.2 我的解决方法

此节是废话,请略过。

我一开始用幸运破解器,破解HttpCanary高级版,很幸运的是,虽然显示破解授权失败,但打开的时候,发现能用了。

下一步,就是安装系统证书了,我就把手机root了,我的手机是小米的,直接root就行。

但是,还是在安装系统证书的过程中出了问题,不能往系统里面移动证书,原因是没有权限。

后来百度了一下,发现,MIUI的root权限,从Android7之后,就没有完整的root权限了。除非刷第三方系统。

但是我又舍不得自己的MIUI12。

接下来,就准备用模拟器了,我下载的是逍遥安卓模拟器。安卓的是4.4版本系统,刷入了xposed框架,安装了justtrustme模块。这个是大佬的解决方法

然后,打开Fiddler抓包,Yes!

有了Cpdaily-Extension跟MOD_AUTH_CAS这两条数据,就能模拟提交了。

此处是2020年5月30日更新,用android4.4毕竟不是个好的解决办法,因为现在好多app已经不支持旧版了。那么还得需要root,然后用HttpCanary抓包。

我手机是android10,想要抓加密包的话,就得安装系统证书,安装到系统文件下。

经过一番折腾,成功了。具体过程看小米root去掉HttpCanary强制更新

2021年1月21日更新,有小伙伴手机又不想root,我建议可以自己淘个二手的爱疯。我500淘了个二手的爱疯7,成色一般,但是功能都正常,像更老的爱疯,更便宜。安装stream软件之后,无脑抓包,啥都不用配,想咋抓咋抓。如果没有那个条件,你想折腾的话,可以用ios模拟器

抓包问题就此解决。耗费了我一整天的时间。

提交过程中碰到的坑:

  1. 今日校园版本过低。这是因为你提交的内容格式不对,按抓包的流程来一遍。
  2. 返回乱码消息。这是因为提交的表单内容,中文部分出现了编码问题,建议以utf-8格式发送。

二、Java模拟post请求

这个算是套模板吧,都是这个套路,直接上代码。不要拿来就用,还是根据实际情况进行修改的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
* HttpUtil类
*
* @author kit chen
* @description 用来模拟发送请求
*/
public class HttpUtil {

public static String sendGet(String url, Map<String, String> headers) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url;
URL realUrl = new URL(urlNameString);
URLConnection conn = realUrl.openConnection();
Set<Entry<String, String>> set = headers.entrySet();
for (Entry<String, String> header : set) {
conn.setRequestProperty(header.getKey(), header.getValue());
}
conn.connect();
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}

public static String sendPost(String url, String param, Map<String, String> headers) {
BufferedWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
Set<Entry<String, String>> set = headers.entrySet();
for (Entry<String, String> header : set) {
conn.setRequestProperty(header.getKey(), header.getValue());
}
conn.setDoOutput(true);
conn.setDoInput(true);
out = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), "utf-8"));
out.write(param);
out.flush();
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!" + e);
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
}

三、模拟请求中的问题

通过抓包获取了请求头跟请求参数,请求参数还好说。

在抓取请求头的时候,遇到了点问题。

通过测试发现,如果想要成功提交内容,需要Cpdaily-Extension跟MOD_AUTH_CAS。

如果设备不去主动退出的话,Cpdaily-Extension是会一直存在有效的。类似的像QQ也是这样的。我在抓取Cpdaily-Extension的过程中,尝试访问各种页面,但是都没法获取到这个的值。哪怕是在登录的时候,也没有这个参数。只有在提交的时候,才能抓取到。

像MOD_AUTH_CAS这个的值,就是个session值,是有有效期的。session一般的有效期是30分钟,但是我们用java开启一个线程之后,是可以让session长久有效的。

问了大佬,好像是涉及到了cas单点登录的知识,这块我也不懂。学!大致的意思,就是在多个系统中,用户只需要登录一次,各个系统即可感知该用户已经登录了

通过这点呢,我们就可以知道,在网页端获取的已登录时的cookie,同样可以用于手机端。由此,我们可以通过保持在网页的session,使在app端的session有效

下述为2021年2月10日更新

在HttpUtil发送请求获取html时,一直报错为乱码,我尝试修改编码,发现没用。后来删掉所有请求头,竟然正确了,百度了下,发现是accept-encoding:gzip, deflate, br的问题。

accept-encoding表示告诉服务器,客服端支持的压缩方式,如果没有的话,就是不支持压缩。

所以携带该请求头访问的是压缩后的数据,但是java获取后,没有进行解压缩,所以就乱码了。解决方案就是去掉accept-encoding。

参考

Java伪造ip地址,可以通过请求头X-Forwarded-For来伪造,但是这种的一般只适于小白菜做的网站,但凡明眼人,一眼就看透了。

参考

四、监测表单并返回表单号

今日校园有个获取今日最新表单的接口,如果没有的话,里面某个数据会是个空数组。

接口

1
/wec-counselor-collector-apps/stu/collector/queryCollectorProcessingList

post的请求参数

1
{"pageSize": 6,"pageNumber": 1}

这个pageSize是指每页返回几条数据,响应请求中,我记得返回的json字符串,最多就只有6个参数,所以这个传个6就行了。大于等于6

返回的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"code": "0",
"message": "SUCCESS",
"datas": {
"totalSize": 0,
"pageSize": 6,
"pageNumber": 1,
"rows": [
"wid":"xx",
"formWid":"xx",
"isHandled":"0"
"...":"..."
]
}
}

我们要的就是这个wid、formWid跟isHandled。isHandled表示是否提交,非0为提交。

监测到有rows有数据,并且isHandled未提交的时候,我们就可以进行模拟提交了。

五、获取学校表单号

这个还有一个坑就是,每天的学校的表单号schoolTaskWid不是固定的,由此,我们就需要来模拟请求来获取schoolTaskWid

接口

1
/wec-counselor-collector-apps/stu/collector/detailCollector

post请求参数

1
{"collectorWid": 传进来第三步获取的collectWid}`

注意:

这sb接口开发者,一开始定义的是collectWid,结果后面又成了collectorWid,一开始在这边把我给坑了,需要注意。

这个接口获取的是collectorWid,第三步获取的是collectWid,其实他俩是一个东西。

大致的返回内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
"code": "0",
"message": "SUCCESS",
"datas": {
"collector": {
"wid": "8888",
"formWid": "164",
"priority": "5",
"endTime": "8888-88-88 88:00:00",
"currentTime": "8888-88-88 88:00:00",
"schoolTaskWid": "8888",
"isConfirmed": 1,
"senderUserName": "牛逼学院(牛逼老师)",
"createTime": "8888-88-88 88:00:00",
"attachmentUrls": null,
"attachmentNames": null,
"attachmentSizes": null,
"isUserSubmit": 1,
"fetchStuLocation": true,
"address": "xx省xx市xx县"
},
"form": {
"wid": "164",
"formTitle": "8月8日学生身体健康状况调查",
"formContent": "https://wecres.cpdaily.com/counselor/1076158768111098/content/d1c0daf5604af56fbccfadaf28cdbd82.html",
"backReason": null,
"isBack": 0,
"attachments": []
}
}
}

这里我们获取需要的schoolTaskWid。

六、获取详细表单

今日校园还有一条验证就是每次请求的表的id,以及表选项的id都是变化的。

所有,我们还需要抓取表的详细表单。

接口

1
/wec-counselor-collector-apps/stu/collector/getFormFields

参数

1
{"pageSize":30,"pageNumber":1,"formWid":formWid,"collectorWid":collectorWid}

返回的内容,依你们老师的设定为准,不放结果了。

七、模拟Post请求提交

7.1 思路

接口

1
/wec-counselor-collector-apps/stu/collector/submitForm

通过上面,我们获取到了formWid,collectWid,schoolTaskWid,address,form。

2021年1月6日更新:

今日校园以前的表单是自动选择了历史选择的选项,所以直接提交就行了。

现在的版本,全部都得自己选,我的方法是通过关键词来过滤,比如我的关键词是“37度以下”、“健康”、“否”

接下来,我们构造出post的json字符串请求体。

发送!

成功!

7.2 邮件通知

如果提交成功,或者提交失败。都会发通知邮件给我。

但是,试了几次,经常报错554 DT:SPM,也就是被当做垃圾邮件驳回了。

尝试了好几个邮箱,像139,163,qq邮箱,都会有这个问题,网上说设置端口啊,不要25,要465…开启ssl…等等

如果涉及到敏感词,什么签到、自动,仍然没有一个奏效的,都没当成垃圾邮件处理。

刚好看到一个大佬写的博客,建议用腾讯企业邮箱,试了一下,果然ok了。

记录一次Could not connect to SMTP host: smtp.163.com, port: 25的解决办法

腾讯云或者阿里云,是默认禁用25端口的

我附上发邮件的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class SendMail {
public static String send(String[] mail) {
Properties properties = new Properties();
properties.put("mail.transport.protocol", "smtp");// 连接协议
properties.put("mail.smtp.host", "smtp.exmail.qq.com");// 主机名
properties.put("mail.smtp.port", "587");// 端口号
properties.put("mail.smtp.auth", "true");//设置smtp是否需要认证
properties.put("mail.smtp.ssl.enable", "true");// 设置是否使用ssl安全连接 ---一般都使用
properties.put("mail.debug", "false");// 设置是否显示debug信息 true 会在控制台显示相关信息
try{
Session session = Session.getInstance(properties);
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(Data.fromMail));
message.setRecipient(Message.RecipientType.TO, new InternetAddress(Data.toMail));
message.setSubject(mail[0]);
message.setText(mail[1]);
message.setSentDate(new Date());
Transport transport = session.getTransport();
transport.connect(Data.fromMail, Data.fromMailPw);//登录发信账号
transport.sendMessage(message, message.getAllRecipients());
transport.close();
return "邮件发送成功";
}catch (Exception e){
return "邮件发送失败";
}
}
}

7.3 运行结果

  • 获取到新表单,则提交。提交成功或失败,24小时之后,再次监测新表单提交
  • 未获取到表单数据,继续监测,间隔2小时

八、总结

8.1 感谢大佬

python版今日校园自动签到、填表

python版今日校园自动填报脚本

java定时刷新网页

手机抓包教程第四节——系统证书的安装,解决APP抓不到包

记录一次Could not connect to SMTP host: smtp.163.com, port: 25的解决办法

java抓取网页指定元素/内容

模拟登陆系列

QQ空间模拟登录

Java获取302时的内容

还是那句话,站在巨人的肩膀上

多亏了有大佬们的指点

8.2 个人收获

连着两天,早上5点就起。

因为这个是学校的老师发的表单,我没有老师权限,没法模拟。

所以,只能,每天早起,在表单未提交之前,进行测试。这也是最难受的一点。

今天专业课考试,我当时写代码写得正在兴头上,结果作业没给交上去。估计这学期也就考个60分吧。无所谓了,反正我也不是学霸,计较个锤子。而且,我这学期,也都没咋听课,天天在家里就知道玩。每次都下定决心好好学习,结果,嘿嘿…

总得来说,抓包还是很关键的。

这个博客算是整理整个的思路,如果思路看明白了,那么,实现这样的功能就不难了。

我看网上也有不少的类似程序,但是大多数是Python开发的,确实,Python在处理数据的时候,很舒服,给我的感觉,就是跟JavaScript一样,就是舒服。PHP如果实现这个功能的话,也会比较轻松。

由于我现在正在学java,还没学透,正好可以拿这个练练手。毕竟,java就像是我的初恋,虽然她身材很臃肿,但我依然爱她啊!

处理过程中,真的感觉人生苦短,多用python

像这样的功能,好多编程语言都能实现,Java不是不能,只是太繁琐了。

如果我再次写这个的话,首选Python,其次Nodejs。

在分层方面,还是觉得自己做地不太好,像学过的继承多态,我在处理的过程中,就是一直在硬写、闷头写。自己的代码也能看得出毛病来,但是想优化,却又不知从何改起。一方面,是对学过的东西,没有彻底理解;另一方面,也是自己的项目经验太少了。

一定要花时间,弥补这方面的不足!

发布:2020-05-06 20:06:46
修改:2021-02-10 23:08:01
链接:https://meethigher.top/blog/2020/cpdaily-automation/
标签:java open spider 
付款码 打赏 分享
若无法评论请科学上网
Shift+Ctrl+1 可控制工具栏