使用HttpClient登入知乎擷取返回頁面資訊

來源:互聯網
上載者:User

標籤:[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); }}


 

代碼的流程是:

  1. 從知乎首頁擷取xsrf資訊。

  2. post請求其中須要cookie資訊,可是我們第一步中沒有得到cookie。請在瀏覽器中自行找到cookie加入進去,上邊的cookie是我找到的。

  3. 提交post請求,得到登入用cookie

  4. 隨便找一個須要登入的子頁面,將得到的cookie寫入到要求標頭中,提交請求,查看是否已經登入成功


 

四 結果驗證

第一張圖顯示得到cookie並登入成功

第二張圖顯示已經進入須要登入的介面


 

總結

    當我們須要登入一個介面擷取資訊的時候,我們要知道登入實際上做了什麼,那就是讀寫cookie,post資料。

    擷取cookie時,須要從回應標頭中擷取。當server發來新的cookie資訊時須要及時寫入。

    當我們能登入一個網站的時候,怎樣對其內容進行操作。這裡推薦jsoup。良心庫,仿jquery操作模式。

摘自開源中國社區:http://my.oschina.net/jiangmitiao/blog/483092

 

使用HttpClient登入知乎擷取返回頁面資訊

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.