[原]Java模拟新浪和腾迅自动登录并发送微博(2013年3月更新可用)

标签: | 发表时间:2013-03-14 16:47 | 作者:supercrsky
出处:http://blog.csdn.net/supercrsky

1.准备工作

  只是登录无需申请新浪和腾迅的开发者账号,如果需要发送微博功能,需要申请一个新浪和腾迅的开发者账号,并添加一个测试应用。

 过程请参考官方帮助文档,申请地址:新浪:http://open.weibo.com    腾迅:http://dev.t.qq.com/

我们需要的是App Key和App Secre及redirect_URI,源代码中已经包含了我申请的测试key,但由于限制直接用我的key你们的账号是无法登录成功的。


2.注意事项

 1)需要注意的是应用的App Key和App Secre及redirect_URI,对应项目根目录下的config.properties配置文件中的

client_ID=1745656892
client_SERCRET=66056719c1d8ca7bcaf36f411217cefa
redirect_URI=www.baidu.com

redirect_URI由于只是测试用并没有直接的回调页面,所以这里随便填写一个地址就行了,但要注意与应用-高级设置里的“回调页面”一致。

2)代码中的测试账号需要要自己添加测试账号,新浪的在“应用信息-测试账号”;腾迅的在“权限控制-创建白名单”中。当然直接用

开发者账号也可以。

3)发送微博引用了新浪的 weibo4j-oauth2-beta2.1.1.zip,腾迅的 Java_SDK_v1.2.1.7z。核心类在util包下。

3.关键代码

1)新浪

package org.utils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.http.HttpException;
import org.core.weibo.sina.Oauth;
import org.core.weibo.sina.Timeline;
import org.core.weibo.sina.http.AccessToken;
import org.core.weibo.sina.model.WeiboException;
import org.core.weibo.sina.weibo4j.util.WeiboConfig;
/***
 * 模拟自动登录并发微博
 * @author zdw
 *
 */
public class Sina {
	/***
	 * 模拟登录并得到登录后的Token
	 * @param username  用户名
	 * @param password  密码
	 * @return
	 * @throws HttpException
	 * @throws IOException
	 */
	public static  AccessToken getToken(String username,String password) throws HttpException, IOException 
	{
			String clientId = WeiboConfig.getValue("client_ID") ;
			String redirectURI = WeiboConfig.getValue("redirect_URI") ;
			String url = WeiboConfig.getValue("authorizeURL");
			
			PostMethod postMethod = new PostMethod(url);
			//应用的App Key 
			postMethod.addParameter("client_id",clientId);
			//应用的重定向页面
			postMethod.addParameter("redirect_uri",redirectURI);
			//模拟登录参数
			//开发者或测试账号的用户名和密码
			postMethod.addParameter("userId", username);
			postMethod.addParameter("passwd", password);
			postMethod.addParameter("isLoginSina", "0");
			postMethod.addParameter("action", "submit");
			postMethod.addParameter("response_type","code");
			HttpMethodParams param = postMethod.getParams();
			param.setContentCharset("UTF-8");
			//添加头信息
			List<Header> headers = new ArrayList<Header>();
			headers.add(new Header("Referer", "https://api.weibo.com/oauth2/authorize?client_id="+clientId+"&redirect_uri="+redirectURI+"&from=sina&response_type=code"));
			headers.add(new Header("Host", "api.weibo.com"));
			headers.add(new Header("User-Agent","Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0"));
			HttpClient client = new HttpClient();
			client.getHostConfiguration().getParams().setParameter("http.default-headers", headers);
			client.executeMethod(postMethod);
			int status = postMethod.getStatusCode();
			System.out.println(status);
			if (status != 302)
			{
				System.out.println("token刷新失败");
				return null;
			}
			//解析Token
			Header location = postMethod.getResponseHeader("Location");
			if (location != null) 
			{
				String retUrl = location.getValue();
				int begin = retUrl.indexOf("code=");
				if (begin != -1) {
					int end = retUrl.indexOf("&", begin);
					if (end == -1)
						end = retUrl.length();
					String code = retUrl.substring(begin + 5, end);
					if (code != null) {
						Oauth oauth = new Oauth();
						try{
							AccessToken token = oauth.getAccessTokenByCode(code);
							return token;
						}catch(Exception e){
							e.printStackTrace();
						}
					}
				}
			}
		return null;
	}
	/**
	 * 发微博
	 * @param token  认证Token
	 * @param content  微博内容
	 * @return
	 * @throws Exception
	 */
	public static boolean sinaSendWeibo(String token,String content) throws Exception {
		boolean flag = false ;
		Timeline timeline = new Timeline();
		timeline.client.setToken(token);
		try 
		{
			timeline.UpdateStatus(content);
			flag = true ;
		} 
		catch (WeiboException e) 
		{
			flag = false ;
			System.out.println(e.getErrorCode());
		}
		return flag;
	}
	
	public static void main(String[] args) throws Exception
	{
		AccessToken at = getToken("xxxx","xxx");
		sinaSendWeibo(at.getAccessToken(),"测试呢");
	}
}

腾迅:

package org.utils;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.util.Scanner;

import net.sf.json.JSONObject;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.core.weibo.tencent.api.UserAPI;
import org.core.weibo.tencent.oauthv2.OAuthV2;
import org.core.weibo.tencent.oauthv2.OAuthV2Client;

/***
 * 腾迅自动登录并获取个人信息
 * @author zdw
 *
 */
public class Tencent
{
	public static final String HEXSTRING = "0123456789ABCDEF";
	public static OAuthV2 oAuth = new OAuthV2();
	private static HttpClient client = new DefaultHttpClient();
	// 初始oAuth应用信息
	public static void init(OAuthV2 oAuth)
	{
		oAuth.setClientId("801216331");
		oAuth.setClientSecret("ea71b26b0cbe5778cdd1c09ad17553a3");
		oAuth.setRedirectUri("http://www.tencent.com/zh-cn/index.shtml");
	}
	/**
	 * 
	 * @param qq
	 *            http://check.ptlogin2.qq.com/check?uin={0}&appid=15000101&r={1 }
	 *            返回的第三个值
	 * @param password
	 *            QQ密码
	 * @param verifycode
	 *            验证码
	 * @return 加密后的密码
	 * @throws UnsupportedEncodingException
	 * @throws Exception
	 * 
	 */
	public static String GetPassword(String qq, String password,
			String verifycode) throws Exception
	{
		String P = hexchar2bin(md5(password));
		String U = md5(P + hexchar2bin(qq.replace("\\x", "").toUpperCase()));
		String V = md5(U + verifycode.toUpperCase());
		return V;
	}
	
	public static String md5(String originalText) throws Exception
	{
		byte buf[] = originalText.getBytes("ISO-8859-1");
		StringBuffer hexString = new StringBuffer();
		String result = "";
		String digit = "";
		try
		{
			MessageDigest algorithm = MessageDigest.getInstance("MD5");
			algorithm.reset();
			algorithm.update(buf);
			byte[] digest = algorithm.digest();
			for (int i = 0; i < digest.length; i++)
			{
				digit = Integer.toHexString(0xFF & digest[i]);
				if (digit.length() == 1)
				{
					digit = "0" + digit;
				}
				hexString.append(digit);
			}
			result = hexString.toString();
		}
		catch (Exception ex)
		{
			result = "";
		}
		return result.toUpperCase();
	}

	public static String hexchar2bin(String md5str) throws UnsupportedEncodingException
	{
		ByteArrayOutputStream baos = new ByteArrayOutputStream(md5str.length() / 2);
		for (int i = 0; i < md5str.length(); i = i + 2)
		{
			baos.write((HEXSTRING.indexOf(md5str.charAt(i)) << 4 | HEXSTRING
					.indexOf(md5str.charAt(i + 1))));
		}
		return new String(baos.toByteArray(), "ISO-8859-1");
	}
	/***
	 * 模拟登录
	 * @param qq QQ号码 
	 * @param password QQ密码
	 * @throws Exception
	 */
	public static void login(String qq, String password) throws Exception
	{
		HttpGet get = new HttpGet("https://ssl.ptlogin2.qq.com/check?uin="+ qq + "&appid=46000101&ptlang=2052&js_type=2&js_ver=10009&r=0.7948186025712065");
		HttpResponse response = client.execute(get);
		String entity = EntityUtils.toString(response.getEntity());
		String[] checkNum = entity.substring(entity.indexOf("(") + 1,entity.lastIndexOf(")")).replace("'", "").split(",");
		String pass = "";
		String responseData = "";
		// 获取验证码(如果有验证码输出到C:/code.jpg,查看后输入可继续执行
		if ("1".equals(checkNum[0]))
		{
			// uin为qq号或者微博用户名
			HttpGet getimg = new HttpGet("http://captcha.qq.com/getimage?aid=46000101&r=0.3478789969909082&uin=" + qq + "&vc_type=" + checkNum[1] + "");
			HttpResponse response2 = client.execute(getimg);
			OutputStream os = new FileOutputStream("c:/code.jpg");
			byte[] b = EntityUtils.toByteArray(response2.getEntity());
			os.write(b, 0, b.length);
			os.close();
			Scanner in = new Scanner(System.in);
			responseData = in.nextLine();
			in.close();
		}
		else
		{
			responseData = checkNum[1];
		}
		/** *******************加密密码 ************************** */
		pass = GetPassword(checkNum[2], password, responseData);
		/** *********************** 登录 *************************** */
		HttpGet getimg = new HttpGet("https://ssl.ptlogin2.qq.com/login?ptlang=2052&u="+ qq+ "&p="+ pass+ "&verifycode="+ responseData+ "&aid=46000101&target=top&u1=https%3A%2F%2Fopen.t.qq.com%2Fcgi-bin%2Foauth2%2Fauthorize%3Fclient_id%3D"
						+ oAuth.getClientId()+ "%26response_type%3Dcode%26redirect_uri="+ oAuth.getRedirectUri()+ "&ptredirect=1&h=1&from_ui=1&dumy=&qlogin_param=abbfew=ddd&wording=%E6%8E%88%E6%9D%83&fp=loginerroralert&action=8-13-240977&g=1&t=1&dummy=&js_type=2&js_ver=10009");
		HttpResponse response2 = client.execute(getimg);
		HttpEntity httpentity = response2.getEntity();
		String entityxc = EntityUtils.toString(httpentity);
		System.out.println(entityxc);
	}

	/**
	 * 
	 * 请求微博开放平台应用 返回登录授权页面,但是如果没有sessionKey的话永远登录不成功 sessionKey
	 * 发现在返回的页面中一个input标签里放的url中有,所以要取到这个sessionKey 其实直接访问标签中的url就可以跳转
	 * 
	 */
	public static String getUrl() throws ClientProtocolException, IOException
	{
		HttpGet getcode = new HttpGet("https://open.t.qq.com/cgi-bin/oauth2/authorize?client_id="+ oAuth.getClientId()+ "&response_type=code&redirect_uri="
										+ oAuth.getRedirectUri()+ "&checkStatus=yes&appfrom=&g_tk&checkType=showAuth&state=");
		HttpResponse response3 = client.execute(getcode);
		HttpEntity entityqqq = response3.getEntity();
		String entityxcc = EntityUtils.toString(entityqqq);
		String form = entityxcc.substring(entityxcc.indexOf("<form"), entityxcc
				.indexOf("</form>"));
		String[] ss = form.split("/>");
		String input = "";
		for (int i = 0; i < ss.length; i++)
		{
			if (ss[i].indexOf("name=\"u1\"") > 0)
			{
				input = ss[i];
			}
			;
		}
		return input.substring(input.indexOf("value=\"") + 7, input.indexOf("\" type=\""));
	}
	/**
	 * 解析并设置Token
	 * @param get
	 * @throws Exception 
	 */
	public static void setToken(HttpGet get) throws Exception
	{
		HttpResponse response4 = client.execute(get);
		HttpEntity entityqqq1 = response4.getEntity();
		String getUrlcode = EntityUtils.toString(entityqqq1);
		// 返回了最终跳转的页面URL,也就是回调页redirect_uri,页面地址上包含code openid openkey
		// 需要将这三个值单独取出来再拼接成 code=xxxxx&openid=xxxxx&openkey=xxxxxx的形式
		String entity = getUrlcode.substring(getUrlcode.indexOf("url="),getUrlcode.indexOf("\">"));
		StringBuffer sb = new StringBuffer();
		String[] arr = entity.split("\\?")[1].split("&");
		for (int x = 0; x < arr.length; x++)
		{
			if (arr[x].indexOf("code") >= 0 || arr[x].indexOf("openid") >= 0
					|| arr[x].indexOf("openkey") >= 0)
			{
				sb.append(arr[x] + "&");
			}
			;
		}
		// 利用code获取accessToken
		OAuthV2Client.parseAuthorization(sb.substring(0, sb.length() - 1), oAuth);
		oAuth.setGrantType("authorize_code");
		OAuthV2Client.accessToken(oAuth);
	}
	/***
	 * 调用(腾迅开放平台账户接口)获取一个人的信息
	 * @throws Exception 
	 */
	public static void getInfo() throws Exception
	{
		//输出Token,如果拿到了Token就代表登录成功,并可以进行下一步操作。
		System.out.println("Token="+oAuth.getAccessToken());
		UserAPI getuser = new UserAPI(oAuth.getOauthVersion());
		String userJson = getuser.otherInfo(oAuth, "json", "", oAuth.getOpenid());
		JSONObject userJsonObject = JSONObject.fromObject(userJson);
		Integer errcode = (Integer) userJsonObject.get("errcode");
		if (errcode == 0)
		{
			JSONObject userdataJsonObject = (JSONObject) userJsonObject.get("data");
			System.out.println(userdataJsonObject.toString());
		}
	}
	
	public static void main(String[] args) throws Exception
	{
		init(oAuth);
		login("123145", "xxxx");
		HttpGet get = new HttpGet(getUrl());
		setToken(get);
		getInfo();
	}



}

4.发送成功都有对应的日志输出

新浪(最后一行日志):

2078 DEBUG [2013-03-14 16:35:29]  {"created_at":"Thu Mar 14 16:35:30 +0800 2013","id":3555791132949940,"mid":"3555791132949940","idstr":"3555791132949940","text":"测试呢","source":"...

腾迅:

登录成功的日志标志:

ptuiCB('0','0','https://open.t.qq.com/cgi-bin/oauth2/authorize?client_id=801216331&response_type=code&redirect_uri=http:','1','登录成功!', 'ㄗs:ヤ淡 啶');
查看个人信息成功后的日志标志:

QHttpClient httpGet [3] Response = {"data":{"birth_day":26,"birth_month":8,"birth_year":2011,"city_code":"2","comp":null,"country_code":"1","edu":null,"email":"","exp":141,"fansnum":..

日志未全列出,只是作为参考。

完整源码下载

作者:supercrsky 发表于2013-3-14 16:47:53 原文链接
阅读:106 评论:1 查看评论

相关 [java 模拟 新浪] 推荐:

[原]Java模拟新浪和腾迅自动登录并发送微博(2013年3月更新可用)

- - 上善若水 厚德载物
  只是登录无需申请新浪和腾迅的开发者账号,如果需要发送微博功能,需要申请一个新浪和腾迅的开发者账号,并添加一个测试应用.  过程请参考官方帮助文档,申请地址:新浪:http://open.weibo.com    腾迅:http://dev.t.qq.com/. 我们需要的是App Key和App Secre及redirect_URI,源代码中已经包含了我申请的测试key,但由于限制直接用我的key你们的账号是无法登录成功的.

java模拟浏览器包htmlunit,selenium

- - BlogJava-首页技术区
发现一个很不错的模拟浏览器包htmlunit,它可以直接执行访问网站地址,并执行相应的JavaScript脚本;这个功能对于网站爬虫有很大的帮助,一些网站使用了ajax,如果使用简单的http访问只能抓到原始的html源码,但对于页面内执行的ajax却无法获取;使用这个包后,可以将执行ajax后的html源码一并抓取下来.

HttpClient 模拟登录Web版新浪微博

- - zzm
其中密码部分进行了加密,加密的算法在网页的js文件里,网上有人把它改成了Java代码. 下面是SinaSSoEncoder类:. 转:http://www.cnblogs.com/e241138/archive/2012/09/16/2687124.html. 已有 0 人发表留言,猛击->> 这里<<-参与讨论.

HttpClient 模拟登录手机版新浪微博

- - zzm
我们要做的就是获取服务器需要的数据,然后用HttpClient模拟浏览器提交. go标签内的href是我们第二次请求的地址,通过这个地址来获取cookie. 用户密码那个field的name属性是随机变化的,需要先获取它然后提交. 思路:先获取表单的值,然后用POST方法提交. 注意添加RequestHeader信息,否则会被服务器拒绝(403).

根据新浪天气API获取各地天气状况(Java实现)

- - CSDN博客互联网推荐文章
http://blog.csdn.net/cyxlzzs/article/details/7602469  新浪. http://blog.csdn.net/l_ch_g/article/details/8205817    新浪. http://blog.csdn.net/killtl/article/details/7312514  新浪.

新浪微游戏首现独立的HTML5模拟经营类游戏《疯狂老板》

- - HTML5研究小组
微游戏是基于新浪微博平台的好友关系及互动而推出的一系列游戏. 目前微游戏中基本都是Flash游戏为主,而鲜少有真正更适合微博平台的随时随地性的HTML5游戏. 2011年8月,《愤怒的小鸟》开发商Rovio首先开发出该游戏的HTML5版. 随后,社交游戏巨头Zynga也发布了三款适用于苹果产品的HTML5游戏.

Java中的锁(Locks in Java)

- - 并发编程网 - ifeve.com
原文链接 作者:Jakob Jenkov 译者:申章 校对:丁一. 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂. 因为锁(以及其它更高级的线程同步机制)是由synchronized同步块的方式实现的,所以我们还不能完全摆脱synchronized关键字( 译者注:这说的是Java 5之前的情况).

Java PaaS 对决

- 呆瓜 - IBM developerWorks 中国 : 文档库
本文为 Java 开发人员比较了三种主要的 Platform as a Service (PaaS) 产品:Google App Engine for Java、Amazon Elastic Beanstalk 和 CloudBees RUN@Cloud. 它分析了每种服务独特的技术方法、优点以及缺点,而且还讨论了常见的解决方法.

Java浮点数

- d0ngd0ng - 译言-电脑/网络/数码科技
Thomas Wang, 2000年3月. Java浮点数的定义大体上遵守了二进制浮点运算标准(即IEEE 754标准). IEEE 754标准提供了浮点数无穷,负无穷,负零和非数字(Not a number,简称NaN)的定义. 在Java开发方面,这些东西经常被多数程序员混淆. 在本文中,我们将讨论计算这些特殊的浮点数相关的结果.

Qt——转战Java?

- - 博客 - 伯乐在线
编者按:事实上,在跨平台开发方面,Qt仍是最好的工具之一,无可厚非,但Qt目前没有得到任何主流移动操作系统的正式支持. 诺基亚的未来计划,定位非常模糊,这也是令很多第三方开发者感到失望,因此将导致诺基亚屡遭失败的原因. Qt的主要开发者之一Mirko Boehm在博客上强烈讽刺Nokia裁了Qt部门的决定,称其为“绝望之举”,而非“策略变更”.