分享

用Java和Perl登录新浪微博

 hh3755 2012-05-11

用Java和Perl登录新浪微博

===============2011/06/28更新==========================
更新了HttpClient 4.x 模拟登录新浪微博的示例代码,经测试能正常登录,HttpClient 3.x和Perl版本的代码没有更新,有需要的同学自己参考HttpClient 4.x改写一下应该就可以了。希望大家也多一点探索精神,我没有精力经常来更新这个代码。

===============2011/05/24更新==========================
添加了用HttpClient 4.x 模拟登录新浪微博的示例代码

===============2011/05/22更新==========================
今天测试了日志中的Java代码,发现至少在目前是好用的,但是不保证以后会一直好用。感谢viLuo反馈的这个链接 新浪微博如何实现 SSO(t.sina.com.cn/weibo.com) 的分析,里面的内容写得很好很详细,遇到问题的同学可以去学习研究一下。

===============2011/03/29更新==========================
在最开始写这篇日志的时候,文中描述的两种方法的代码都经过了测试,能够成功登录。但是新浪的登录参数可能不停地在变化,所以如果你把日志中的代码直接复制回去,不能运行是很正常的情况。这里是文初写的模拟登录的一篇博客,里面涉及到了更多细节,有兴趣的朋友可以去看看。感谢zhaojiguang在评论中反馈此链接。
====================================================

现在新浪微博已经开放了API,为开发提供了很大的方便。但是仍然有一些事情是API所无能为力的,这时候就需要用到其他办法了。

1. 获得登录参数

一般的网站登录窗口都是一个简单的表单,随便搞一段代码就可以很轻易地登录上去,但是新浪的登录窗口却是由javascript控制的,稍微麻烦一些。对于简单的表单,可以通过查看html源代码获得登录参数;但是对于新浪这种,需要更深入一点的分析才行。

那么,要怎么办呢?答案是:万能的抓包工具。下面的截图分别展示了用Wireshark和Live HTTP headers(Firefox的一款插件)来获取登录参数的情况。

(1) Wireshark

抓包后找到带有 POST /sso/login.php?client=ssologin.js(v1.x.xx) HTTP/1.1的一行

然后右键,选择Follow TCP Stream,就会出来想要的结果,如图。注意看空行下面的红色文字部分。

(2) Live HTTP headers

实际上这个不算抓包工具,但是用起来更简单。注意看图中蓝底白字部分。

2. Java版

当获得了这些登录所需要传给服务器的参数以后,接下来的工作就比较简单了。
Java版主要用到了HttpClient,代码原始来源:http:///?p=27 ,我稍作了修改。
新浪微博中有一些页面登录前和登录后看到的内容不一样,比如 http://t.sina.com.cn/pub/tags ,程序中访问这个页面来检验是否登录成功。

(1) HttpClient 3.x版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.io.IOException;
 
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
 
public class SinaLogin
{
	public static String login(String email, String passwd) throws HttpException, IOException
	{
		PostMethod post = new PostMethod("http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.3.11)");
		post.addParameter("service", "miniblog");
		post.addParameter("client", "ssologin.js(v1.3.11)");
		post.addParameter("entry", "miniblog");
		post.addParameter("encoding", "utf-8");
		post.addParameter("gateway", "1");
		post.addParameter("savestate", "7");
		post.addParameter("from", "");
		post.addParameter("useticket", "0");
		post.addParameter("username", email);
		post.addParameter("password", passwd);
		post.addParameter("url", "http://t.sina.com.cn/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack");
		post.addParameter("returntype", "META");
		HttpClient client = new HttpClient();
		client.executeMethod(post);
		GetMethod get = new GetMethod("http://t.sina.com.cn/pub/tags");
		client.executeMethod(get);
		System.out.println(new String(get.getResponseBody()));
		return new String(get.getResponseBody());
	}
 
	public static void main(String[] args) throws HttpException, IOException
	{
		login("email","password");
	}
}

(2) HttpClient 4.x版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package com.icycandy;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
 
public class SinaLogin {
 
	private final static HttpClient client = new DefaultHttpClient();
 
	/**
	 * 抓取网页
	 * 
	 * @param url
	 * @throws IOException
	 */
	static String get(String url) throws IOException {
		HttpGet get = new HttpGet(url);
		HttpResponse response = client.execute(get);
		System.out.println(response.getStatusLine());
		HttpEntity entity = response.getEntity();
 
		String result = dump(entity);
		get.abort();
 
		return result;
	}
 
	/**
	 * 执行登录过程
	 * 
	 * @param user
	 * @param pwd
	 * @param debug
	 * @throws IOException
	 */
	static void login(String user, String pwd) throws IOException {
		HttpPost post = new HttpPost(
				"http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.3.14)");
		post.setHeader("User-Agent",
				"Mozilla/5.0 (X11; Linux i686; rv:5.0) Gecko/20100101 Firefox/5.0");
		post.setHeader("Referer", "http://weibo.com/");
		post.setHeader("Content-Type", "application/x-www-form-urlencoded");
 
		// 登录表单的信息
		List<NameValuePair> qparams = new ArrayList<NameValuePair>();
		qparams.add(new BasicNameValuePair("entry", "miniblog"));
		qparams.add(new BasicNameValuePair("gateway", "1"));
		qparams.add(new BasicNameValuePair("from", ""));
		qparams.add(new BasicNameValuePair("savestate", "0"));
		qparams.add(new BasicNameValuePair("useticket", "1"));
		qparams.add(new BasicNameValuePair("ssosimplelogin", "1"));
		qparams.add(new BasicNameValuePair("service", "miniblog"));
		// servertime=1309164392
		// nonce=PJZCHM
		// qparams.add(new BasicNameValuePair("pwencode", "wsse"));
		qparams.add(new BasicNameValuePair("encoding", "utf-8"));
		qparams.add(new BasicNameValuePair(
				"url",
				"http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack"));
		qparams.add(new BasicNameValuePair("returntype", "META"));
 
		qparams.add(new BasicNameValuePair("username", user));
		qparams.add(new BasicNameValuePair("password", pwd));
 
		UrlEncodedFormEntity params = new UrlEncodedFormEntity(qparams, "UTF-8");
		post.setEntity(params);
 
		// Execute the request
		HttpResponse response = client.execute(post);
		post.abort();
		// 新浪微博登录没有301,302之类的跳转;而是返回200,然后用javascript实现的跳转
		// int statusCode = response.getStatusLine().getStatusCode();
		// if ((statusCode == HttpStatus.SC_MOVED_PERMANENTLY)
		// || (statusCode == HttpStatus.SC_MOVED_TEMPORARILY)
		// || (statusCode == HttpStatus.SC_SEE_OTHER)
		// || (statusCode == HttpStatus.SC_TEMPORARY_REDIRECT)) {
		// // 此处重定向处理 此处还未验证
		// String newUri = response.getLastHeader("Location").getValue();
		// get(newUri);
		// }
 
		// Get hold of the response entity
		HttpEntity entity = response.getEntity();
		// 取出跳转的url
		// location.replace("http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&ticket=ST-MTkxODMxOTI0Nw==-1309224549-xd-263902F174B27BAB9699691BA866EFF2&retcode=0");
		String location = getRedirectLocation(dump(entity));
		get(location);
	}
 
	private static String getRedirectLocation(String content) {
		String regex = "location\\.replace\\(\'(.*?)\'\\)";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(content);
 
		String location = null;
		if (matcher.find()) {
			location = matcher.group(1);
		}
 
		return location;
	}
 
	/**
	 * 打印页面
	 * 
	 * @param entity
	 * @throws IOException
	 */
	private static String dump(HttpEntity entity) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(
				entity.getContent(), "utf8"));
 
		//return EntityUtils.toString(entity);
		return IOUtils.toString(br);
	}
 
	public static void main(String[] args) throws IOException {
		login("username", "password");
		String result = get("http://t.sina.com.cn/pub/tags");
		System.out.println(result);
	}
}

3. Perl版

Perl版代码是鑫哥给我的,未知原始来源,同样也稍作了修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
use LWP::UserAgent;
use HTTP::Cookies;
use HTTP::Headers;
 
my $ua = new LWP::UserAgent(keep_alive => 1);
$ua->timeout(5);
$ua->agent('Mozilla/4.0');
$ua->cookie_jar(HTTP::Cookies->new(file=>'getsina.cookies',autosave=>1));
 
my $res = $ua->post('http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.3.11)',
    [
        service => 'miniblog',
        client => 'ssologin.js(v1.3.11)',
        entry => 'miniblog',
        encoding => 'utf-8',
        gateway => '1',
        savestate => '7',
        username => 'username',
        password => 'password',
        from => '',
        useticket => '0',
        url => 'http://t.sina.com.cn/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack',
        returntype => 'META',
    ],
);
if (!$res->is_success) {
    print STDERR $res->status_line, "\n";
}
 
my $req = HTTP::Request->new(GET => 'http://t.sina.com.cn/pub/tags');
$req->content_type('application/x-www-form-urlencoded');
$res = $ua->request($req);
print $res->as_string;
 
exit(0);

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多