首页 > 代码库 > HTTPclient模拟登陆交大图书馆

HTTPclient模拟登陆交大图书馆

最近想做一个图书馆的客户端,由于学校没有提供API,只能模拟登陆然后爬取数据了。

首先要解决的就是登陆问题,其实会了之后并不难,我在此竟然耗费了两天……都是一些细节问题。

采用HTTPclient模拟请求,需要注意:

  1.  HttpClient(DefaultHttpClient)代表了一个会话,在同一个会话中,HttpClient对cookie自动进行管理(当然,也可以在程序中进行控制)。
  2. 在同一个会话中,当使用post或是get发起一个新的请求时,一般需要对调用前一个会话的abort()方法,否则会抛出异常。
  3. 有些网站登录成功后会重定向(302, 303)。如果发出的是post请求,需要从响应头中取出location,并再次向网站发送请求,以获取最终数据
  4. 抓取程序不要运行地过于频繁,大部分站点都有抵制刷网站机制。
  5. Android 使用jsoup对得到的html进行解析。 
图书馆的登陆过程如下:
  1. 发送post请求,设置响应的请求头。表单体需要传入四个字段,分别为:用户名(code),密码(pin),(submit.x),(submit.y)
  2. 根据post请求的响应头,获取location,得到重定向的网址。
  3. 发送get请求,获取具体信息。如果第二个请求你又使用了一个新的HTTPclient对象,你就需要获取post请求中的cookie,并将cookie设置到get请求的请求头,否则,系统提示超过有效期。这里如果使用同一个HTTPclient,则不需要设置cookie,因为HTTPclient会帮你管理cookie。
  4. 查阅资料得到一点说明:HttpClient支持自动转向处理,但是象POST和PUT方式这种要求接受后继服务的请求方式,暂时不支持自动转向,因此如果碰到POST方式提交后返回的是301或者302的话需要自己处理。
代码如下:

<span style="font-size:14px;">package com.ali.login;

import java.util.ArrayList;
import java.util.List;

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;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

public class LibraryUtil {

	private static final String baseUrl = "http://innopac.lib.xjtu.edu.cn";
	private static String POST_URL = "http://innopac.lib.xjtu.edu.cn/patroninfo*chx";
	private static String KEY_CODE = "code";
	private static String KEY_PIN = "pin";
	private static String KEY_Submit_x = "submit.x";// 26
	private static String KEY_Submit_y = "submit.y";// 20
	// The HttpClient is used in one session
	private static HttpResponse response;
	private static HttpClient httpclient = null;
	private static String resultHtml = null;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		boolean isConn = login("2111******", "********");
		if (isConn) {

			System.out.println(resultHtml);
		}

	}

	/**
	 * 登陆
	 * 
	 */
	public static boolean login(String userName, String password) {

		HttpGet httpget = null;
		HttpPost httppost = null;
		try {
			httpclient = new DefaultHttpClient(); // 看作是浏览器
			BasicHttpParams httpParams = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParams, 10000);
			HttpConnectionParams.setSoTimeout(httpParams, 10000);
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
			nameValuePairs.add(new BasicNameValuePair(KEY_CODE, userName));
			nameValuePairs.add(new BasicNameValuePair(KEY_PIN, password));
			nameValuePairs.add(new BasicNameValuePair(KEY_Submit_x, Integer
					.toString(50)));
			nameValuePairs.add(new BasicNameValuePair(KEY_Submit_y, Integer
					.toString(25)));
			httppost = new HttpPost(POST_URL);
			httppost.setHeader("Accept",
					"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
			httppost.setHeader("Accept-Language",
					"zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
			httppost.setHeader("Accept-Encoding", "gzip, deflate");
			httppost.setHeader("Referer",
					"http://innopac.lib.xjtu.edu.cn/patroninfo*chx");
			httppost.setHeader("Connection", "keep-alive");
			httppost.setHeader("Content-Type",
					"application/x-www-form-urlencoded");
			httppost.setHeader("Host", "innopac.lib.xjtu.edu.cn");
			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			response = httpclient.execute(httppost);// 发送post请求
			int code = response.getStatusLine().getStatusCode();
			System.out.println(response.getStatusLine());
			// 200说明密码或用户名错误,302则说明正常登陆
			if (code == 200) {
				System.out.println("用户名或密码错误,请重新登陆");
				return false;
			} else if (code == 302) {
				System.out.println("登陆成功,跳转中...");
				String location = response.getHeaders("Location")[0].getValue();
				System.out.println(location);
				httppost.abort();

				httpget = new HttpGet(baseUrl + location);
				response = httpclient.execute(httpget);// 发送get请求
				code = response.getStatusLine().getStatusCode();
				System.out.println(response.getStatusLine());
				if (code == 200) {

					if (response != null) {
						resultHtml = EntityUtils.toString(response.getEntity(),
								HTTP.UTF_8);
					}
					return true;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			httpget.abort();
			httpclient.getConnectionManager().shutdown();
		}

		return false;
	}

}
</span>

参考:http://www.iteye.com/problems/65312

HTTPclient模拟登陆交大图书馆