天天看點

《Python爬蟲開發與項目實戰》——2.2 HTTP标準

本節書摘來自華章計算機《python爬蟲開發與項目實戰》一書中的第2章,第2.2節,作者:範傳輝著,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視

  http協定(hypertext transfer protocol,超文本傳輸協定)是用于從www伺服器傳輸超文本到本地浏覽器的傳送協定。它可以使浏覽器更加高效,減少網絡傳輸。它不僅保證計算機正确快速地傳輸超文本文檔,還确定傳輸文檔中的哪一部分,以及哪部分内容首先顯示(如文本先于圖形)等。之後的python爬蟲開發,主要就是和http協定打交道。

2.2.1 http請求過程

  http協定采取的是請求響應模型,http協定永遠都是用戶端發起請求,伺服器回送響應。模型如圖2-8所示。

《Python爬蟲開發與項目實戰》——2.2 HTTP标準

  http協定是一個無狀态的協定,同一個用戶端的這次請求和上次請求沒有對應關系。一次http操作稱為一個事務,其執行過程可分為四步:

首先用戶端與伺服器需要建立連接配接,例如單擊某個超連結,http的工作就開始了。

建立連接配接後,用戶端發送一個請求給伺服器,請求方式的格式為:統一資源辨別符(url)、協定版本号,後邊是mime資訊,包括請求修飾符、客戶機資訊和可能的内容。

伺服器接到請求後,給予相應的響應資訊,其格式為一個狀态行,包括資訊的協定版本号、一個成功或錯誤的代碼,後邊是mime資訊,包括伺服器資訊、實體資訊和可能的内容。

用戶端接收伺服器所傳回的資訊,通過浏覽器将資訊顯示在使用者的顯示屏上,然後用戶端與伺服器斷開連接配接。

  如果以上過程中的某一步出現錯誤,那麼産生錯誤的資訊将傳回到用戶端,在顯示屏輸出,這些過程是由http協定自己完成的。

2.2.2 http狀态碼含義

  當浏覽者通路一個網頁時,浏覽者的浏覽器會向網頁所在伺服器送出請求。在浏覽器接收并顯示網頁前,此網頁所在的伺服器會傳回一個包含http狀态碼的資訊頭(server header)用以響應浏覽器的請求。http狀态碼主要是是為了辨別此次http請求的運作狀态。下面是常見的http狀态碼:

200——請求成功。

301——資源(網頁等)被永久轉移到其他url。

404——請求的資源(網頁等)不存在。

500——内部伺服器錯誤。

  http狀态碼由三個十進制數字組成,第一個十進制數字定義了狀态碼的類型。http狀态碼共分為5種類型,如表2-9所示。

《Python爬蟲開發與項目實戰》——2.2 HTTP标準

  全部的http狀态碼的資訊,請大家查詢http協定标準手冊。

2.2.3 http頭部資訊

  http頭部資訊由衆多的頭域組成,每個頭域由一個域名、冒号(:)和域值三部分組成。域名是大小寫無關的,域值前可以添加任何數量的空格符,頭域可以被擴充為多行,在每行開始處,使用至少一個空格或制表符。

  通過浏覽器通路部落格園首頁時,使用f12打開開發者工具,裡面可以監控整個http通路的過程。下面就以通路部落格園的http請求進行分析,首先是浏覽器送出請求,請求頭的資料如下:

  在請求頭中包含以下内容:

get代表的是請求方式,http/1.1表示使用http 1.1協定标準。

host頭域,用于指定請求資源的intenet主機和端口号,必須表示請求url的原始伺服器或網關的位置。http/1.1請求必須包含主機頭域,否則系統會以400狀态碼傳回。

user-agent頭域,裡面包含送出請求的使用者資訊,其中有使用的浏覽器型号、版本和作業系統的資訊。這個頭域經常用來作為反爬蟲的措施。

accept請求報頭域,用于指定用戶端接受哪些類型的資訊。例如:accept:image/gif,表明用戶端希望接受gif圖象格式的資源;accept:text/html,表明用戶端希望接受html文本。

accept-language請求報頭域,類似于accept,但是它用于指定一種自然語言。例如:accept-language:zh-cn.如果請求消息中沒有設定這個報頭域,伺服器假定用戶端對各種語言都可以接受。

accept-encoding請求報頭域,類似于accept,但是它用于指定可接受的内容編碼。例如:accept-encoding:gzip.deflate。如果請求消息中沒有設定這個域伺服器假定用戶端對各種内容編碼都可以接受。

connection報頭域允許發送用于指定連接配接的選項。例如指定連接配接的狀态是連續,或者指定“close”選項,通知伺服器,在響應完成後,關閉連接配接。

if-modified-since頭域用于在發送http請求時,把浏覽器端緩存頁面的最後修改時間一起發到伺服器去,伺服器會把這個時間與伺服器上實際檔案的最後修改時間進行比較。如果時間一緻,那麼傳回http狀态碼304(不傳回檔案内容),用戶端收到之後,就直接把本地緩存檔案顯示到浏覽器中。如果時間不一緻,就傳回http狀态碼200和新的檔案内容,用戶端收到之後,會丢棄舊檔案,把新檔案緩存起來,并顯示到浏覽器中。

  請求發送成功後,伺服器進行響應,接下來看一下響應的頭資訊,資料如下:

《Python爬蟲開發與項目實戰》——2.2 HTTP标準

  響應頭中包含以下内容:

http/1.1表示使用http 1.1協定标準,200 ok說明請求成功。

date表示消息産生的日期和時間。

content-type實體報頭域用于指明發送給接收者的實體正文的媒體類型。text/html; charset=utf-8代表html文本文檔,utf-8編碼。

transfer-encoding:chunked表示輸出的内容長度不能确定。

vary頭域指定了一些請求頭域,這些請求頭域用來決定當緩存中存在一個響應,并且該緩存沒有過期失效時,是否被允許利用此響應去回複後續請求而不需要重複驗證。

cache-control用于指定緩存指令,緩存指令是單向的,且是獨立的。請求時的緩存指令包括:no-cache(用于訓示請求或響應消息不能緩存)、no-store、max-age、max-stale、min-fresh、only-if-cached;響應時的緩存指令包括:public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age、s-maxage。

expires實體報頭域給出響應過期的日期和時間。為了讓代理伺服器或浏覽器在一段時間以後更新緩存中(再次通路曾通路過的頁面時,直接從緩存中加載,縮短響應時間和降低伺服器負載)的頁面,我們可以使用expires實體報頭域指定頁面過期的時間。

last-modified實體報頭域用于訓示資源的最後修改日期和時間。

content-encoding實體報頭域被用作媒體類型的修飾符,它的值訓示了已經被應用到實體正文的附加内容的編碼,因而要獲得content-type報頭域中所引用的媒體類型,必須采用相應的解碼機制。

  從上面分析的過程中,大家基本上了解了請求和響應的頭資訊,最後進行一下總結:

  http消息報頭主要包括普通報頭、請求報頭、響應報頭、實體報頭。具體如下:

  1)在普通報頭中,有少數報頭域用于所有的請求和響應消息,但并不用于被傳輸的實體,隻用于傳輸的消息。

  2)請求報頭允許用戶端向伺服器端傳遞請求的附加資訊以及用戶端自身的資訊。

  3)響應報頭允許伺服器傳遞不能放在狀态行中的附加響應資訊,以及關于伺服器的資訊和對request-uri所辨別的資源進行下一步通路的資訊。

  4)請求和響應消息都可以傳送一個實體。一個實體由實體報頭域和實體正文組成,但并不是說實體報頭域和實體正文要在一起發送,可以隻發送實體報頭域。實體報頭定義了關于實體正文和請求所辨別的資源的元資訊。

  通過表2-10~表2-13對封包頭進行分類列舉說明。

《Python爬蟲開發與項目實戰》——2.2 HTTP标準
《Python爬蟲開發與項目實戰》——2.2 HTTP标準

2.2.4 cookie狀态管理

  cookie和session都用來儲存狀态資訊,都是儲存用戶端狀态的機制,它們都是為了解決http無狀态的問題所做的努力。對于爬蟲開發來說,我們更加關注的是cookie,因為cookie将狀态儲存在用戶端,session将狀态儲存在伺服器端。

  cookie是伺服器在本地機器上存儲的小段文本并随每一個請求發送至同一個伺服器。網絡伺服器用http頭向用戶端發送cookie,浏覽器則會解析這些cookie并将它們儲存為一個本地檔案,它會自動将同一伺服器的任何請求綁定上這些cookie。

  cookie的工作方式:伺服器給每個session配置設定一個唯一的jsessionid,并通過cookie發送給用戶端。當用戶端發起新的請求的時候,将在cookie頭中攜帶這個jsessionid。這樣伺服器能夠找到這個用戶端對應的session,流程如圖2-9所示。

《Python爬蟲開發與項目實戰》——2.2 HTTP标準

2.2.5 http請求方式

  http的請求方法包括如下幾種:

get

post

head

put

delete

options

trace

connect

  其中常用的請求方式是get和post:

get方式:是以實體的方式得到由請求url所指定資源的資訊,如果請求url隻是一個資料産生過程,那麼最終要在響應實體中傳回的是處理過程的結果所指向的資源,而不是處理過程的描述。

post方式:用來向目的伺服器送出請求,要求它接受被附在請求後的實體,并把它當作請求隊列中請求url所指定資源的附加新子項。

get與post方法有以下差別:

在用戶端,get方式通過url送出資料,資料在url中可以看到:post方式,資料放置在實體區内送出。

get方式送出的資料最多隻能有1024位元組,而post則沒有此限制。

安全性問題。使用get的時候,參數會顯示在位址欄上,而post不會。是以,如果這些資料是非敏感資料,那麼使用get;如果使用者輸入的資料包含敏感資料,那麼還是使用post為好。

  在爬蟲開發中基本處理的也是get和post請求。get請求在通路網頁時很常見,post請求則是常用在登入框、送出框的位置。下面展示一個完整的post請求,這是登入知乎社群時捕獲的請求,上面一部分是請求頭,下面全部加粗的資料是請求實體。請求内容如下:

《Python爬蟲開發與項目實戰》——2.2 HTTP标準
《Python爬蟲開發與項目實戰》——2.2 HTTP标準