ApkBus.java
package me.shumei.open.oks.apkbus;
import java.io.IOException;
import java.util.HashMap;
import org.jsoup.Connection.Method;
import org.jsoup.Connection.Response;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.jsoup.Jsoup;
/**
* 安卓巴士的操作类
*
* @author 蠻荒搜神
*
*/
public class ApkBus extends CommonData {
// 这里放置常量
/** 登录页面 */
private final static String LOGIN = "http://www.apkbus.com/member.php?mod=logging&action=login&mobile=yes";
/** 登录提交信息的地址 */
private final static String LOGIN_ACTION = "http://www.apkbus.com/member.php?mod=logging&action=login&loginsubmit=yes&mobile=yes&loginhash=";
/** 签到页面 */
private final static String SIGN = "http://www.apkbus.com/plugin.php?id=dsu_paulsign:sign&mobile=yes";
/** 签到提交信息的地址 */
private final static String SIGN_ACTION = "http://www.apkbus.com/plugin.php?id=dsu_paulsign:sign&operation=qiandao&infloat=0&inajax=0&mobile=yes";
/** 获取下载豆的地址 */
private static final String GET_POINT = "http://www.apkbus.com/home.php?mod=spacecp&ac=credit&showcredit=1&inajax=1&ajaxtarget=extcreditmenu_menu";
public String name, password, formhash, loginhash;// 依次是用户名,密码,formhash,loginhash,后两个都是抓包之后看到需要用到的
public HashMap<String, String> cookies;// cookies,你的一些数据,比如说登录的数据
/**
* 初始化ApkBus
*
* @param name
* 用户名
* @param password
* 密码
*/
public ApkBus(String name, String password) {
// 如果直接输入name那么java优先认为是在方法内部的变量/参数
// 所以这里必需用this.name
/*
* 如果是其它名字,那么加不加this都无所谓比如:public ApkBus(String n, String p)
* 这里就可以用name=n;
*/
this.name = name;
this.password = password;
cookies = new HashMap<String, String>();
}
/***
* 登录
*
* @return 返回一个2维String数组:1为成功,0为失败,后面附带信息
*/
public String[] login() {
// 定义提交的data,包括用户名和密码
HashMap<String, String> data = new HashMap<String, String>();
// 查一下API文档 public V put(K key,V value),解释一下:key对应名称 value对应值
// data.put不用分先后
// 下面的都是通过抓包的来的,抓包涉及另外的知识,在这我不便多说
data.put("answer", "");// 问题的回答,我没有设置
data.put("cookietime", "2592000");
data.put("fastloginfield", "username");
data.put("password", this.password);// 后面的password是类变量 密码
data.put("username", this.name);// 后面的name是类变量 用户名
data.put("questionid", "0");
data.put("referer", "http://www.apkbus.com/./");
data.put("submit", "登录");
// 现在开始准备登录
Response res = null;
try {
// 先访问登录页面
res = Jsoup.connect(LOGIN).cookies(cookies).userAgent(UA_ANDROID)
.timeout(TIME_OUT).execute();
cookies.putAll(res.cookies());// 保存cookies,每一步几乎都要保存
String html = res.parse().select("form").get(1).attr("action");// 选择网页form便签的第2条(java从0开始数)的action属性的值
loginhash = Tool.getText(html, "loginhash=", "&");// Tool是我自己写的小工具,根据两个文本取得中间文本,理论上用这里的Jsoup也可以,但是我嫌麻烦
// 这里才是开始登陆动作
res = Jsoup.connect(LOGIN_ACTION + loginhash).cookies(cookies)
.data(data).method(Method.POST).userAgent(UA_ANDROID)
.timeout(TIME_OUT).execute();
cookies.putAll(res.cookies());// 记得保存cookies
if (res.body().contains("登录失败")) {// 密码错误
html = Tool.getText(res.body(), "登录失败", "次");
return new String[] { "0", "密码错误" + html + "次" };
}
if (res.body().contains("密码错误次数过多")) {
return new String[] { "0", "密码错误次数过多,请 15 分钟后重新登录" };
}
} catch (IOException e) {// 如果没有连接就会抛出异常,然后直接返回
// TODO Auto-generated catch block
e.printStackTrace();
return new String[] { "0", "连接超时" };
}
// 如果有异常上面就会捕捉,就不会运行到这了
return new String[] { "1", "登录成功" };
}
/**
* 签到
*
* @return 返回签到信息,到时候会显示在屏幕上
*/
public String sign() {
// 签到提交的信息
HashMap<String, String> data = new HashMap<String, String>();
data.put("fastreply", "0");
data.put("qdmode", "1");
data.put("qdxq", "kx");// 你的心情,kx就是开心
data.put("todaysay", "签到");// 签到的文本
Response res = null;
String info = getSignInfo();// 获得签到信息
data.put("formhash", formhash);// 获取信息的时候取得formhash;
if (!info.equals("")) {// 返回""就是已签到,不能用==判断,String和int long
// boolean不一样,是类,不是基本数据类型,自己看API文档就会知道
return "今日已签到过!\n" + getPoint() + info;// 注意这里是直接返回,不会运行下面的代码
} else {
try {
// 执行签到动作
res = Jsoup.connect(SIGN_ACTION).cookies(cookies)
.method(Method.POST).userAgent(UA_ANDROID)
.timeout(TIME_OUT).data(data).execute();
cookies.putAll(res.cookies());
info = res.parse().select("p").first().text();// 得到签到得多少下载豆的信息
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "连接超时";
}
}
info = getPoint() + info;
info += getSignInfo();// 注意这里info+=...等于info=info+... 这是java的缩写习惯
// 有的人会觉得getSignInfo()重复执行了.
// 如果签到过就不会运行到这了,如果没签到过是需要重新获取签到信息的
return "签到成功!\n" + info;
}
/**
* 获取签到信息
*
* @return 获取签到信息,如果未签到则返回"",已签到返回签到信息,会显示在屏幕上
*/
public String getSignInfo() {
Response res = null;
String html = null;
String info = "";// 不能用null,不然info开头会带null,到时候还要删掉
try {
// 访问签到页面
res = Jsoup.connect(SIGN).cookies(cookies).userAgent(UA_ANDROID)
.timeout(TIME_OUT).execute();
cookies.putAll(res.cookies());// 记得保存cookies
formhash = res.parse().select("input").get(1).attr("value");// 得到网页的input标签的第2个元素的value属性的值,这个是查看网页得来的
html = res.parse().text();// 将网页全部解析为文本
if (html.contains("您今天已经签到过了或者签到时间还未开始")) {// 已签到
Elements eles = res.parse().select("p");
for (int i = 0; i < 6; i++) {
if (i != 2) {
info += "\n" + eles.get(i).text();
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return info;// 如果未签到则返回""
}
/**
* 获取下载都
*
* @return 总共多少下载豆
*/
public String getPoint() {
Response res;
String point = null;
try {
// 访问获取下载都的页面,要靠抓包
res = Jsoup.connect(GET_POINT).cookies(cookies).userAgent(UA_IE8)
.timeout(TIME_OUT).execute();
cookies.putAll(res.cookies());// 保存cookies
Element ele = Jsoup.parse(res.parse().text()).getElementById(
"hcredit_4");// 这是解析网页的,在电脑上不断分析得来的
point = "共有下载豆:" + ele.text();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "";// 异常返回""
}
return point;// 返回得到的point
}
}