HTTP基本要點(diǎn)
HTTP請(qǐng)求,由客戶端向服務(wù)端發(fā)出,可以分為 4 部分內(nèi)容:請(qǐng)求方法(Request Method)、請(qǐng)求的網(wǎng)址(Request URL)、請(qǐng)求頭(Request Headers)、請(qǐng)求體(Request Body)。
請(qǐng)求方法
方 法 | 描述 | 描 述 |
---|---|---|
GET | 請(qǐng)求頁(yè)面,并返回頁(yè)面內(nèi)容 | |
HEAD | 類似于 GET 請(qǐng)求,只不過(guò)返回的響應(yīng)中沒(méi)有具體的內(nèi)容,用于獲取報(bào)頭 | |
POST | 大多用于提交表單或上傳文件,數(shù)據(jù)包含在請(qǐng)求體中 | |
PUT | 從客戶端向服務(wù)器傳送的數(shù)據(jù)取代指定文檔中的內(nèi)容 | |
DELETE | 請(qǐng)求服務(wù)器刪除指定的頁(yè)面 | |
CONNECT | 把服務(wù)器當(dāng)作跳板,讓服務(wù)器代替客戶端訪問(wèn)其他網(wǎng)頁(yè) | |
OPTIONS | 允許客戶端查看服務(wù)器的性能 | |
TRACE | 回顯服務(wù)器收到的請(qǐng)求,主要用于測(cè)試或診斷 |
請(qǐng)求頭
Accept:請(qǐng)求報(bào)頭域,用于指定客戶端可接受哪些類型的信息。
Accept-Language:指定客戶端可接受的語(yǔ)言類型。
Accept-Encoding:指定客戶端可接受的內(nèi)容編碼。
Host:用于指定請(qǐng)求資源的主機(jī) IP 和端口號(hào),其內(nèi)容為請(qǐng)求 URL 的原始服務(wù)器或網(wǎng)關(guān)的位置。從 HTTP 1.1 版本開(kāi)始,請(qǐng)求必須包含此內(nèi)容。
Cookie:也常用復(fù)數(shù)形式 Cookies,這是網(wǎng)站為了辨別用戶進(jìn)行會(huì)話跟蹤而存儲(chǔ)在用戶本地的數(shù)據(jù)。它的主要功能是維持當(dāng)前訪問(wèn)會(huì)話。例如,我們輸入用戶名和密碼成功登錄某個(gè)網(wǎng)站后,服務(wù)器會(huì)用會(huì)話保存登錄狀態(tài)信息,后面我們每次刷新或請(qǐng)求該站點(diǎn)的其他頁(yè)面時(shí),會(huì)發(fā)現(xiàn)都是登錄狀態(tài),這就是 Cookies 的功勞。Cookies 里有信息標(biāo)識(shí)了我們所對(duì)應(yīng)的服務(wù)器的會(huì)話,每次瀏覽器在請(qǐng)求該站點(diǎn)的頁(yè)面時(shí),都會(huì)在請(qǐng)求頭中加上 Cookies 并將其發(fā)送給服務(wù)器,服務(wù)器通過(guò) Cookies 識(shí)別出是我們自己,并且查出當(dāng)前狀態(tài)是登錄狀態(tài),所以返回結(jié)果就是登錄之后才能看到的網(wǎng)頁(yè)內(nèi)容。
Referer:此內(nèi)容用來(lái)標(biāo)識(shí)這個(gè)請(qǐng)求是從哪個(gè)頁(yè)面發(fā)過(guò)來(lái)的,服務(wù)器可以拿到這一信息并做相應(yīng)的處理,如做來(lái)源統(tǒng)計(jì)、防盜鏈處理等。
User-Agent:簡(jiǎn)稱 UA,它是一個(gè)特殊的字符串頭,可以使服務(wù)器識(shí)別客戶使用的操作系統(tǒng)及版本、瀏覽器及版本等信息。在做爬蟲(chóng)時(shí)加上此信息,可以偽裝為瀏覽器;如果不加,很可能會(huì)被識(shí)別出為爬蟲(chóng)。
Content-Type:也叫互聯(lián)網(wǎng)媒體類型(Internet Media Type)或者 MIME 類型,在 HTTP 協(xié)議消息頭中,它用來(lái)表示具體請(qǐng)求中的媒體類型信息。例如,text/html 代表 HTML 格式,image/gif 代表 GIF 圖片,application/json 代表 JSON 類型,更多對(duì)應(yīng)關(guān)系可以查看此對(duì)照表:http://tool.oschina.net/commons。
請(qǐng)求體
Content-Type 和 POST 提交數(shù)據(jù)方式的關(guān)系
Content-Type | 提交數(shù)據(jù)的方式 |
---|---|
application/x-www-form-urlencoded | 表單數(shù)據(jù) |
multipart/form-data | 表單文件上傳 |
application/json | 序列化 JSON 數(shù)據(jù) |
text/xml | XML 數(shù)據(jù) |
響應(yīng)
響應(yīng),由服務(wù)端返回給客戶端,可以分為三部分:響應(yīng)狀態(tài)碼(Response Status Code)、響應(yīng)頭(Response Headers)和響應(yīng)體(Response Body)。
響應(yīng)狀態(tài)碼
常見(jiàn)的錯(cuò)誤代碼及錯(cuò)誤原因
狀態(tài)碼 | 說(shuō) 明 | 詳 情 |
---|---|---|
100 | 繼續(xù) | 請(qǐng)求者應(yīng)當(dāng)繼續(xù)提出請(qǐng)求。服務(wù)器已收到請(qǐng)求的一部分,正在等待其余部分 |
101 | 切換協(xié)議 | 請(qǐng)求者已要求服務(wù)器切換協(xié)議,服務(wù)器已確認(rèn)并準(zhǔn)備切換 |
200 | 成功 | 服務(wù)器已成功處理了請(qǐng)求 |
201 | 已創(chuàng)建 | 請(qǐng)求成功并且服務(wù)器創(chuàng)建了新的資源 |
202 | 已接受 | 服務(wù)器已接受請(qǐng)求,但尚未處理 |
203 | 非授權(quán)信息 | 服務(wù)器已成功處理了請(qǐng)求,但返回的信息可能來(lái)自另一個(gè)源 |
204 | 無(wú)內(nèi)容 | 服務(wù)器成功處理了請(qǐng)求,但沒(méi)有返回任何內(nèi)容 |
205 | 重置內(nèi)容 | 服務(wù)器成功處理了請(qǐng)求,內(nèi)容被重置 |
206 | 部分內(nèi)容 | 服務(wù)器成功處理了部分請(qǐng)求 |
300 | 多種選擇 | 針對(duì)請(qǐng)求,服務(wù)器可執(zhí)行多種操作 |
301 | 永久移動(dòng) | 請(qǐng)求的網(wǎng)頁(yè)已永久移動(dòng)到新位置,即永久重定向 |
302 | 臨時(shí)移動(dòng) | 請(qǐng)求的網(wǎng)頁(yè)暫時(shí)跳轉(zhuǎn)到其他頁(yè)面,即暫時(shí)重定向 |
303 | 查看其他位置 | 如果原來(lái)的請(qǐng)求是 POST,重定向目標(biāo)文檔應(yīng)該通過(guò) GET 提取 |
304 | 未修改 | 此次請(qǐng)求返回的網(wǎng)頁(yè)未修改,繼續(xù)使用上次的資源 |
305 | 使用代理 | 請(qǐng)求者應(yīng)該使用代理訪問(wèn)該網(wǎng)頁(yè) |
307 | 臨時(shí)重定向 | 請(qǐng)求的資源臨時(shí)從其他位置響應(yīng) |
400 | 錯(cuò)誤請(qǐng)求 | 服務(wù)器無(wú)法解析該請(qǐng)求 |
401 | 未授權(quán) | 請(qǐng)求沒(méi)有進(jìn)行身份驗(yàn)證或驗(yàn)證未通過(guò) |
403 | 禁止訪問(wèn) | 服務(wù)器拒絕此請(qǐng)求 |
404 | 未找到 | 服務(wù)器找不到請(qǐng)求的網(wǎng)頁(yè) |
405 | 方法禁用 | 服務(wù)器禁用了請(qǐng)求中指定的方法 |
406 | 不接受 | 無(wú)法使用請(qǐng)求的內(nèi)容響應(yīng)請(qǐng)求的網(wǎng)頁(yè) |
407 | 需要代理授權(quán) | 請(qǐng)求者需要使用代理授權(quán) |
408 | 請(qǐng)求超時(shí) | 服務(wù)器請(qǐng)求超時(shí) |
409 | 沖突 | 服務(wù)器在完成請(qǐng)求時(shí)發(fā)生沖突 |
410 | 已刪除 | 請(qǐng)求的資源已永久刪除 |
411 | 需要有效長(zhǎng)度 | 服務(wù)器不接受不含有效內(nèi)容長(zhǎng)度標(biāo)頭字段的請(qǐng)求 |
412 | 未滿足前提條件 | 服務(wù)器未滿足請(qǐng)求者在請(qǐng)求中設(shè)置的其中一個(gè)前提條件 |
413 | 請(qǐng)求實(shí)體過(guò)大 | 請(qǐng)求實(shí)體過(guò)大,超出服務(wù)器的處理能力 |
414 | 請(qǐng)求 URI 過(guò)長(zhǎng) | 請(qǐng)求網(wǎng)址過(guò)長(zhǎng),服務(wù)器無(wú)法處理 |
415 | 不支持類型 | 請(qǐng)求格式不被請(qǐng)求頁(yè)面支持 |
416 | 請(qǐng)求范圍不符 | 頁(yè)面無(wú)法提供請(qǐng)求的范圍 |
417 | 未滿足期望值 | 服務(wù)器未滿足期望請(qǐng)求標(biāo)頭字段的要求 |
500 | 服務(wù)器內(nèi)部錯(cuò)誤 | 服務(wù)器遇到錯(cuò)誤,無(wú)法完成請(qǐng)求 |
501 | 未實(shí)現(xiàn) | 服務(wù)器不具備完成請(qǐng)求的功能 |
502 | 錯(cuò)誤網(wǎng)關(guān) | 服務(wù)器作為網(wǎng)關(guān)或代理,從上游服務(wù)器收到無(wú)效響應(yīng) |
503 | 服務(wù)不可用 | 服務(wù)器目前無(wú)法使用 |
504 | 網(wǎng)關(guān)超時(shí) | 服務(wù)器作為網(wǎng)關(guān)或代理,但是沒(méi)有及時(shí)從上游服務(wù)器收到請(qǐng)求 |
505 | HTTP 版本不支持 | 服務(wù)器不支持請(qǐng)求中所用的 HTTP 協(xié)議版本 |
響應(yīng)頭
響應(yīng)頭包含了服務(wù)器對(duì)請(qǐng)求的應(yīng)答信息,如 Content-Type、Server、Set-Cookie 等。下面簡(jiǎn)要說(shuō)明一些常用的頭信息。
Date:標(biāo)識(shí)響應(yīng)產(chǎn)生的時(shí)間。
Last-Modified:指定資源的最后修改時(shí)間。
Content-Encoding:指定響應(yīng)內(nèi)容的編碼。
Server:包含服務(wù)器的信息,比如名稱、版本號(hào)等。
Content-Type:文檔類型,指定返回的數(shù)據(jù)類型是什么,如 text/html 代表返回 HTML 文檔,application/x-javascript 則代表返回 JavaScript 文件,image/jpeg 則代表返回圖片。
Set-Cookie:設(shè)置 Cookies。響應(yīng)頭中的 Set-Cookie 告訴瀏覽器需要將此內(nèi)容放在 Cookies 中,下次請(qǐng)求攜帶 Cookies 請(qǐng)求。
Expires:指定響應(yīng)的過(guò)期時(shí)間,可以使代理服務(wù)器或?yàn)g覽器將加載的內(nèi)容更新到緩存中。如果再次訪問(wèn)時(shí),就可以直接從緩存中加載,降低服務(wù)器負(fù)載,縮短加載時(shí)間。
響應(yīng)體
最重要的當(dāng)屬響應(yīng)體的內(nèi)容了。響應(yīng)的正文數(shù)據(jù)都在響應(yīng)體中,比如請(qǐng)求網(wǎng)頁(yè)時(shí),它的響應(yīng)體就是網(wǎng)頁(yè)的 HTML 代碼;請(qǐng)求一張圖片時(shí),它的響應(yīng)體就是圖片的二進(jìn)制數(shù)據(jù)。
web網(wǎng)頁(yè)基礎(chǔ)
節(jié)點(diǎn)樹(shù)及節(jié)點(diǎn)間的關(guān)系
在 HTML 中,所有標(biāo)簽定義的內(nèi)容都是節(jié)點(diǎn),它們構(gòu)成了一個(gè) HTML DOM 樹(shù)。
我們先看下什么是 DOM。DOM 是 W3C(萬(wàn)維網(wǎng)聯(lián)盟)的標(biāo)準(zhǔn),其英文全稱 Document Object Model,即文檔對(duì)象模型。它定義了訪問(wèn) HTML 和 XML 文檔的標(biāo)準(zhǔn):
W3C 文檔對(duì)象模型(DOM)是中立于平臺(tái)和語(yǔ)言的接口,它允許程序和腳本動(dòng)態(tài)地訪問(wèn)和更新文檔的內(nèi)容、結(jié)構(gòu)和樣式。
根據(jù) W3C 的 HTML DOM 標(biāo)準(zhǔn),HTML 文檔中的所有內(nèi)容都是節(jié)點(diǎn):
-
整個(gè)文檔是一個(gè)文檔節(jié)點(diǎn)
-
每個(gè) HTML 元素是元素節(jié)點(diǎn)
-
HTML 元素內(nèi)的文本是文本節(jié)點(diǎn)
-
每個(gè) HTML 屬性是屬性節(jié)點(diǎn)
-
注釋是注釋節(jié)點(diǎn)
HTML DOM 將 HTML 文檔視作樹(shù)結(jié)構(gòu),這種結(jié)構(gòu)被稱為節(jié)點(diǎn)樹(shù)
通過(guò) HTML DOM,樹(shù)中的所有節(jié)點(diǎn)均可通過(guò) JavaScript 訪問(wèn),所有 HTML 節(jié)點(diǎn)元素均可被修改,也可以被創(chuàng)建或刪除。
節(jié)點(diǎn)樹(shù)中的節(jié)點(diǎn)彼此擁有層級(jí)關(guān)系。我們常用父(parent)、子(child)和兄弟(sibling)等術(shù)語(yǔ)描述這些關(guān)系。父節(jié)點(diǎn)擁有子節(jié)點(diǎn),同級(jí)的子節(jié)點(diǎn)被稱為兄弟節(jié)點(diǎn)。
在節(jié)點(diǎn)樹(shù)中,頂端節(jié)點(diǎn)稱為根(root)。除了根節(jié)點(diǎn)之外,每個(gè)節(jié)點(diǎn)都有父節(jié)點(diǎn),同時(shí)可擁有任意數(shù)量的子節(jié)點(diǎn)或兄弟節(jié)點(diǎn)。
選擇器
我們知道網(wǎng)頁(yè)由一個(gè)個(gè)節(jié)點(diǎn)組成,CSS 選擇器會(huì)根據(jù)不同的節(jié)點(diǎn)設(shè)置不同的樣式規(guī)則,那么怎樣來(lái)定位節(jié)點(diǎn)呢?
在 CSS 中,我們使用 CSS 選擇器來(lái)定位節(jié)點(diǎn)。例如,上例中 div 節(jié)點(diǎn)的 id 為 container,那么就可以表示為 #container,其中 # 開(kāi)頭代表選擇 id,其后緊跟 id 的名稱。另外,如果我們想選擇 class 為 wrapper 的節(jié)點(diǎn),便可以使用.wrapper,這里以點(diǎn)(.)開(kāi)頭代表選擇 class,其后緊跟 class 的名稱。另外,還有一種選擇方式,那就是根據(jù)標(biāo)簽名篩選,例如想選擇二級(jí)標(biāo)題,直接用 h2 即可。這是最常用的 3 種表示,分別是根據(jù) id、class、標(biāo)簽名篩選,請(qǐng)牢記它們的寫(xiě)法。
另外,CSS 選擇器還支持嵌套選擇,各個(gè)選擇器之間加上空格分隔開(kāi)便可以代表嵌套關(guān)系,如 #container .wrapper p 則代表先選擇 id 為 container 的節(jié)點(diǎn),然后選中其內(nèi)部的 class 為 wrapper 的節(jié)點(diǎn),然后再進(jìn)一步選中其內(nèi)部的 p 節(jié)點(diǎn)。另外,如果不加空格,則代表并列關(guān)系,如 div#container .wrapper p.text 代表先選擇 id 為 container 的 div 節(jié)點(diǎn),然后選中其內(nèi)部的 class 為 wrapper 的節(jié)點(diǎn),再進(jìn)一步選中其內(nèi)部的 class 為 text 的 p 節(jié)點(diǎn)。這就是 CSS 選擇器,其篩選功能還是非常強(qiáng)大的。
另外,CSS 選擇器還有一些其他語(yǔ)法規(guī)則
選 擇 器 | 例 子 | 例子描述 |
---|---|---|
.class | .intro | 選擇 class=“intro” 的所有節(jié)點(diǎn) |
#id | #firstname | 選擇 id=“firstname” 的所有節(jié)點(diǎn) |
* | * | 選擇所有節(jié)點(diǎn) |
element | p | 選擇所有 p 節(jié)點(diǎn) |
element,element | div,p | 選擇所有 div 節(jié)點(diǎn)和所有 p 節(jié)點(diǎn) |
element element | div p | 選擇 div 節(jié)點(diǎn)內(nèi)部的所有 p 節(jié)點(diǎn) |
element>element | div>p | 選擇父節(jié)點(diǎn)為 div 節(jié)點(diǎn)的所有 p 節(jié)點(diǎn) |
element+element | div+p | 選擇緊接在 div 節(jié)點(diǎn)之后的所有 p 節(jié)點(diǎn) |
[attribute] | [target] | 選擇帶有 target 屬性的所有節(jié)點(diǎn) |
[attribute=value] | [target=blank] | 選擇 target=“blank” 的所有節(jié)點(diǎn) |
[attribute~=value] | [title~=flower] | 選擇 title 屬性包含單詞 flower 的所有節(jié)點(diǎn) |
:link | a:link | 選擇所有未被訪問(wèn)的鏈接 |
:visited | a:visited | 選擇所有已被訪問(wèn)的鏈接 |
:active | a:active | 選擇活動(dòng)鏈接 |
:hover | a:hover | 選擇鼠標(biāo)指針位于其上的鏈接 |
:focus | input:focus | 選擇獲得焦點(diǎn)的 input 節(jié)點(diǎn) |
:first-letter | p:first-letter | 選擇每個(gè) p 節(jié)點(diǎn)的首字母 |
:first-line | p:first-line | 選擇每個(gè) p 節(jié)點(diǎn)的首行 |
:first-child | p:first-child | 選擇屬于父節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn)的所有 p 節(jié)點(diǎn) |
:before | p:before | 在每個(gè) p 節(jié)點(diǎn)的內(nèi)容之前插入內(nèi)容 |
:after | p:after | 在每個(gè) p 節(jié)點(diǎn)的內(nèi)容之后插入內(nèi)容 |
:lang(language) | p:lang | 選擇帶有以 it 開(kāi)頭的 lang 屬性值的所有 p 節(jié)點(diǎn) |
element1~element2 | p~ul | 選擇前面有 p 節(jié)點(diǎn)的所有 ul 節(jié)點(diǎn) |
[attribute^=value] | a[src^=“https”] | 選擇其 src 屬性值以 https 開(kāi)頭的所有 a 節(jié)點(diǎn) |
[attribute$=value] | a[src$=“.pdf”] | 選擇其 src 屬性以.pdf 結(jié)尾的所有 a 節(jié)點(diǎn) |
[attribute*=value] | a[src*=“abc”] | 選擇其 src 屬性中包含 abc 子串的所有 a 節(jié)點(diǎn) |
:first-of-type | p:first-of-type | 選擇屬于其父節(jié)點(diǎn)的首個(gè) p 節(jié)點(diǎn)的所有 p 節(jié)點(diǎn) |
:last-of-type | p:last-of-type | 選擇屬于其父節(jié)點(diǎn)的最后 p 節(jié)點(diǎn)的所有 p 節(jié)點(diǎn) |
:only-of-type | p:only-of-type | 選擇屬于其父節(jié)點(diǎn)唯一的 p 節(jié)點(diǎn)的所有 p 節(jié)點(diǎn) |
:only-child | p:only-child | 選擇屬于其父節(jié)點(diǎn)的唯一子節(jié)點(diǎn)的所有 p 節(jié)點(diǎn) |
:nth-child(n) | p:nth-child | 選擇屬于其父節(jié)點(diǎn)的第二個(gè)子節(jié)點(diǎn)的所有 p 節(jié)點(diǎn) |
:nth-last-child(n) | p:nth-last-child | 同上,從最后一個(gè)子節(jié)點(diǎn)開(kāi)始計(jì)數(shù) |
:nth-of-type(n) | p:nth-of-type | 選擇屬于其父節(jié)點(diǎn)第二個(gè) p 節(jié)點(diǎn)的所有 p 節(jié)點(diǎn) |
:nth-last-of-type(n) | p:nth-last-of-type | 同上,但是從最后一個(gè)子節(jié)點(diǎn)開(kāi)始計(jì)數(shù) |
:last-child | p:last-child | 選擇屬于其父節(jié)點(diǎn)最后一個(gè)子節(jié)點(diǎn)的所有 p 節(jié)點(diǎn) |
:root | :root | 選擇文檔的根節(jié)點(diǎn) |
:empty | p:empty | 選擇沒(méi)有子節(jié)點(diǎn)的所有 p 節(jié)點(diǎn)(包括文本節(jié)點(diǎn)) |
:target | #news:target | 選擇當(dāng)前活動(dòng)的 #news 節(jié)點(diǎn) |
:enabled | input:enabled | 選擇每個(gè)啟用的 input 節(jié)點(diǎn) |
:disabled | input:disabled | 選擇每個(gè)禁用的 input 節(jié)點(diǎn) |
:checked | input:checked | 選擇每個(gè)被選中的 input 節(jié)點(diǎn) |
:not(selector) | :not | 選擇非 p 節(jié)點(diǎn)的所有節(jié)點(diǎn) |
::selection | ::selection | 選擇被用戶選取的節(jié)點(diǎn)部分 |
爬蟲(chóng)基本原理
獲取網(wǎng)頁(yè)
首先要做的是獲取網(wǎng)頁(yè)的源代碼,向服務(wù)器發(fā)送一個(gè)請(qǐng)求,返回的就是網(wǎng)頁(yè)源代碼,可以利用python提供的urllib,requests等庫(kù)幫我們實(shí)現(xiàn),得到響應(yīng)之后解析數(shù)據(jù)結(jié)構(gòu)中的網(wǎng)頁(yè)源代碼即可。
提取信息
通常采用正則表達(dá)式提取想要的數(shù)據(jù),也可以根據(jù)網(wǎng)頁(yè)節(jié)點(diǎn)屬性、CSS選擇器、XPath來(lái)提取,如 Beautiful Soup、pyquery、lxml 等庫(kù)
保存數(shù)據(jù)
將數(shù)據(jù)簡(jiǎn)單保存為txt或保存到數(shù)據(jù)庫(kù)
JavaScript 渲染頁(yè)面
有時(shí)候,我們?cè)谟?urllib 或 requests 抓取網(wǎng)頁(yè)時(shí),得到的源代碼實(shí)際和瀏覽器中看到的不一樣。
這是一個(gè)非常常見(jiàn)的問(wèn)題。現(xiàn)在網(wǎng)頁(yè)越來(lái)越多地采用 Ajax、前端模塊化工具來(lái)構(gòu)建,整個(gè)網(wǎng)頁(yè)可能都是由 JavaScript 渲染出來(lái)的,也就是說(shuō)原始的 HTML 代碼就是一個(gè)空殼,例如:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>This is a Demo</title>
</head>
<body>
<div id="container">
</div>
</body>
<script src="app.js"></script>
</html>
body 節(jié)點(diǎn)里面只有一個(gè) id 為 container 的節(jié)點(diǎn),但是需要注意在 body 節(jié)點(diǎn)后引入了 app.js,它便負(fù)責(zé)整個(gè)網(wǎng)站的渲染。
在瀏覽器中打開(kāi)這個(gè)頁(yè)面時(shí),首先會(huì)加載這個(gè) HTML 內(nèi)容,接著瀏覽器會(huì)發(fā)現(xiàn)其中引入了一個(gè) app.js 文件,然后便會(huì)接著去請(qǐng)求這個(gè)文件,獲取到該文件后,便會(huì)執(zhí)行其中的 JavaScript 代碼,而 JavaScript 則會(huì)改變 HTML 中的節(jié)點(diǎn),向其添加內(nèi)容,最后得到完整的頁(yè)面。
但是在用 urllib 或 requests 等庫(kù)請(qǐng)求當(dāng)前頁(yè)面時(shí),我們得到的只是這個(gè) HTML 代碼,它不會(huì)幫助我們?nèi)ダ^續(xù)加載這個(gè) JavaScript 文件,這樣也就看不到瀏覽器中的內(nèi)容了。
這也解釋了為什么有時(shí)我們得到的源代碼和瀏覽器中看到的不一樣。
因此,使用基本 HTTP 請(qǐng)求庫(kù)得到的源代碼可能跟瀏覽器中的頁(yè)面源代碼不太一樣。對(duì)于這樣的情況,我們可以分析其后臺(tái) Ajax 接口,也可使用 Selenium、Splash 這樣的庫(kù)來(lái)實(shí)現(xiàn)模擬 JavaScript 渲染。
會(huì)話與Cookies
靜態(tài)網(wǎng)頁(yè)與動(dòng)態(tài)網(wǎng)頁(yè)
靜態(tài)網(wǎng)頁(yè)的內(nèi)容只采用html編寫(xiě),加載速度快,編寫(xiě)簡(jiǎn)單,但是不能使用URL傳入?yún)?shù)來(lái)動(dòng)態(tài)地改變頁(yè)面上的內(nèi)容,動(dòng)態(tài)網(wǎng)頁(yè)應(yīng)運(yùn)而生,它可以動(dòng)態(tài)解析 URL 中參數(shù)的變化,關(guān)聯(lián)數(shù)據(jù)庫(kù)并動(dòng)態(tài)呈現(xiàn)不同的頁(yè)面內(nèi)容,非常靈活多變。
無(wú)狀態(tài)HTTP
HTTP 的無(wú)狀態(tài)是指 HTTP 協(xié)議對(duì)事務(wù)處理是沒(méi)有記憶能力的,也就是說(shuō)服務(wù)器不知道客戶端是什么狀態(tài)。當(dāng)我們向服務(wù)器發(fā)送請(qǐng)求后,服務(wù)器解析此請(qǐng)求,然后返回對(duì)應(yīng)的響應(yīng),服務(wù)器負(fù)責(zé)完成這個(gè)過(guò)程,而且這個(gè)過(guò)程是完全獨(dú)立的,服務(wù)器不會(huì)記錄前后狀態(tài)的變化,也就是缺少狀態(tài)記錄。這意味著如果后續(xù)需要處理前面的信息,則必須重傳,這導(dǎo)致需要額外傳遞一些前面的重復(fù)請(qǐng)求,才能獲取后續(xù)響應(yīng),然而這種效果顯然不是我們想要的。為了保持前后狀態(tài),我們肯定不能將前面的請(qǐng)求全部重傳一次,這太浪費(fèi)資源了,對(duì)于這種需要用戶登錄的頁(yè)面來(lái)說(shuō),更是棘手。
這時(shí)兩個(gè)用于保持 HTTP 連接狀態(tài)的技術(shù)就出現(xiàn)了,它們分別是會(huì)話和 Cookies。會(huì)話在服務(wù)端,也就是網(wǎng)站的服務(wù)器,用來(lái)保存用戶的會(huì)話信息;Cookies 在客戶端,也可以理解為瀏覽器端,有了 Cookies,瀏覽器在下次訪問(wèn)網(wǎng)頁(yè)時(shí)會(huì)自動(dòng)附帶上它發(fā)送給服務(wù)器,服務(wù)器通過(guò)識(shí)別 Cookies 并鑒定出是哪個(gè)用戶,然后再判斷用戶是否是登錄狀態(tài),然后返回對(duì)應(yīng)的響應(yīng)。
我們可以理解為 Cookies 里面保存了登錄的憑證,有了它,只需要在下次請(qǐng)求攜帶 Cookies 發(fā)送請(qǐng)求而不必重新輸入用戶名、密碼等信息重新登錄了。
會(huì)話
在 Web 中,會(huì)話對(duì)象用來(lái)存儲(chǔ)特定用戶會(huì)話所需的屬性及配置信息。這樣,當(dāng)用戶在應(yīng)用程序的 Web 頁(yè)之間跳轉(zhuǎn)時(shí),存儲(chǔ)在會(huì)話對(duì)象中的變量將不會(huì)丟失,而是在整個(gè)用戶會(huì)話中一直存在下去。當(dāng)用戶請(qǐng)求來(lái)自應(yīng)用程序的 Web 頁(yè)時(shí),如果該用戶還沒(méi)有會(huì)話,則 Web 服務(wù)器將自動(dòng)創(chuàng)建一個(gè)會(huì)話對(duì)象。當(dāng)會(huì)話過(guò)期或被放棄后,服務(wù)器將終止該會(huì)話。
Cookies
Cookies 指某些網(wǎng)站為了辨別用戶身份、進(jìn)行會(huì)話跟蹤而存儲(chǔ)在用戶本地終端上的數(shù)據(jù)。
當(dāng)客戶端第一次請(qǐng)求服務(wù)器時(shí),服務(wù)器會(huì)返回一個(gè)響應(yīng)頭中帶有 Set-Cookie 字段的響應(yīng)給客戶端,用來(lái)標(biāo)記是哪一個(gè)用戶,客戶端瀏覽器會(huì)把 Cookies 保存起來(lái)。當(dāng)瀏覽器下一次再請(qǐng)求該網(wǎng)站時(shí),瀏覽器會(huì)把此 Cookies 放到請(qǐng)求頭一起提交給服務(wù)器,Cookies 攜帶了會(huì)話 ID 信息,服務(wù)器檢查該 Cookies 即可找到對(duì)應(yīng)的會(huì)話是什么,然后再判斷會(huì)話來(lái)以此來(lái)辨認(rèn)用戶狀態(tài)。
在后續(xù)訪問(wèn)頁(yè)面時(shí)客戶端會(huì)把 Cookies 發(fā)送給服務(wù)器,服務(wù)器再找到對(duì)應(yīng)的會(huì)話加以判斷。如果會(huì)話中的某些設(shè)置登錄狀態(tài)的變量是有效的,那就證明用戶處于登錄狀態(tài)
屬性結(jié)構(gòu)
Name,即該 Cookie 的名稱。Cookie 一旦創(chuàng)建,名稱便不可更改
Value,即該 Cookie 的值。如果值為 Unicode 字符,需要為字符編碼。如果值為二進(jìn)制數(shù)據(jù),則需要使用 BASE64 編碼。
Max Age,即該 Cookie 失效的時(shí)間,單位秒,也常和 Expires 一起使用,通過(guò)它可以計(jì)算出其有效時(shí)間。Max Age 如果為正數(shù),則該 Cookie 在 Max Age 秒之后失效。如果為負(fù)數(shù),則關(guān)閉瀏覽器時(shí) Cookie 即失效,瀏覽器也不會(huì)以任何形式保存該 Cookie。
Path,即該 Cookie 的使用路徑。如果設(shè)置為 /path/,則只有路徑為 /path/ 的頁(yè)面可以訪問(wèn)該 Cookie。如果設(shè)置為 /,則本域名下的所有頁(yè)面都可以訪問(wèn)該 Cookie。
Domain,即可以訪問(wèn)該 Cookie 的域名。例如如果設(shè)置為 .zhihu.com,則所有以 zhihu.com,結(jié)尾的域名都可以訪問(wèn)該 Cookie。
Size 字段,即此 Cookie 的大小。
Http 字段,即 Cookie 的 httponly 屬性。若此屬性為 true,則只有在 HTTP Headers 中會(huì)帶有此 Cookie 的信息,而不能通過(guò) document.cookie 來(lái)訪問(wèn)此 Cookie。
Secure,即該 Cookie 是否僅被使用安全協(xié)議傳輸。安全協(xié)議。安全協(xié)議有 HTTPS,SSL 等,在網(wǎng)絡(luò)上傳輸數(shù)據(jù)之前先將數(shù)據(jù)加密。默認(rèn)為 false。
代理基本原理
代理實(shí)際上指的就是代理服務(wù)器,英文叫作 proxy server,它的功能是代理網(wǎng)絡(luò)用戶去取得網(wǎng)絡(luò)信息。形象地說(shuō),它是網(wǎng)絡(luò)信息的中轉(zhuǎn)站。在我們正常請(qǐng)求一個(gè)網(wǎng)站時(shí),是發(fā)送了請(qǐng)求給 Web 服務(wù)器,Web 服務(wù)器把響應(yīng)傳回給我們。如果設(shè)置了代理服務(wù)器,實(shí)際上就是在本機(jī)和服務(wù)器之間搭建了一個(gè)橋,此時(shí)本機(jī)不是直接向 Web 服務(wù)器發(fā)起請(qǐng)求,而是向代理服務(wù)器發(fā)出請(qǐng)求,請(qǐng)求會(huì)發(fā)送給代理服務(wù)器,然后由代理服務(wù)器再發(fā)送給 Web 服務(wù)器,接著由代理服務(wù)器再把 Web 服務(wù)器返回的響應(yīng)轉(zhuǎn)發(fā)給本機(jī)。這樣我們同樣可以正常訪問(wèn)網(wǎng)頁(yè),但這個(gè)過(guò)程中 Web 服務(wù)器識(shí)別出的真實(shí) IP 就不再是我們本機(jī)的 IP 了,就成功實(shí)現(xiàn)了 IP 偽裝,這就是代理的基本原理。
代理的作用
代理有什么作用呢?我們可以簡(jiǎn)單列舉如下。
-
突破自身 IP 訪問(wèn)限制,訪問(wèn)一些平時(shí)不能訪問(wèn)的站點(diǎn)。
-
訪問(wèn)一些單位或團(tuán)體內(nèi)部資源,如使用教育網(wǎng)內(nèi)地址段免費(fèi)代理服務(wù)器,就可以用于對(duì)教育網(wǎng)開(kāi)放的各類 FTP 下載上傳,以及各類資料查詢共享等服務(wù)。
-
提高訪問(wèn)速度,通常代理服務(wù)器都設(shè)置一個(gè)較大的硬盤(pán)緩沖區(qū),當(dāng)有外界的信息通過(guò)時(shí),同時(shí)也將其保存到緩沖區(qū)中,當(dāng)其他用戶再訪問(wèn)相同的信息時(shí), 則直接由緩沖區(qū)中取出信息,傳給用戶,以提高訪問(wèn)速度。
-
隱藏真實(shí) IP,上網(wǎng)者也可以通過(guò)這種方法隱藏自己的 IP,免受攻擊,對(duì)于爬蟲(chóng)來(lái)說(shuō),我們用代理就是為了隱藏自身 IP,防止自身的 IP 被封鎖。
代理分類
FTP 代理服務(wù)器,主要用于訪問(wèn) FTP 服務(wù)器,一般有上傳、下載以及緩存功能,端口一般為 21、2121 等。
HTTP 代理服務(wù)器,主要用于訪問(wèn)網(wǎng)頁(yè),一般有內(nèi)容過(guò)濾和緩存功能,端口一般為 80、8080、3128 等。
SSL/TLS 代理,主要用于訪問(wèn)加密網(wǎng)站,一般有 SSL 或 TLS 加密功能(最高支持 128 位加密強(qiáng)度),端口一般為 443。
RTSP 代理,主要用于 Realplayer 訪問(wèn) Real 流媒體服務(wù)器,一般有緩存功能,端口一般為 554。
Telnet 代理,主要用于 telnet 遠(yuǎn)程控制(黑客入侵計(jì)算機(jī)時(shí)常用于隱藏身份),端口一般為 23。
POP3/SMTP 代理,主要用于 POP3/SMTP 方式收發(fā)郵件,一般有緩存功能,端口一般為 110/25。
SOCKS 代理,只是單純傳遞數(shù)據(jù)包,不關(guān)心具體協(xié)議和用法,所以速度快很多,一般有緩存功能,端口一般為 1080。SOCKS 代理協(xié)議又分為 SOCKS4 和 SOCKS5,SOCKS4 協(xié)議只支持 TCP,而 SOCKS5 協(xié)議支持 TCP 和 UDP,還支持各種身份驗(yàn)證機(jī)制、服務(wù)器端域名解析等。簡(jiǎn)單來(lái)說(shuō),SOCK4 能做到的 SOCKS5 都可以做到,但 SOCKS5 能做到的 SOCK4 不一定能做到。
高度匿名代理,高度匿名代理會(huì)將數(shù)據(jù)包原封不動(dòng)的轉(zhuǎn)發(fā),在服務(wù)端看來(lái)就好像真的是一個(gè)普通客戶端在訪問(wèn),而記錄的 IP 是代理服務(wù)器的 IP。
普通匿名代理,普通匿名代理會(huì)在數(shù)據(jù)包上做一些改動(dòng),服務(wù)端上有可能發(fā)現(xiàn)這是個(gè)代理服務(wù)器,也有一定幾率追查到客戶端的真實(shí) IP。代理服務(wù)器通常會(huì)加入的 HTTP 頭有 HTTP_VIA 和 HTTP_X_FORWARDED_FOR。
透明代理,透明代理不但改動(dòng)了數(shù)據(jù)包,還會(huì)告訴服務(wù)器客戶端的真實(shí) IP。這種代理除了能用緩存技術(shù)提高瀏覽速度,能用內(nèi)容過(guò)濾提高安全性之外,并無(wú)其他顯著作用,最常見(jiàn)的例子是內(nèi)網(wǎng)中的硬件防火墻。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-714500.html
間諜代理,間諜代理指組織或個(gè)人創(chuàng)建的,用于記錄用戶傳輸?shù)臄?shù)據(jù),然后進(jìn)行研究、監(jiān)控等目的代理服務(wù)器。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-714500.html
到了這里,關(guān)于python爬蟲(chóng)入門(一)web基礎(chǔ)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!