摘要:打開知乎首頁,打開,開始監(jiān)聽端口,輸入用戶名和密碼,點擊登錄,查看抓到的包。第二張圖是提交的信息,包括,,,,注意,提交的信息中包括,可以從知乎首頁中獲取。
引言
HttpClient是java語言下一個支持http協(xié)議的客戶端編程工具包,它實現(xiàn)了HTTP協(xié)議的所有方法,但是不支持JS渲染。我們在做一些小玩意時,有可能需要登錄某些網(wǎng)站獲取信息,那么HttpClient就是你的好幫手,廢話不多說,進入實戰(zhàn)。
一 登錄的實際意義在HTTP橫行的今天,我們每天都要登錄一些網(wǎng)站,那么登錄的意義是什么呢?首先要對cookie要有一定了解。cookie是存放在本地的一些小文件,它由服務器發(fā)送命令,瀏覽器在本地讀寫。當訪問某些網(wǎng)站的時候,瀏覽器會檢查是否有所瀏覽網(wǎng)站的cookie信息,如果有則在發(fā)送訪問請求的時候攜帶上這些內(nèi)容,服務器可以讀取到瀏覽器發(fā)送請求中的cookie信息,在回應請求時可以再寫cookie信息。cookie信息包括鍵值,內(nèi)容,過期時間,所屬網(wǎng)站。
說到這里cookie差不多講完了,那么登錄到底是怎么回事?登錄就是服務器向你的瀏覽器寫cookie,如果僅僅是在你的計算機上寫cookie,那么別有用心的人偽造一個cookie也有機會登錄網(wǎng)站,所以服務器會在內(nèi)存中保留一份相同的信息,這個過程叫做session會話。如果你在網(wǎng)站點擊退出按鈕,服務器會把內(nèi)存中的cookie清除掉,同時清除瀏覽器中有關(guān)登錄的cookie。知道了這些,我們就可以上手了。
二 找到登錄關(guān)鍵cookie這里我們可以用wireshark來抓包分析一下。打開知乎首頁,打開wireshark,開始監(jiān)聽端口,輸入用戶名和密碼,點擊登錄,查看wireshark抓到的包。截圖如下:
第一張圖是瀏覽器post提交數(shù)據(jù)。
第二張圖是提交的信息,包括_xsrf,password,remember_me,email,注意,提交的信息中包括cookie,_xsrf可以從知乎首頁中獲取。
第三張圖是服務器返回的信息,注意它的狀態(tài)是200,說明是成功的。
第四章圖是服務器返回的數(shù)據(jù),注意它有三條cookie設置,以及帶有一個登錄成功與否的信息。
通過上邊的步驟我們能知道什么呢?首先,發(fā)送登錄請求的時候帶有的cookie,以及post數(shù)據(jù)的格式,其次我們能拿到登錄用cookie信息(第四張圖)。
三 使用HttpClient構(gòu)造登錄信息HttpClient是怎樣模擬瀏覽器的呢?首先需要建立一個HttpClient,這個HttpClient是用來模擬一個瀏覽器。其次構(gòu)造一個post請求,添加post數(shù)據(jù)信息以及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) { //創(chuàng)建一個HttpClient RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT).build(); CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build(); try { //創(chuàng)建一個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("")[0]; System.out.println("xsrfValue:" + xsrfValue); response.close(); //構(gòu)造post數(shù)據(jù) ListvaluePairs = new LinkedList (); valuePairs.add(new BasicNameValuePair("_xsrf", xsrfValue)); valuePairs.add(new BasicNameValuePair("email", "xxxx@xxx.com")); valuePairs.add(new BasicNameValuePair("password", "xxxxx")); valuePairs.add(new BasicNameValuePair("remember_me", "true")); UrlEncodedFormEntity entity = new UrlEncodedFormEntity(valuePairs, Consts.UTF_8); //創(chuàng)建一個post請求 HttpPost post = new HttpPost("http://www.zhihu.com/login/email"); post.setHeader("Cookie", " cap_id="YjA5MjE0YzYyNGQ2NDY5NWJhMmFhN2YyY2EwODIwZjQ=|1437610072|e7cc307c0d2fe2ee84fd3ceb7f83d298156e37e0"; "); //注入post數(shù)據(jù) post.setEntity(entity); HttpResponse httpResponse = httpClient.execute(post); //打印登錄是否成功信息 printResponse(httpResponse); //構(gòu)造一個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(); // 響應狀態(tài) System.out.println("status:" + httpResponse.getStatusLine()); System.out.println("headers:"); HeaderIterator iterator = httpResponse.headerIterator(); while (iterator.hasNext()) { System.out.println(" " + iterator.next()); } // 判斷響應實體是否為空 if (entity != null) { String responseString = EntityUtils.toString(entity); System.out.println("response length:" + responseString.length()); System.out.println("response content:" + responseString.replace(" ", "")); } } public static Map cookieMap = new HashMap (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寫入到請求頭中,提交請求,查看是否已經(jīng)登錄成功
四 結(jié)果驗證第一張圖顯示得到cookie并登錄成功
第二張圖顯示已經(jīng)進入需要登錄的界面
總結(jié)當我們需要登錄一個界面獲取信息的時候,我們要知道登錄實際上做了什么,那就是讀寫cookie,post數(shù)據(jù)。
獲取cookie時,需要從響應頭中獲取,當服務器發(fā)來新的cookie信息時需要及時寫入。
當我們能登錄一個網(wǎng)站的時候,如何對其內(nèi)容進行操作,這里推薦jsoup,良心庫,仿jquery操作模式。
更多文章:http://blog.gavinzh.com
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/64406.html
摘要:本文章屬于爬蟲入門到精通系統(tǒng)教程第七講直接開始案例吧。本次我們實現(xiàn)如何模擬登陸知乎。 本文章屬于爬蟲入門到精通系統(tǒng)教程第七講 直接開始案例吧。 本次我們實現(xiàn)如何模擬登陸知乎。 1.抓包 首先打開知乎登錄頁 知乎 - 與世界分享你的知識、經(jīng)驗和見解 注意打開開發(fā)者工具后點擊preserve log,密碼記得故意輸入錯誤,然后點擊登錄 showImg(https://segmentfaul...
摘要:最近看了很多關(guān)于爬蟲入門的文章,發(fā)現(xiàn)其中大部分都是以知乎為爬取對象,所以這次我也以知乎為目標來進行爬取的演示,用到的爬蟲框架為編寫的。項目地址這次寫的內(nèi)容為爬取知乎的用戶,下面就是詳細說一下寫爬蟲的過程了。 最近看了很多關(guān)于爬蟲入門的文章,發(fā)現(xiàn)其中大部分都是以知乎為爬取對象,所以這次我也以知乎為目標來進行爬取的演示,用到的爬蟲框架為 PHP 編寫的 Beanbun。 項目地址:http...
摘要:使用腳本發(fā)送郵件并不復雜。以下為思路導圖模塊與發(fā)送郵件相關(guān)的模塊是關(guān)于簡單郵件傳輸協(xié)議的操作模塊,在發(fā)送郵件的過程中起到服務器之間互相通信的作用。 0. 前言 發(fā)送電子郵件是個很常見的開發(fā)需求。比如你寫了個監(jiān)控天氣的腳本,發(fā)現(xiàn)第二天要下雨,或者網(wǎng)站上關(guān)注的某個商品降價了,就可以發(fā)個郵件到郵箱來提醒自己。 使用 Python 腳本發(fā)送郵件并不復雜。不過由于各家郵件的發(fā)送機制和安全策略不同...
摘要:在知乎上,你一定關(guān)注了一些不錯的專欄比如的編程教室。有需要的請在公眾號里回復爬蟲實戰(zhàn)源碼下載獲取知乎專欄下載器源碼,請在公眾號的編程教室里回復關(guān)鍵字知乎除了代碼外,本專欄打包好的也一并奉上,歡迎閱讀與分享。 老是有同學問,學了 Python 基礎后不知道可以做點什么來提高。今天就再用個小例子,給大家講講,通過 Python 和 爬蟲 ,可以完成怎樣的小工具。 在知乎上,你一定關(guān)注了...
摘要:在抓取數(shù)據(jù)之前,請在瀏覽器中登錄過知乎,這樣才使得是有效的。所謂的模擬登陸,只是在中盡量的模擬在瀏覽器中的交互過程,使服務端無感抓包過程。若是幫你解決了問題,或者給了你啟發(fā),不要吝嗇給加一星。 折騰了將近兩天,中間數(shù)次想要放棄,還好硬著頭皮搞下去了,在此分享出來,希望有同等需求的各位能少走一些彎路。 源碼放在了github上, 歡迎前往查看。 若是幫你解決了問題,或者給了你啟發(fā),不要吝...
閱讀 954·2019-08-30 15:55
閱讀 550·2019-08-26 13:56
閱讀 2079·2019-08-26 12:23
閱讀 3295·2019-08-26 10:29
閱讀 600·2019-08-26 10:17
閱讀 2867·2019-08-23 16:53
閱讀 696·2019-08-23 15:55
閱讀 2813·2019-08-23 14:25