综合之前的知到答题和四史答题,在这里写一些总结,
爬取题库,倒也不是什么高大上的东西,之前写的python爬题库,也不过是记录自己的学习结果,实在不会也可以复制粘贴。
然后是对题库的处理,主要是对replace的运用,实际上你用文档自带的替换可能更快更简单。
先将文档保存到手机上,脚本能访问到的位置即可
参照之前的autojs之自动答题
//读取文档
path="/storage/emulated/0/脚本/行政.js"
var tiku =files.read(path)
//处理特殊字符
pattern=/[`~!@#$^&*()=|';'“”\\\[\]\.<>\/?~!@#¥……&*()——|【】';:'。,、?\s]/g;
tiku = tiku.replace(pattern,"")
//转换为键值对
tiku = eval("(" + tiku + ")");
//只有你的题库文档中有地方格式不对,这个eval就会报错
//必须是这样:{"题目":"答案","题目":"答案"}
使用autojs悬浮窗,分析页面,获得题目和选项的唯一标识
//点击答案
click(daan)
//这个答案选项的text属性里就是"我是答案字符串",所以可以直接点击
//四史中就不可以了,下面讲解
也可能需要多种属性确定:
className(“android.view.View”).depth(“8”).drawingOrder(“0”).indexInParent(“2”)
//获取题目
var wenti = className("android.view.View").depth("8").drawingOrder("0").indexInParent("2").findOnce().text()
//多种属性不是每个都必须,只要能确定唯一指向题目或答案字符串即可
//然后也要对获取的题目进行处理,去除所有特殊字符
最难的就属四史答题了
大家仔细观察这张图片,有没有发现和知到答题有什么不同
没错,四史答题中把题目和选项都切分成了好多小块,这样就没办法通过上面两个方法获得题目和点击答案了,而且网上竟然找不到和我一样的问题,可是把我难为了好几天,尝试了好多种方法(比如就用其中的一块文字进行匹配,还有通过属性标识进行拼接获得完整的文字,也想过通过截图然后百度识图提取题目和选项,但是因为种种原因,这些方法都不好使),最后采取了比较靠谱的方法:
-对于题目,可以通过提取整个页面的文字,然后根据开头【单/多选题】和结尾【出题:武汉大学】/[题目来源:湘潭/西安交通/上海交通大学],将中间的题目提取出来;
控件 = className("android.view.View").find();
题目 = ''
jj = 0
for (i = 0; i < 控件.length; i++) {
控件里的文字 = 控件[i].text();
if (控件里的文字 != "") {
题目 += 控件里的文字;
if (控件里的文字.indexOf('学】') > -1 || 控件里的文字.indexOf('学]') > -1) {
break
}
}
}
if (题目.indexOf("题】") != -1) {
//【单选题】【多选题】
var index = 题目.indexOf("题】")
题目 = 题目.substring(index + 2, 题目.length)
}
if (题目.indexOf("【出题:武汉大学】") != -1) {
var index = 题目.indexOf("【出题:武汉大学】")
题目 = 题目.substring(0, index)
}
if (题目.indexOf("[题目来源:") != -1) {
//[题目来源:湘潭大学西安交通大学上海交通大学]
var index = 题目.indexOf("[题目来源:")
题目 = 题目.substring(0, index)
}
//对获取的题目进行处理,去除所有特殊字符
pattern = /[`~!@#$^&*()=|{}':;'“”,\\\[\]\.<>\/?~!@#¥……&*()——|{}【】';:""'。,、?\s]/g;
题目 = 题目.replace(pattern, "")
log(题目)
-对于选项,用上面的方法能提取出文字,但是!四个选项都连在一起,分不清ABCD!所以采取了新的处理方法:
从上图可以看到选项被切割了,但是它们还在同一个父框里,所以我通过找父控件,然后获得它的孩子孙子控件中的包含文字的控件,再拼接在一起就是选项了。
for (i = 0; i < 4; i++) {
选项[i] = ''
if (className("RadioButton").depth("24").indexInParent(i).findOnce())
className("RadioButton").depth("24").indexInParent(i).findOne().children()
.forEach(function (child) {
//log(child.className());
if (child.className() == "android.view.View") {
if (child.text() != "") {
if (选项[i] != child.text())
选项[i] += child.text()
//log(child.text());
}
else {
child.children()
.forEach(function (child) {
// log(child.className());
if (child.text() != "") {
if (选项[i] != child.text())
选项[i] += child.text()
//log("!" + child.text());
}
});
}
}
});
log(选项[i]);
}
可以看到套了很多层(2层)判断,那是因为四史答题里面,选项的文字,它可能是儿子里包含文字,也可能是孙子,还可能是曾孙子(我遇到过曾孙子的情况,但是懒得写了就没加判断)。。。我没有很好的办法一下子提取所有的,所以只能挨个判断了,如果有更好的思路,欢迎提出,一起讨论。
还是参见知到答题
/*
*匹配答案
* 题库中[第i个题目].indexof(题目)>-1,表示匹配到问题
* 返回答案
*/
function 匹配答案(题库, 题目) {
i = 0
flag = 0
while (Object.keys(题库)[i]) {
if (Object.keys(题库)[i].indexOf(题目) > -1) {
flag = 1
var 答案 = 题库[Object.keys(题库)[i]]
return 答案
}
i++;
}
if (flag == 0) 提示文本("没有匹配到问题,自行作答,百度搜索") //没有写百度搜索
return -1
}
四史答题和知到答题的不同之前已经说了,所以没办法直接click(daan),
上面获取了选项,存储在 选项[i] 中
这里通过if (答案.indexOf(选项[j]) > -1),获得的i就是要点击的选项的indexInParent(j)
单选:
随机位置x = className("android.widget.RadioButton").depth("24").indexInParent(j).findOnce().bounds().centerX() + random(0, 100)
随机位置y = className("android.widget.RadioButton").depth("24").indexInParent(j).findOnce().bounds().centerY() + random(0, 30)
click(随机位置x, 随机位置y)
多选:
随机位置x = className("android.widget.CheckBox").depth(23).indexInParent(j).findOnce().bounds().centerX() + random(0, 100)
随机位置y = className("android.widget.CheckBox").depth(23).indexInParent(j).findOnce().bounds().centerY() + random(0, 30)
click(随机位置x, 随机位置y)
整体框架:
function 点击答案(答案) {
if (答案 == -1) {
if (!多选) {
toast("无匹配,默认点击第2个")
。。。
}
else if (多选) {
toast("默认全选")
。。。
}
}
else {
if (!多选) {
for (j = 0; j < 4; j++) {
}
if (答案.indexOf(选项[j]) > -1) {
}
}
else if (多选) {
for (j = 0; j < 4; j++) {
}
if (答案.indexOf(选项[j]) > -1) {
}
}
}
}
具体参见四史答题
其他的好像也没什么了,想起来再评论补充,对于验证码,ui,多线程,我的处理还不是很好,再学习学习,之后再总结吧
有我没有写到的,可以评论。
感谢点赞,评论,收藏,关注!