標籤:[1] .exe status ble mem http 退出 頁面 html
引言
HttpClient是java語言下一個支援http協議的client編程工具包,它實現了HTTP協議的全部方法,可是不支援JS渲染。我們在做一些小玩意時,有可能須要登入某些網站擷取資訊,那麼HttpClient就是你的好幫手,廢話不多說,進入實戰。
一 登入的實際意義
在HTTP橫行的今天,我們每天都要登入一些網站,那麼登入的意義是什麼呢?首先要對cookie要有一定瞭解。cookie是存放在本地的一些小檔案,它由server發送命令。瀏覽器在本地讀寫。
當訪問某些網站的時候,瀏覽器會檢查是否有所瀏覽網站的cookie資訊,假設有則在發送訪問請求的時候攜帶上這些內容,server能夠讀取到瀏覽器發送請求中的cookie資訊。在回應請求時能夠再寫cookie資訊。cookie資訊包含索引值。內容。到期時間。所屬網站。
講到這裡cookie幾乎相同講完了。那麼登入究竟是怎麼回事?登入就是server向你的瀏覽器寫cookie,假設不過在你的電腦上寫cookie,那麼別實用心的人偽造一個cookie也有機會登入網站。所以server會在記憶體中保留一份同樣的資訊。這個過程叫做會話。假設你在網站點擊退出button,server會把記憶體中的cookie清除掉。同一時候清除瀏覽器中有關登入的cookie。
知道了這些,我們就能夠上手了。
二 找到登入關鍵cookie
這裡我們能夠用wireshark來抓包分析一下。
開啟知乎首頁,開啟wireshark。開始監聽port。輸入username和password,點擊登入。查看wireshark抓到的包。
例如以下:
第一張圖是本地post提交資料。
第二張圖是提交的資訊,包含_xsrf,password。remember_me,email。注意,提交的資訊中包含cookie,_xsrf能夠從知乎首頁中擷取。
第三張圖是server返回的資訊,注意它的狀態是200,說明是成功的。
第四章圖是server返回的資料,注意它有三條cookie設定。以及帶有一個登入成功與否的資訊。
通過上邊的步驟我們能知道什麼呢?首先,發送登入請求的時候帶有的cookie。以及post資料的格式。其次我們能拿到登入用cookie資訊(第四張圖)。
三 使用HttpClient構造登入資訊
HttpClient是如何類比瀏覽器的呢?首先須要建立一個HttpClient,這個HttpClient是用來類比一個瀏覽器。
其次構造一個post請求,加入post資料資訊以及cookie。具體代碼例如以下:
import org.apache.http.*;import org.apache.http.client.CookieStore;import org.apache.http.client.config.CookieSpecs;import org.apache.http.client.config.RequestConfig;import org.apache.http.client.entity.UrlEncodedFormEntity;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.methods.HttpPost;import org.apache.http.client.protocol.HttpClientContext;import org.apache.http.config.Lookup;import org.apache.http.config.RegistryBuilder;import org.apache.http.cookie.CookieSpecProvider;import org.apache.http.impl.client.BasicCookieStore;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.impl.cookie.BasicClientCookie;import org.apache.http.impl.cookie.DefaultCookieSpecProvider;import org.apache.http.message.BasicNameValuePair;import org.apache.http.util.EntityUtils;import java.io.IOException;import java.util.HashMap;import java.util.LinkedList;import java.util.List;import java.util.Map; /** * Created by gavin on 15-7-23. */public class HttpClientTest { public static void main(String[] args) { //建立一個HttpClient RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT).build(); CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build(); try { //建立一個get請求用來接收_xsrf資訊 HttpGet get = new HttpGet("http://www.zhihu.com/"); //擷取_xsrf CloseableHttpResponse response = httpClient.execute(get,context); setCookie(response); String responseHtml = EntityUtils.toString(response.getEntity()); String xsrfValue = responseHtml.split("<input type=\"hidden\" name=\"_xsrf\" value=\"")[1].split("\"/>")[0]; System.out.println("xsrfValue:" + xsrfValue); response.close(); //構造post資料 List<NameValuePair> valuePairs = new LinkedList<NameValuePair>(); valuePairs.add(new BasicNameValuePair("_xsrf", xsrfValue)); valuePairs.add(new BasicNameValuePair("email", "[email protected]")); valuePairs.add(new BasicNameValuePair("password", "xxxxx")); valuePairs.add(new BasicNameValuePair("remember_me", "true")); UrlEncodedFormEntity entity = new UrlEncodedFormEntity(valuePairs, Consts.UTF_8); //建立一個post請求 HttpPost post = new HttpPost("http://www.zhihu.com/login/email"); post.setHeader("Cookie", " cap_id=\"YjA5MjE0YzYyNGQ2NDY5NWJhMmFhN2YyY2EwODIwZjQ=|1437610072|e7cc307c0d2fe2ee84fd3ceb7f83d298156e37e0\"; "); //注入post資料 post.setEntity(entity); HttpResponse httpResponse = httpClient.execute(post); //列印登入是否成功資訊 printResponse(httpResponse); //構造一個get請求,用來測試登入cookie是否拿到 HttpGet g = new HttpGet("http://www.zhihu.com/question/following"); //得到post請求返回的cookie資訊 String c = setCookie(httpResponse); //將cookie注入到get要求標頭其中 g.setHeader("Cookie",c); CloseableHttpResponse r = httpClient.execute(g); String content = EntityUtils.toString(r.getEntity()); System.out.println(content); r.close(); } catch (IOException e) { e.printStackTrace(); } finally { try { httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void printResponse(HttpResponse httpResponse) throws ParseException, IOException { // 擷取響應訊息實體 HttpEntity entity = httpResponse.getEntity(); // 響應狀態 System.out.println("status:" + httpResponse.getStatusLine()); System.out.println("headers:"); HeaderIterator iterator = httpResponse.headerIterator(); while (iterator.hasNext()) { System.out.println("\t" + iterator.next()); } // 推斷響應實體是否為空白 if (entity != null) { String responseString = EntityUtils.toString(entity); System.out.println("response length:" + responseString.length()); System.out.println("response content:" + responseString.replace("\r\n", "")); } } public static Map<String,String> cookieMap = new HashMap<String, String>(64); //從響應資訊中擷取cookie public static String setCookie(HttpResponse httpResponse) { System.out.println("----setCookieStore"); Header headers[] = httpResponse.getHeaders("Set-Cookie"); if (headers == null || headers.length==0) { System.out.println("----there are no cookies"); return null; } String cookie = ""; for (int i = 0; i < headers.length; i++) { cookie += headers[i].getValue(); if(i != headers.length-1) { cookie += ";"; } } String cookies[] = cookie.split(";"); for (String c : cookies) { c = c.trim(); if(cookieMap.containsKey(c.split("=")[0])) { cookieMap.remove(c.split("=")[0]); } cookieMap.put(c.split("=")[0], c.split("=").length == 1 ? "":(c.split("=").length ==2?
c.split("=")[1]:c.split("=",2)[1])); } System.out.println("----setCookieStore success"); String cookiesTmp = ""; for (String key :cookieMap.keySet()) { cookiesTmp +=key+"="+cookieMap.get(key)+";"; } return cookiesTmp.substring(0,cookiesTmp.length()-2); }}
代碼的流程是:
從知乎首頁擷取xsrf資訊。
post請求其中須要cookie資訊,可是我們第一步中沒有得到cookie。請在瀏覽器中自行找到cookie加入進去,上邊的cookie是我找到的。
提交post請求,得到登入用cookie
隨便找一個須要登入的子頁面,將得到的cookie寫入到要求標頭中,提交請求,查看是否已經登入成功
四 結果驗證
第一張圖顯示得到cookie並登入成功
第二張圖顯示已經進入須要登入的介面
總結
當我們須要登入一個介面擷取資訊的時候,我們要知道登入實際上做了什麼,那就是讀寫cookie,post資料。
擷取cookie時,須要從回應標頭中擷取。當server發來新的cookie資訊時須要及時寫入。
當我們能登入一個網站的時候,怎樣對其內容進行操作。這裡推薦jsoup。良心庫,仿jquery操作模式。
摘自開源中國社區:http://my.oschina.net/jiangmitiao/blog/483092
使用HttpClient登入知乎擷取返回頁面資訊