转载请声明出处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<String> mLikeBars; // 关注的贴吧首页 private List<String> mLikeBarsUrls; public BaiduSignUp() { mLikeBars = new ArrayList<String>(); mLikeBarsUrls = new ArrayList<String>(); 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<NameValuePair> params = new ArrayList<NameValuePair>(); 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小时再次签到。将用户名和密码填上就可以了。
源码下载