天天看點

Java實作從學校教務網上爬取資料(一)—— 虛拟登陸第一步:獲得post發送的Name 第二步:發送post請求,驗證傳回的cookie是否正确

<span style="font-family: 'Microsoft YaHei'; font-size: 14px; background-color: rgb(255, 255, 255);">以前看到一些類似課程格子和超級課程表這樣的app,感覺都有種高大上的感覺,畢竟可以通過教務網資料從别人的網頁上爬到資料,那時的我都不懂這個叫做爬蟲程式。這個暑假的課程實踐裡需要從自家學校的教務網上擷取課程表資訊,為Android的開發拟寫背景的爬蟲程式,經過大概一個晚上奮鬥,借鑒多方面的資料,最終實作了這個功能,這裡把我自己實踐過程做一下記錄。</span>
           

第一步:獲得post發送的Name

這裡我需要簡單解釋一下HTTP協定中get和post這兩種表單送出方式的差別。get是從伺服器上擷取資料,post是向伺服器傳送資料。get是把參數資料隊列加到送出表單的ACTION屬性所指的URL中,值和表單内各個字段一一對應,在URL中可以看到。post是通過HTTP post機制,将表單内各個字段與其内容放置在HTML HEADER内一起傳送到ACTION屬性所指的URL位址,使用者看不到這個過程。從安全性來講,post比get更安全,而且post的一次傳送的資料容量大于get。get一般傳送的資料大小一般小于2KB。

一般向密碼登陸這樣的表單送出方式都是post,如果見過get方式一定要通知我。

用Fidder4抓取得到登入需要傳遞的參數如下:(不懂Fidder4的百度一下就好)

Java實作從學校教務網上爬取資料(一)—— 虛拟登陸第一步:獲得post發送的Name 第二步:發送post請求,驗證傳回的cookie是否正确

注意到登陸隻需要傳三個參數userName, password, returnUrl,其中returnUrl為null。 然後我送出NameValuePair的内容就是這樣子

List<NameValuePair> nvps = new ArrayList<NameValuePair>();

        nvps.add(new BasicNameValuePair("userName", userName));   
        nvps.add(new BasicNameValuePair("password", password));   
        nvps.add(new BasicNameValuePair("returnUrl", "null"));  
           

第二步:發送post請求,驗證傳回的cookie是否正确

這一步我就直接貼上代碼了

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;

import org.apache.http.message.BasicNameValuePair;

public class AnalogLogin{

	private static final String URL = "xxxxxxxx";//通路的登陸網址

	/** 
	 * 登陸到教務系統 
	 * @author xuan
	 * @param userName 使用者名
	 * @param password 密碼
	 * @return 成功傳回true 失敗傳回false
	 *  
	 */  
	public boolean login(String userName,String password){  
		HttpClient httpclient = new DefaultHttpClient(new ThreadSafeClientConnManager());


		HttpPost httpost = new HttpPost(URL);  
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();

		nvps.add(new BasicNameValuePair("userName", userName));   
		nvps.add(new BasicNameValuePair("password", password));   
		nvps.add(new BasicNameValuePair("returnUrl", "null"));  
		
		/*設定字元*/  
		httpost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));  
		
		/*嘗試登陸*/  
		HttpResponse response;  
		try {     
			response = httpclient.execute(httpost);  
			String result = "";
			Header[] headers = response.getAllHeaders();
			for(Header header: headers)
				result = result + header + "\n";

			System.out.println(result);
			/*驗證cookie的内容是否包含userName*/
			if(result.contains(userName)){  
				return true;  
			}else{  
				return false;  
			}  
		} catch (ClientProtocolException e) {  
			e.printStackTrace();  
		} catch (IOException e) {  
			e.printStackTrace();  
		}  

		return false;  
	}



	public static void main(String[]args){
		AnalogLogin login = new AnalogLogin();
		System.out.println(login.login("userName", "password"));
	}


}
           

測試一下,居然成功,說明一晚上的努力還是有成果的,但是登陸成功之後又怎麼擷取資訊,而且不是說登陸成功後要管理header裡儲存的cookie進行下一次的通路擷取嗎,但是我上面的代碼并沒有太多關于擷取cookie的内容,算了,睡醒在繼續。