Java实现百度贴吧自动签到器

   转载请声明出处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小时再次签到。将用户名和密码填上就可以了。

就这么多了,不保证百度后台升级后程序会一直有效。


源码下载

    

猜你喜欢

转载自blog.csdn.net/zhongkejingwang/article/details/39995909