转载请声明出处http://blog.csdn.net/zhongkejingwang/article/details/39995909
前段时间经常逛贴吧,每次都要手动签到,有时候也会忘记签到,很麻烦。于是就想用Java写个自动签到的工具并部署到实验室的服务器上,这样就可以常年自动签到了。于是就有了这篇文章,权当玩玩。
将此程序放到服务器后台运行就可以了,不用再担心断签~
要签到首先要登录然后再获取贴吧页面里的签到链接。由于Java自带的http的API使用起来很不方便,这里使用的是Apache的httpclient(只用到了三个jar包,后面会提供下载),用post方法提交表单数据即可,关于表单的item参数可以用chrome浏览器抓包分析一下(按F12)。登录地址选择百度的手机网页端:http://wappass.baidu.com/passport/login这个地址,这样的话服务器端识别为手机签到,可以加分。在代码中将用户名和密码提交到这个地址即可,在去年的时候抓包分析过这个页面提交的数据还是明文的....现在已经升级了,网页是经过加密后提交的密码,不过明文提交还是可以登录。
登录完了需要获取贴吧首页中用户关注的所有贴吧,在这个地址http://tieba.baidu.com/mo,获取网页特定内容需要用到html解析工具,这里使用的是Jsoup,可以在这里看使用教程http://www.open-open.com/jsoup/
获取到关注贴吧的首页然后把该贴吧的html页面拉下来一份,检索看看有没有包含“sign”字符串,没有表示已经签到了;有则获取对应的签到地址,访问改地址即可签到成功。
关于添加依赖包:在eclipse中右键工程—>属性—>Java 构建路径—>库(L)里添加外部JAR,就可以了。
关于怎么打包成可执行的jar包:这里有依赖的jar包,建议将依赖的jar包一块打包进去,可以使用eclipse打包,具体步骤:
右键工程—>导出—>Java—>可运行的jar包,点击下一步,在接下来的选项中选择Package required libraries into generated JAR:
这样就可以很方便的把jar包上传到服务器执行了。否则手动打包需要写MANIFEST.MF清单文件,指定Class-Path,指向所有依赖包,否则运行时找不到依赖包,比较麻烦。所以还是建议用eclipse打包吧。。。
过程讲完了可以讲代码了。写一个SignUpTool接口:
package com.jingchen.util;
public interface SignUpTool {
/**
* 用户登录
*
* @param username
* 用户名
* @param passwd
* 密码
* @return 登录成功返回true,失败则返回false
*/
boolean login(String username, String passwd);
/**
* 签到
*
* @return 签到成功返回true,失败则返回falses
*/
boolean signUp();
}
接口包含了登录和签到方法,此接口不同的实现可以登录不同的网站。
写一个HttpUtil,封装post和get操作:
package com.jingchen.util;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
public class HttpUtil {
private HttpClient mHttpClient;
private CookieStore mCookieStore;
private HttpContext mContext;
private HttpPost post;
private HttpGet get;
public HttpUtil() {
mHttpClient = new DefaultHttpClient();
mCookieStore = new BasicCookieStore();
mContext = new BasicHttpContext();
}
public HttpResponse post(String url, HttpEntity he)
throws ClientProtocolException, IOException {
post = new HttpPost(url);
post.setEntity(he);
mContext.setAttribute(ClientContext.COOKIE_STORE, mCookieStore);
HttpResponse hr = mHttpClient.execute(post, mContext);
return hr;
}
public String get(String url) throws ClientProtocolException, IOException {
String result = null;
get = new HttpGet(url);
HttpResponse hr = mHttpClient.execute(get, mContext);
result = EntityUtils.toString(hr.getEntity());
return result;
}
}
实现SignUpTool接口的BaiduSignUp:
package com.jingchen.util;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
/**
* 用于登录百度贴吧账号并签到的类
*
* @author jingchen
*
*/
public class BaiduSignUp implements SignUpTool {
// 登录链接
private String mLoginUrl = null;
// 登录后跳转的页面
private String mIndexUrl = null;
// 获取网页中的相对路径拼接上这个头部构成完整请求路径
private String mUrlHead = null;
// 是否需要验证码
private boolean isAuth = false;
private HttpUtil httpUtil;
// 关注的贴吧
private List mLikeBars;
// 关注的贴吧首页
private List mLikeBarsUrls;
public BaiduSignUp() {
mLikeBars = new ArrayList();
mLikeBarsUrls = new ArrayList();
httpUtil = new HttpUtil();
mLoginUrl = "http://wappass.baidu.com/passport/login";
mIndexUrl = "http://tieba.baidu.com/mo";
mUrlHead = "http://tieba.baidu.com";
}
public boolean login(String username, String passwd) {
isAuth = false;
mLikeBars.clear();
mLikeBarsUrls.clear();
print("login...");
List params = new ArrayList();
params.add(new BasicNameValuePair("username", username));
params.add(new BasicNameValuePair("password", passwd));
HttpEntity he;
try {
he = new UrlEncodedFormEntity(params, "UTF-8");
HttpResponse hr = httpUtil.post(mLoginUrl, he);
String firstresult = EntityUtils.toString(hr.getEntity());
if (firstresult.contains("verifycode")) {
// 在异地登录或者登录频繁会出现验证码
isAuth = true;
print("需要验证码");
return false;
} else if (firstresult.contains("error_area")) {
print("密码错误");
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
print("登录成功");
return true;
}
public boolean signUp() {
if (isAuth) {
print("需要验证码");
return false;
}
print("signUp...");
if (mLikeBars.size() != 0) {
mLikeBars.clear();
mLikeBarsUrls.clear();
}
if (!getLikeBars())
return false;
try {
for (int i = 0; i < mLikeBars.size(); i++) {
String barview = getWebContent(mLikeBarsUrls.get(i));
if (!barview.contains("sign"))
print(mLikeBars.get(i) + "已签到");
else {
Elements signurl = Jsoup.parse(barview)
.getElementsByAttributeValueMatching("href",
".*sign.*");
getWebContent(mUrlHead + signurl.attr("href"));
print(mLikeBars.get(i) + "签到成功");
}
}
} catch (Exception e) {
e.printStackTrace();
print("fail in signUp!");
return false;
}
return true;
}
/**
* 获取关注的贴吧
*
* @return
*/
private boolean getLikeBars() {
print("getLikeBars...");
String indexresult = getWebContent(mIndexUrl);
if (indexresult == null)
return false;
Document document = Jsoup.parse(indexresult);
Elements likebars = document.select("div.my_love_bar a");
for (Element e : likebars) {
mLikeBarsUrls.add(mUrlHead + e.attr("href"));
mLikeBars.add(e.text());
}
if (mLikeBars.size() == 0)
return false;
return true;
}
/**
* 获取网页内容
*
* @param url
* 链接地址
* @return 网页内容
*/
private String getWebContent(String url) {
print("getWebContent...");
String result = null;
try {
result = httpUtil.get(url);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return result;
}
public void print(String s) {
System.out.println(s);
}
}
包含main方法的主类:
package com.jingchen.main;
import com.jingchen.util.BaiduSignUp;
import com.jingchen.util.SignUpTool;
public class MainClass {
public static String username = "******";
public static String passwd = "******";
public static int mInterval = 30;
public static void main(String[] args) {
boolean isSignup = false;
boolean isLogin = false;
SignUpTool tool = new BaiduSignUp();
// SignUpTool tool = new BBSLogin();
while (true) {
try {
isLogin = tool.login(username, passwd);
isSignup = tool.signUp();
if (isLogin && isSignup) {
// 签到成功则三小时后再签到
System.out.println("continue after three hours...");
Thread.sleep(3 * 60 * 60 * 1000);
} else {
// 签到失败则30分钟后再次签到
System.out.println("continue after " + mInterval
+ " minites...");
Thread.sleep(mInterval * 60 * 1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
每次签到前都先登录,签到失败则等半小时再尝试,签到成功则等待3小时再次签到。将用户名和密码填上就可以了。源码下载