今天接到任务要去爬sina微博内容。爬虫爬得有cookie,所以要用httpclient写个登录接口。
用到的分析工具:Live HTTP Headers(火狐的一个插件)
参考资源:
http://blog.csdn.net/yodlove/article/details/5938022;
http://blog.csdn.net/jk_yu520/article/details/6622661;
用到单点登陆真是蛋疼。而且还跳来跳去,不得不跟着一步一步来。
修改:
昨天没看细节,发现cookie有问题。导致登陆是成功的,但是使用cookie的时候出问题,只好继续埋头BAIDU,发现一个虽然目前无法登陆但还是可以借鉴的源代码.
http://www.lupaworld.com/code.php?mod=list&itemid=26&path=weibobackup_1.1/src/cn/jayslong/weibo&file=Login.java
主要代码修改:增加了
DefaultHttpParams.getDefaultParams().setBooleanParameter(
HttpMethodParams.SINGLE_COOKIE_HEADER, true);
废除了mergeCookie( )方法。
代码
package com.cp.http;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import com.cp.http.Sh1;
/**
*
*
* @author chengping
*
*/
public class TestClient {
static final String LOGON_SITE = "login.sina.com.cn";
static final int LOGON_PORT = 80;
static final String preLoginUrl = "http://login.sina.com.cn/sso/prelogin.php?entry=miniblog&callback=sinaSSOController.preloginCallBack&client=ssologin.js(v1.3.14)&_=1313560817097";
static final String loginurl = "/sso/login.php?client=ssologin.js(v1.3.14)";
static final String defaultUser = "xxxxx";
static final String defaultPasswordOld = "xxxxxx";
static final String homePageUrl = "http://weibo.com/";
public static void main(String[] args) throws Exception {
HttpClient client = new HttpClient();
client.getParams().setParameter(
HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF8");
//原先采用自己合并COOKIE,但是出现问题,用此方法OK
DefaultHttpParams.getDefaultParams().setBooleanParameter(
HttpMethodParams.SINGLE_COOKIE_HEADER, true);
client.getParams().setParameter(HttpMethodParams.USER_AGENT,"Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.1.2) Gecko/20090803 Fedora/3.5.2-2.fc11 Firefox/3.5.2");
client.getHostConfiguration().setHost(LOGON_SITE, LOGON_PORT);
String ajaxLoginUrl=Login(client, preLogin(client));
String uniqueid=ajaxLogin(client,ajaxLoginUrl);
getHomePage(client,homePageUrl+uniqueid);
}
/**
* 获取用户的主页
* @param client
* @param homePageUrl
* @throws IOException
*/
public static void getHomePage(HttpClient client,String homePageUrl) throws IOException {
// TODO Auto-generated method stub
GetMethod get = new GetMethod(homePageUrl);
try {
client.executeMethod(get);
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String response = get.getResponseBodyAsString();
System.out.println(response);
}
/**
* preLogin获得servertime和一个定长随机的字符串nonce
* 用户账号采用默认账号
* @param client
* @return
* @throws Exception
*/
public static Map<String, String> preLogin(HttpClient client)
throws Exception {
return preLogin(client, defaultUser);
}
/**
* preLogin获得servertime和一个定长随机的字符串nonce
* 用户账号采用输入账号
* @param client
* @param userEmail
* @return
* @throws Exception
*/
public static Map<String, String> preLogin(HttpClient client,
String userEmail) throws Exception {
GetMethod get = new GetMethod(preLoginUrl + "&usr=" + userEmail);
try {
client.executeMethod(get);
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String response = get.getResponseBodyAsString();
// System.out.println(response);
// System.out.println(get.getFollowRedirects());
// System.out.println(get.getPath());
// for (Header h : get.getResponseHeaders()) {
// System.out.print(h);
// }
get.releaseConnection();
printCookie(client);
mergeCookie(client);
printCookie(client);
System.out.println("-------------preLogin结束--------------");
return responseBodyToMap(response);
}
/**
* prelogin后拿到2个参数用来生成加密的密码,正式登陆。
* 账户,密码是系统默认
* @param client
* @param serverTimeAndNonce
* @return
* @throws IOException
* @throws HttpException
*/
public static String Login(HttpClient client,
Map<String, String> serverTimeAndNonce) throws IOException,
HttpException {
return Login(client, serverTimeAndNonce, defaultUser,
defaultPasswordOld);
}
/**
* prelogin后拿到2个参数用来生成加密的密码,正式登陆。
* 账户,密码采用输入参数
* @param client
* @param serverTimeAndNonce
* @param userEmail
* @param passwordOld
* @return
* @throws IOException
* @throws HttpException
*/
public static String Login(HttpClient client,
Map<String, String> serverTimeAndNonce, String userEmail,
String passwordOld) throws IOException, HttpException {
PostMethod post = new PostMethod(loginurl);
// 初始化POST方法的content
NameValuePair entry = new NameValuePair("entry", "miniblog");
NameValuePair gateway = new NameValuePair("gateway", "1");
NameValuePair from = new NameValuePair("from", "");
NameValuePair savestate = new NameValuePair("savestate", "7");
NameValuePair useticket = new NameValuePair("useticket", "1");
NameValuePair ssosimplelogin = new NameValuePair("ssosimplelogin", "1");
NameValuePair username = new NameValuePair("username", userEmail);
NameValuePair service = new NameValuePair("service", "miniblog");
NameValuePair servertime = new NameValuePair("servertime",
serverTimeAndNonce.get("servertime"));
NameValuePair nonce = new NameValuePair("nonce", serverTimeAndNonce
.get("nonce"));
NameValuePair pwencode = new NameValuePair("pwencode", "wsse");
NameValuePair password = new NameValuePair("password", encryption(
passwordOld, serverTimeAndNonce));
NameValuePair encoding = new NameValuePair("encoding", "utf-8");
NameValuePair url = new NameValuePair(
"url",
"http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack");
NameValuePair returntype = new NameValuePair("returntype", "META");
post.addParameters(new NameValuePair[] { entry, gateway, from,
savestate, useticket, ssosimplelogin, username, service,
servertime, nonce, pwencode, password, encoding, url,
returntype });
int status = client.executeMethod(post);
String responseBodyAsString = post.getResponseBodyAsString();
/* System.out.println(status);
System.out.println(response);
System.out.println(post.getFollowRedirects());
System.out.println(post.getPath());
for (Header h : post.getResponseHeaders()) {
System.out.print(h);
}*/
//printCookie(client);
//mergeCookie(client);
//printCookie(client);
System.out.println("-------------Login结束--------------");
post.releaseConnection();
return getAjaxUrl(responseBodyAsString);
}
/**
* 加密密码
* @param passwordOld
* @param serverTimeAndNonce
* @return
*/
private static String encryption(String passwordOld,
Map<String, String> serverTimeAndNonce) {
// TODO Auto-generated method stub
String tempPassword = Sh1.testDigest(Sh1.testDigest(passwordOld));
tempPassword += serverTimeAndNonce.get("servertime");
tempPassword += serverTimeAndNonce.get("nonce");
return Sh1.testDigest(tempPassword);
}
/**
* login后密码验证成功后跳入ajaxLogin,获得唯一标示码。
* @param client
* @param ajaxUrl
* @return
* @throws IOException
* @throws HttpException
*/
public static String ajaxLogin(HttpClient client, String ajaxUrl)
throws IOException, HttpException {
GetMethod getByAjax = new GetMethod(ajaxUrl);
client.executeMethod(getByAjax);
System.out.println(getByAjax.getURI());
//printCookie(client);
//mergeCookie(client);
//printCookie(client);
System.out.println("-------------ajaxLogin结束--------------");
//System.out.println(getByAjax.getResponseBodyAsString());
String responseBodyAsString=getByAjax.getResponseBodyAsString();
getByAjax.releaseConnection();
return getUniqueid(responseBodyAsString);
}
/**
* 从AjaxLogin返回的信息中获得唯一标识码
* @param responseBodyAsString
* @return
*/
private static String getUniqueid(String responseBodyAsString) {
// TODO Auto-generated method stub
int start=responseBodyAsString.indexOf("uniqueid")+11;
int end=responseBodyAsString.indexOf("userid")-3;
//System.out.println(responseBodyAsString);
//System.out.println(responseBodyAsString.indexOf("uniqueid"));
//System.out.println(responseBodyAsString.indexOf("userid"));
//System.out.println(responseBodyAsString.substring(start, end));
return responseBodyAsString.substring(start, end);
}
/**
* 将preLogin返回信息提取需要的二个参数转为MAP形式
* @param response
* @return
*/
private static Map<String, String> responseBodyToMap(String response) {
Map<String, String> result = new HashMap<String, String>();
int start = response.indexOf("{") + 1;
int end = response.indexOf("}");
String body = response.substring(start, end);
String[] strings = body.split(",");
for (int i = 1; i < 3; i++) {
String[] elements = strings[i].split(":");
result.put(elements[0].replace("\"", ""), elements[1].replace("\"",
""));
}
return result;
}
/**
* 构建阶段时输出cookie值
* @param client
*/
private static void printCookie(HttpClient client){
Cookie[] cookies = client.getState().getCookies();
System.out.println("目前有"+cookies.length+"条cookie");
int index =0;
for(Cookie cookie:cookies){
System.out.println("cookie["+index+"]:{"+cookie.getName()+","+cookie.getValue()+"}");
index++;
}
}
/**
* 合并cookie信息放到一个cookie中
* 此方法会出错,无效。
* @param client
*/
private static void mergeCookie(HttpClient client){
Cookie[] cookies = client.getState().getCookies();
if (cookies != null && cookies.length > 0) {
String cook = cookies[0].getValue();
for (int i = 1; i < cookies.length; i++) {
cook += "; " + cookies[i].getName() + "="
+ cookies[i].getValue();
}
cookies[0].setValue(cook);
HttpState state = new HttpState();
state.addCookie(cookies[0]);
client.setState(state);
}
}
/**
* 从login方法后返回的信息中获得下一步AjaxLogin的URL
* @param responseBodyAsString
* @return
*/
private static String getAjaxUrl(String responseBodyAsString){
int start=responseBodyAsString.indexOf("replace")+9;
int end=responseBodyAsString.indexOf("</script>")-6;
//System.out.println(responsBodyAsString);
//System.out.println(responsBodyAsString.indexOf("</script>"));
//System.out.println(responsBodyAsString.substring(start, end));
return responseBodyAsString.substring(start, end);
}
}
下面是密码加密的辅助类,sina采用的加密是密码二次SHA1加密后得到的字符串拼接上preLogin得到的二个参数servertime(服务器时间),nonce(随机生成的字符串)。再用SHA加密。(我靠,sina他不累啊。)
package com.cp.http;
public class Sh1 {
public static String testDigest(String info)
{
try {
//java.security.MessageDigest alg=java.security.MessageDigest.getInstance("MD5");
java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1");
alga.update(info.getBytes());
byte[] digesta=alga.digest();
// System.out.println("本信息摘要是:"+byte2hex(digesta));
//通过某中方式传给其他人你的信息(myinfo)和摘要(digesta) 对方可以判断是否更改或传输正常
return byte2hex(digesta);
}
catch (java.security.NoSuchAlgorithmException ex) {
System.out.println("非法摘要算法");
return "erro";
}
}
public static String byte2hex(byte[] b) //二行制转字符串
{
String hs="";
String stmp="";
for (int n=0;n<b.length;n++)
{
stmp=(Integer.toHexString(b[n] & 0XFF));
if (stmp.length()==1) hs=hs+"0"+stmp;
else hs=hs+stmp;
// if (n<b.length-1) hs=hs+":";
}
return hs;
}
}
分享到:
相关推荐
首先,我们来看`Sina.java`,这是用于模拟登录新浪微博的代码。在新浪微博的模拟登录过程中,主要涉及到以下几个关键步骤: 1. **创建HttpClient实例**:HttpClient是整个模拟登录的核心,通过`HttpClientBuilder`...
- **OAuth**:用于安全地获取新浪微博的访问权限,允许程序代表用户进行操作。 - **API集成**:理解新浪的开放API,包括发送微博的接口规范。 - **JSON解析**:API通常返回或接收JSON格式的数据,需要能够解析和构造...
这个爬虫可能利用HttpClient发送GET或POST请求,获取新浪微博的话题页面HTML源码。 3. **HTML解析**:为了提取话题数据,项目可能使用了HTML解析库,如HtmlAgilityPack,它可以解析HTML文档,方便地定位并提取所需...
在这个场景中,我们关注的是如何使用HTTPClient 4库来模拟登录新浪微博。首先,我们需要理解HTTPClient库的基本概念。 HTTPClient是一个强大的Java库,用于处理HTTP请求和响应。它提供了丰富的功能,包括支持HTTPS...
在这个项目中,我们重点讨论基于Java实现的新浪微博API客户端,它提供了访问和交互微博数据的能力。 首先,Java是面向对象的编程语言,它的强大在于其丰富的类库和强大的社区支持。在开发微博应用时,可以使用如...
在ASP.NET开发中,集成第三方社交媒体登录功能,如腾讯微博和新浪微博,是提高用户体验和方便用户注册的重要方式。本文将详细讲解如何在ASP.NET项目中实现腾讯微博和新浪微博的账号授权登录。 首先,我们需要理解...
在这个项目中,Java客户端为用户提供了一种在本地操作系统上访问和操作新浪微博的功能。 4. **开源软件**:开源意味着源代码对公众开放,任何人都可以查看、使用、修改和分发代码。该项目开源,意味着开发者可以...
【安卓新浪微博】是一款针对Android平台开发的应用,它允许用户实现基本的微博登录功能,为用户提供了一个简洁、易于学习的社交互动平台。在这个应用中,开发者主要利用了Android SDK中的相关组件和技术来构建用户...
在本例中,我们将讨论如何使用C#来实现一个基于OAuth2.0的新浪微博客户端。 **C#** 是一种面向对象的编程语言,由微软开发,主要用于.NET Framework。在C#中,我们可以利用HTTP请求库如HttpClient或Flurl来发送网络...
以上是开发“Android开发我的新浪微博客户端”所需的关键知识点,通过这个项目,开发者可以深入理解Android开发的全貌,提升自己的技能。在实际开发中,还需要不断学习和适应Android的新特性,以及遵循最佳实践,以...
在Android平台上实现新浪微博的功能,包括OAuth认证登录以及获取微博信息,是移动应用开发中的常见需求。这个实例项目,"weibo4android",提供了一个完整的解决方案,帮助开发者深入理解和运用相关技术。 首先,...
* 测试新浪微博API * @author syn * @date 2010/12/22 */ public class TestActivity extends Activity { private static final String BASE_URL = "http://api.t.sina.com.cn/"; //API接口 private static final ...
这里提到的是新浪微博API,它是由新浪提供的一个接口,让开发者能够通过编程方式访问和操作新浪微博的数据,例如发布微博、获取用户信息、评论、转发等。 Java是一种广泛使用的面向对象的编程语言,具有跨平台的...
新浪微博和腾讯微博都提供了开发者API,以供第三方应用访问其数据。 对于新浪微博,你需要注册成为开发者并创建一个应用,以获取API密钥(包括AppKey和AppSecret)。然后,你可以使用OAuth2.0授权协议获取用户的...
本主题聚焦于使用Java实现对新浪微博的模拟登录,这对于数据分析、信息抓取或自动化测试等应用场景具有重要意义。 【描述】:“新浪微博模拟登陆源代码,java实现,微博数据抓取” 这段描述揭示了几个关键点: 1....
在这种情况下,"【开放平台】_新浪微博JAVA代码样例及详细说明" 提供了使用Java编程语言与新浪微博开放平台进行交互的示例代码和指南。新浪微博是中国极具影响力的社交媒体平台,它提供了丰富的API供开发者构建各种...
在Java开发中,集成第三方登录服务,如新浪微博,是一个常见的需求。这有助于为用户提供便捷的登录体验,同时也能增加应用程序的用户基础。本教程将基于提供的"java实现新浪微博第三方登录"的Demo,深入讲解如何使用...
1. **OAuth认证**:新浪微博API采用了OAuth 2.0进行授权,开发者需要注册应用获取App Key和App Secret,然后通过用户授权获取Access Token,以此来安全地访问用户的微博数据。 2. **HTTP请求库**:Java中常用如...
在本文中,我们将深入探讨如何使用OAuth2协议模拟登录新浪微博,并了解相关技术细节。OAuth2是一种授权框架,允许第三方应用代表用户与服务提供商进行交互,例如发布微博。在这个例子中,我们将使用Java的Apache ...
微博批量抓取器是一款使用C#编程语言开发的应用程序,专为高效地从新浪微博平台上抓取大量数据而设计。在当前的社交媒体时代,微博作为中国极具影响力的社交网络平台,其用户活跃度高,信息传播速度快。因此,对于...