事和組長的一番對話引起了筆者對 git 的思考
先介紹一下我司小工坊式的 git 提交流程,本地打包,刪除 dist 文件,重建 dist 文件,git add .,git commit -m 'XX',git push origin 分支名
和傳統(tǒng)公司的 git 提交不同,我司打包是本地打包,而且是把 dist 文件直接上傳到倉庫
同事把代碼推上去后,瀏覽器訪問的還是原來的 js 和 css。
同事說:組長,需要你把 dist 刪掉,重新再從倉庫里拉一下最新的
組長:git 提交后不就把原來的 dist 替換了嗎,你讓我刪 dist 有什么意義
扯皮了一會兒,組長還是刪了然后重新拉,沒想到好了
組長說:你的 dist 現(xiàn)在是最新的,所以現(xiàn)在就好了
同事具體說了什么筆者忘記了,大致上在辯護(hù) git 提交不會把原來的 dist 文件刪除問題,不過他沒說服組長,組長也沒說服他,反正已經(jīng)安全上線而不了了之。
我正好在旁邊聽到了,要是兩年前我也許會一直提出問題參與辯論,申援同事。但筆者沒動,不是怕 PUA,而是表達(dá)能力太差,即使是對的,也說不好。其根本原因是筆者對這塊知識了解的不深刻,所以不敢說大話
按照理論知識,你 push 整個(gè) dist 文件,即使遠(yuǎn)程倉庫中有 dist,也不會把整個(gè) dist 文件夾替換,只會替換其中相同的數(shù)據(jù),而因?yàn)榇蛄?hash 值,所以 css 和 js 都是不同的,所以一直這樣做,dist 中的文件會越來越多,而因?yàn)?index.html 文件只有一個(gè),所以不會出現(xiàn)替換了還引用之前文件的問題,如果出現(xiàn),清除下瀏覽器的緩存就能解決
因?yàn)樯a(chǎn)環(huán)境和測試環(huán)境發(fā)布代碼流程不同,所以先要把環(huán)境配置成一致先
需要做的事情很簡單,把 nginx 中指向倉庫地址,到時(shí)候從遠(yuǎn)端拉下代碼即可
先修改 nginx 中的配置
server {
listen 7000;
# root /usr/share/nginx/html/dist
root /home/jingqb-web/dist
...
}
再檢查一下 nginx 配置是否 ok
nginx -t
接著重啟 nginx
nginx -s reload
接著把代碼提交到遠(yuǎn)端倉庫,再上服務(wù)器進(jìn)入 /home/jingqb-web 目錄下,git pull origin XX ,進(jìn)入 dist 文件,查看打包后的 js
原js的hash值
我們修改在項(xiàng)目中打印一些日志,表示文件改動,這樣 build 之后會打出不同 hash 的 js
git push origin XX
再次登錄服務(wù)器,進(jìn)入 /home/jingqb-web 目錄,再拉代碼git pull origin xx
再次提交后的代碼
發(fā)現(xiàn),umi.b0f5511b.js 被刪掉了,新生成的 umi.f8280c0e.js 在其中,dist 中是干凈的源文件,這是為什么呢?
你 build 之后,是先刪掉 dist 文件,生成的是一個(gè)干凈的 dist,然后我的操作是:
我的操作中沒有 pull 代碼,而是直接 push 代碼,這就意味著 dist 就是我本地的 dist,而非合并之后的
想想這種做法的缺點(diǎn)是多人開發(fā)時(shí),pull 別人的代碼后,merge 之后還要重新 build,才能再次提交
好險(xiǎn),還好沒有逞英雄
謹(jǐn)言慎行是一輩子的學(xué)問
這觸發(fā)了筆者對 git 的新認(rèn)知,結(jié)合平時(shí)經(jīng)驗(yàn),筆者覺得三個(gè)問題能測試別人對 git 的理解程度
面幾篇文章我們講到了跨站腳本(XSS)漏洞的幾種類型和驗(yàn)證方法以及防御措施,有興趣的朋友可以到我的主頁翻看文章《十大常見web漏洞——跨站腳本漏洞》和《實(shí)操web漏洞驗(yàn)證——跨站腳本漏洞》,今天我們繼續(xù)由易到難實(shí)戰(zhàn)演示一下跨站腳本漏洞的形成,以便更好地了解漏洞的產(chǎn)生原理,進(jìn)一步做好防御。
上一篇文章我們已經(jīng)闖過了5關(guān),今天我們繼續(xù)。
html事件是在滿足一定條件的用戶行為發(fā)生時(shí),所觸發(fā)的的事件,例如當(dāng)單擊鼠標(biāo)時(shí)的“onclick”以及當(dāng)瀏覽器加載圖像時(shí)的“onload”,我們可以將這些特定的html事件發(fā)生時(shí),將JavaScript語句作為屬性傳遞給特定的標(biāo)簽,從而構(gòu)成一個(gè)或多個(gè)JavaScript命令或函數(shù)。
下圖我們從網(wǎng)上搜索了一些html事件屬性,有興趣的可以自己搜索學(xué)習(xí)。
html事件屬性
在這一關(guān)中,我們可以構(gòu)造語句:
111" onmouseover="alert(document.domain);"
前邊的“111"”是為了閉合標(biāo)簽,后邊的“onmouseover”屬性表示當(dāng)鼠標(biāo)移動到輸入框時(shí)執(zhí)行后邊的語句,點(diǎn)擊“search”按鈕,將鼠標(biāo)移動到輸入框時(shí),頁面在彈出內(nèi)容為當(dāng)前頁面域名的彈窗后,提示“恭喜!”,就可以順利進(jìn)入下一關(guān)了,如下圖所示:
恭喜通關(guān)
這一關(guān)我們先來探測一下注入點(diǎn)的情況,我們和之前一樣先閉合標(biāo)簽,輸入“123456"”來閉合標(biāo)簽,找到對應(yīng)的代碼,發(fā)現(xiàn)我們輸入的內(nèi)容被另一對引號括住了,如下圖所示:
頁面代碼
這表明我們輸入的內(nèi)容直接被實(shí)體化了,那我們不使用引號閉合,直接輸入“123456 onmouseover=“alert(document.domain)””,發(fā)現(xiàn)只要是等號后邊的參數(shù)都被引號括了起來,如下圖所示:
頁面代碼
因此我們都不加引號,構(gòu)造:
123456 onmouseover=alert(document.domain)
注意中間有個(gè)空格,點(diǎn)擊“search”按鈕時(shí),頁面在彈出內(nèi)容為當(dāng)前頁面域名的彈窗后,提示“恭喜!”,就可以順利進(jìn)入下一關(guān)了,如下圖所示:
恭喜通關(guān)
有時(shí)候我們需要將JavaScript代碼添加到客戶端中,這時(shí)就需要JavaScript偽協(xié)議來幫助,它的格式為JavaScript:url,例如:JavaScript:alert("hello word!"),就是一個(gè)簡單的通過JavaScript偽協(xié)議來執(zhí)行alert("hello word!")語句,它表示在頁面顯示“hello word!”。
因此我們可以構(gòu)造語句
JavaScript:alert(document.domain);
點(diǎn)擊“Make a Link”按鈕時(shí),可見輸入框下邊出現(xiàn)一個(gè)URL超鏈接,我們點(diǎn)擊這個(gè)鏈接,如下圖所示:
URL超鏈接
頁面在彈出內(nèi)容為當(dāng)前頁面域名的彈窗后,提示“恭喜!”,就可以順利進(jìn)入下一關(guān)了,如下圖所示:
恭喜通關(guān)
這個(gè)比較簡單,因?yàn)閁TF-7絕大多數(shù)瀏覽器都已經(jīng)不用了,我們很少會遇到,因此我們直接構(gòu)造語句:
onclick=alert(document.domain);
我們按F12鍵,根據(jù)下圖提示找到第三步位置,將以上語句寫入到對應(yīng)位置,再點(diǎn)擊第二步的位置,如下圖所示:
修改頁面代碼
頁面在彈出內(nèi)容為當(dāng)前頁面域名的彈窗后,提示“恭喜!”,就可以順利進(jìn)入下一關(guān)了,如下圖所示:
恭喜通關(guān)
首先我們還是老辦法構(gòu)造閉合語句,如下所示:
"><script>alert(document.domain);</script>
點(diǎn)擊“search”,按F12,找到如下圖紅框中的位置,發(fā)現(xiàn)我們上邊構(gòu)造的語句中“domain”被刪除了,如下圖所示:
頁面代碼
既然被刪除了,這時(shí)我們可以通過雙寫來繞過domain被刪除這種情況,我們可以構(gòu)造:
"><script>alert(document.dodomainmain);</script>
注意我們在單詞domain中間又加了一個(gè)單詞domain,這時(shí)系統(tǒng)在刪除一個(gè)單詞domain后,還會留下一個(gè)domain,這樣我們就成功執(zhí)行了語句了。
點(diǎn)擊“search”按鈕時(shí),頁面在彈出內(nèi)容為當(dāng)前頁面域名的彈窗后,提示“恭喜!”,就可以順利進(jìn)入下一關(guān)了,如下圖所示:
恭喜通關(guān)
當(dāng)然我們也可以通過編碼的方法來繞過,我們可以構(gòu)造:
"><script>eval(atob('YWxlcnQoZG9jdW1lbnQuZG9kb21haW5tYWluKTs='));</script>
其中“eval”是用來執(zhí)行字符串,其后邊的內(nèi)容會當(dāng)成JavaScript語句執(zhí)行,“atob”表示將加密的base64密文,轉(zhuǎn)換成原文,而里邊的一串亂碼就是通過base64加密過的的“alert(document.domain)”語句,關(guān)于加密,有興趣的可以閱讀我的文章《Web滲透測試——密碼學(xué)基礎(chǔ)》,其實(shí)和上邊的語句一樣,這樣就可以避免domain被刪除了。
以上就是跨站腳本(XSS)漏洞實(shí)戰(zhàn)演示——由易到難第二部分的全部內(nèi)容,希望對你了解XSS漏洞有所幫助,歡迎關(guān)注@科技興了解更多科技尤其是網(wǎng)絡(luò)安全方面的資訊和知識。
正式學(xué)習(xí)網(wǎng)絡(luò)爬蟲之前,我們需要詳細(xì)了解 HTTP 的基本原理,了解在瀏覽器中敲入 URL 到獲取網(wǎng)頁內(nèi)容之間發(fā)生了什么。了解這些內(nèi)容,有助于我們進(jìn)一步了解爬蟲的基本原理。
在本節(jié)中,我們會詳細(xì)了解 HTTP 的基本原理,了解在瀏覽器中敲入 URL 到獲取網(wǎng)頁內(nèi)容之間發(fā)生了什么。了解這些內(nèi)容,有助于我們進(jìn)一步了解爬蟲的基本原理。
這里我們先了解一下 URI 和 URL。URI 的全稱為 Uniform Resource Identifier,即統(tǒng)一資源標(biāo)志符;而 URL 的全稱為 Universal Resource Locator,即統(tǒng)一資源定位符。舉例來說,github.com/favicon.ico 是一個(gè) URL,也是一個(gè) URI。即有這樣一個(gè)圖標(biāo)資源,我們用 URL/URI 來唯一指定了它的訪問方式,這其中包括了訪問協(xié)議 https、訪問路徑(即根目錄)和資源名稱 favicon.ico。通過這樣一個(gè)鏈接,我們便可以從互聯(lián)網(wǎng)上找到這個(gè)資源,這就是 URL/URI。
URL 是 URI 的子集,也就是說每個(gè) URL 都是 URI,但不是每個(gè) URI 都是 URL。那么,怎樣的 URI 不是 URL 呢?URI 還包括一個(gè)子類,叫作 URN,它的全稱為 Universal Resource Name,即統(tǒng)一資源名稱。URN 只命名資源而不指定如何定位資源,比如 urn:isbn:0451450523 指定了一本書的 ISBN,可以唯一標(biāo)識這本書,但是沒有指定到哪里定位這本書,這就是 URN。URL、URN 和 URI 的關(guān)系可以用圖 1-1 表示。
但是在目前的互聯(lián)網(wǎng),URN 使用得非常少,幾乎所有的 URI 都是 URL,所以對于一般的網(wǎng)頁鏈接,我們既可以稱之為 URL,也可以稱之為 URI,我個(gè)人習(xí)慣稱之為 URL。
但 URL 也不是隨便寫的,它也是需要遵循一定的格式規(guī)范的,基本的組成格式如下:
scheme://[username:password@]hostname[:port][/path][;parameters][?query][#fragment]
復(fù)制代碼
其中這些括號包括的內(nèi)容代表非必要部分,比如 www.baidu.com 這個(gè) URL,這里就只包含了 scheme 和 host 兩部分,其他的 port、path、parameters、query、fragment 都沒有。
這里我們分別介紹下幾部分代表的含義和作用:
以上我們就簡單了解了 URL 的基本概念和構(gòu)成,后文我們會結(jié)合多個(gè)實(shí)戰(zhàn)案例練習(xí)來幫助加深其理解。
剛才我們了解了 URL 的基本構(gòu)成,其支持的協(xié)議有很多,比如 http、https、ftp、sftp、smb 等等。
在爬蟲中,我們抓取的頁面通常基于 http 或 https 協(xié)議,這里首先我們先來了解一下這兩個(gè)協(xié)議的含義。
HTTP 的全稱是 Hyper Text Transfer Protocol,中文名叫作超文本傳輸協(xié)議。HTTP 協(xié)議是用于從網(wǎng)絡(luò)傳輸超文本數(shù)據(jù)到本地瀏覽器的傳送協(xié)議,它能保證高效而準(zhǔn)確地傳送超文本文檔。HTTP 由萬維網(wǎng)協(xié)會(World Wide Web Consortium)和 Internet 工作小組 IETF(Internet Engineering Task Force)共同合作制定的規(guī)范,目前廣泛使用的是 HTTP 1.1 版本,當(dāng)然 HTTP 2.0 現(xiàn)在不少網(wǎng)站也增加了支持。
其發(fā)展歷史見下表:
版本 | 產(chǎn)生時(shí)間 | 主要特點(diǎn) | 發(fā)展現(xiàn)狀 |
HTTP/0.9 | 1991 年 | 不涉及數(shù)據(jù)包傳輸,規(guī)定客戶端和服務(wù)器之間通信格式,只能 GET 請求 | 沒有作為正式的標(biāo)準(zhǔn) |
HTTP/1.0 | 1996 年 | 傳輸內(nèi)容格式不限制,增加 PUT、PATCH、HEAD、 OPTIONS、DELETE 命令 | 正式作為標(biāo)準(zhǔn) |
HTTP/1.1 | 1997 年 | 持久連接(長連接)、節(jié)約帶寬、HOST 域、管道機(jī)制、分塊傳輸編碼 | 正式作為標(biāo)準(zhǔn)并廣泛使用 |
HTTP/2.0 | 2015 年 | 多路復(fù)用、服務(wù)器推送、頭信息壓縮、二進(jìn)制協(xié)議等 | 逐漸覆蓋市場 |
HTTPS 的全稱是 Hyper Text Transfer Protocol over Secure Socket Layer,是以安全為目標(biāo)的 HTTP 通道,簡單講是 HTTP 的安全版,即在 HTTP 下加入 SSL 層,簡稱為 HTTPS。
HTTPS 的安全基礎(chǔ)是 SSL,因此通過它傳輸?shù)膬?nèi)容都是經(jīng)過 SSL 加密的,它的主要作用分為以下兩種。
現(xiàn)在越來越多的網(wǎng)站和 App 都已經(jīng)向 HTTPS 方向發(fā)展,舉例如下。
因此,HTTPS 已經(jīng)是大勢所趨。
注:HTTP 和 HTTPS 協(xié)議都屬于計(jì)算機(jī)網(wǎng)絡(luò)中的應(yīng)用層協(xié)議,其下層是基于 TCP 協(xié)議實(shí)現(xiàn)的,TCP 協(xié)議屬于計(jì)算機(jī)網(wǎng)絡(luò)中的傳輸層協(xié)議,包括建立連接時(shí)的三次握手和斷開時(shí)的四次揮手等過程。但本書主要講的是網(wǎng)絡(luò)爬蟲相關(guān),主要爬取的是 HTTP/HTTPS 協(xié)議相關(guān)的內(nèi)容,所以這里就不再展開深入講解 TCP、IP 等相關(guān)知識了,感興趣的讀者可以搜索相關(guān)資料了解下,如《計(jì)算機(jī)網(wǎng)絡(luò)》、《圖解 HTTP》等書籍。
我們在瀏覽器中輸入一個(gè) URL,回車之后便會在瀏覽器中觀察到頁面內(nèi)容。
實(shí)際上,這個(gè)過程是瀏覽器向網(wǎng)站所在的服務(wù)器發(fā)送了一個(gè)請求,網(wǎng)站服務(wù)器接收到這個(gè)請求后進(jìn)行處理和解析,然后返回對應(yīng)的響應(yīng),接著傳回給瀏覽器。
由于響應(yīng)里包含頁面的源代碼等內(nèi)容,瀏覽器再對其進(jìn)行解析,便將網(wǎng)頁呈現(xiàn)了出來,流程如圖 1-3 所示。
此處客戶端即代表我們自己的 PC 或手機(jī)瀏覽器,服務(wù)器即要訪問的網(wǎng)站所在的服務(wù)器。
為了更直觀地說明這個(gè)過程,這里用 Chrome 瀏覽器開發(fā)者模式下的 Network 監(jiān)聽組件來做下演示,它可以顯示訪問當(dāng)前請求網(wǎng)頁時(shí)發(fā)生的所有網(wǎng)絡(luò)請求和響應(yīng)。
打開 Chrome 瀏覽器,訪問百度 www.baidu.com/,這時(shí)候鼠標(biāo)右鍵并選擇“檢查”菜單(或直接按快捷鍵 F12),即可打開瀏覽器的開發(fā)者工具,如下圖所示:
我們切換到 Network 面板,然后重新刷新網(wǎng)頁,這時(shí)候就可以看到在 Network 面板下方出現(xiàn)了很多個(gè)條目,其中一個(gè)條目就代表一次發(fā)送請求和接收響應(yīng)的過程,如圖所示:
我們先觀察第一個(gè)網(wǎng)絡(luò)請求,即 www.baidu.com,其中各列的含義如下。
我們點(diǎn)擊這個(gè)條目,即可看到其更詳細(xì)的信息,如圖所示。
首先是 General 部分,其中 Request URL 為請求的 URL,Request Method 為請求的方法,Status Code 為響應(yīng)狀態(tài)碼,Remote Address 為遠(yuǎn)程服務(wù)器的地址和端口,Referrer Policy 為 Referrer 判別策略。
再繼續(xù)往下可以看到,有 Response Headers 和 Request Headers,它們分別代表響應(yīng)頭和請求頭。請求頭里帶有許多請求信息,例如瀏覽器標(biāo)識、Cookie、Host 等信息,這是請求的一部分,服務(wù)器會根據(jù)請求頭內(nèi)的信息判斷請求是否合法,進(jìn)而作出對應(yīng)的響應(yīng)。圖 1-5 中看到的 Response Headers 就是響應(yīng)的一部分,其中包含了服務(wù)器的類型、文檔類型、日期等信息,瀏覽器接收到響應(yīng)后,會解析響應(yīng)內(nèi)容,進(jìn)而呈現(xiàn)網(wǎng)頁內(nèi)容。
下面我們分別來介紹一下請求和響應(yīng)都包含哪些內(nèi)容。
請求,英文為 Request,由客戶端向服務(wù)器發(fā)出,可以分為 4 部分內(nèi)容:請求方法(Request Method)、請求的網(wǎng)址(Request URL)、請求頭(Request Headers)、請求體(Request Body)。
下面我們分別予以介紹。
請求方法,英文為 Request Method,用于標(biāo)識請求客戶端請求服務(wù)端的方式,常見的請求方法有兩種:GET 和 POST。
在瀏覽器中直接輸入 URL 并回車,這便發(fā)起了一個(gè) GET 請求,請求的參數(shù)會直接包含到 URL 里。例如,在百度中搜索 Python,這就是一個(gè) GET 請求,鏈接為 www.baidu.com/s?wd=Python,其中 URL 中包含了請求的 query 信息,這里的參數(shù) wd 表示要搜尋的關(guān)鍵字。POST 請求大多在表單提交時(shí)發(fā)起。比如,對于一個(gè)登錄表單,輸入用戶名和密碼后,點(diǎn)擊 “登錄” 按鈕,這通常會發(fā)起一個(gè) POST 請求,其數(shù)據(jù)通常以表單的形式傳輸,而不會體現(xiàn)在 URL 中。
GET 和 POST 請求方法有如下區(qū)別:
一般來說,登錄時(shí),需要提交用戶名和密碼,其中包含了敏感信息,使用 GET 方式請求的話,密碼就會暴露在 URL 里面,造成密碼泄露,所以這里最好以 POST 方式發(fā)送。上傳文件時(shí),由于文件內(nèi)容比較大,也會選用 POST 方式。
我們平常遇到的絕大部分請求都是 GET 或 POST 請求。另外,還有一些請求方法,如 GET、HEAD、POST、PUT、DELETE、CONNECT、OPTIONS、TRACE 等,我們簡單將其總結(jié)為下表。
方 法 | 描 述 |
GET | 請求頁面,并返回頁面內(nèi)容 |
HEAD | 類似于 GET 請求,只不過返回的響應(yīng)中沒有具體的內(nèi)容,用于獲取報(bào)頭 |
POST | 大多用于提交表單或上傳文件,數(shù)據(jù)包含在請求體中 |
PUT | 從客戶端向服務(wù)器傳送的數(shù)據(jù)取代指定文檔中的內(nèi)容 |
DELETE | 請求服務(wù)器刪除指定的頁面 |
CONNECT | 把服務(wù)器當(dāng)作跳板,讓服務(wù)器代替客戶端訪問其他網(wǎng)頁 |
OPTIONS | 允許客戶端查看服務(wù)器的性能 |
TRACE | 回顯服務(wù)器收到的請求,主要用于測試或診斷 |
本表參考:www.runoob.com/http/http-m…。
請求的網(wǎng)址,英文為 Reqeust URL,它可以唯一確定我們想請求的資源。關(guān)于 URL 的構(gòu)成和各個(gè)部分的功能我們在前文已經(jīng)提及到了,這里就不再贅述。
請求頭,英文為 Request Headers,用來說明服務(wù)器要使用的附加信息,比較重要的信息有 Cookie、Referer、User-Agent 等。
下面簡要說明一些常用的頭信息:
因此,請求頭是請求的重要組成部分,在寫爬蟲時(shí),大部分情況下都需要設(shè)定請求頭。
請求體,即 Request Body 一般承載的內(nèi)容是 POST 請求中的表單數(shù)據(jù),而對于 GET 請求,請求體則為空。
例如,這里我登錄 GitHub 時(shí)捕獲到的請求和響應(yīng)如圖 1-6 所示。
登錄之前,我們填寫了用戶名和密碼信息,提交時(shí)這些內(nèi)容就會以表單數(shù)據(jù)的形式提交給服務(wù)器,此時(shí)需要注意 Request Headers 中指定 Content-Type 為 application/x-www-form-urlencoded。只有設(shè)置 Content-Type 為 application/x-www-form-urlencoded,才會以表單數(shù)據(jù)的形式提交。另外,我們也可以將 Content-Type 設(shè)置為 application/json 來提交 JSON 數(shù)據(jù),或者設(shè)置為 multipart/form-data 來上傳文件。
如下表是 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ù) |
在爬蟲中,如果要構(gòu)造 POST 請求,需要使用正確的 Content-Type,并了解各種請求庫的各個(gè)參數(shù)設(shè)置時(shí)使用的是哪種 Content-Type,不然可能會導(dǎo)致 POST 提交后無法正常響應(yīng)。
響應(yīng),即 Response,由服務(wù)器返回給客戶端,可以分為三部分:響應(yīng)狀態(tài)碼(Response Status Code)、響應(yīng)頭(Response Headers)和響應(yīng)體(Response Body)。
響應(yīng)狀態(tài)碼,即 Response Status Code,表示服務(wù)器的響應(yīng)狀態(tài),如 200 代表服務(wù)器正常響應(yīng),404 代表頁面未找到,500 代表服務(wù)器內(nèi)部發(fā)生錯(cuò)誤。在爬蟲中,我們可以根據(jù)狀態(tài)碼來判斷服務(wù)器響應(yīng)狀態(tài),如狀態(tài)碼為 200,則證明成功返回?cái)?shù)據(jù),再進(jìn)行進(jìn)一步的處理,否則直接忽略。下表列出了常見的錯(cuò)誤代碼及錯(cuò)誤原因。
常見的錯(cuò)誤代碼及錯(cuò)誤原因
狀態(tài)碼 | 說 明 | 詳 情 |
100 | 繼續(xù) | 請求者應(yīng)當(dāng)繼續(xù)提出請求。服務(wù)器已收到請求的一部分,正在等待其余部分 |
101 | 切換協(xié)議 | 請求者已要求服務(wù)器切換協(xié)議,服務(wù)器已確認(rèn)并準(zhǔn)備切換 |
200 | 成功 | 服務(wù)器已成功處理了請求 |
201 | 已創(chuàng)建 | 請求成功并且服務(wù)器創(chuàng)建了新的資源 |
202 | 已接受 | 服務(wù)器已接受請求,但尚未處理 |
203 | 非授權(quán)信息 | 服務(wù)器已成功處理了請求,但返回的信息可能來自另一個(gè)源 |
204 | 無內(nèi)容 | 服務(wù)器成功處理了請求,但沒有返回任何內(nèi)容 |
205 | 重置內(nèi)容 | 服務(wù)器成功處理了請求,內(nèi)容被重置 |
206 | 部分內(nèi)容 | 服務(wù)器成功處理了部分請求 |
300 | 多種選擇 | 針對請求,服務(wù)器可執(zhí)行多種操作 |
301 | 永久移動 | 請求的網(wǎng)頁已永久移動到新位置,即永久重定向 |
302 | 臨時(shí)移動 | 請求的網(wǎng)頁暫時(shí)跳轉(zhuǎn)到其他頁面,即暫時(shí)重定向 |
303 | 查看其他位置 | 如果原來的請求是 POST,重定向目標(biāo)文檔應(yīng)該通過 GET 提取 |
304 | 未修改 | 此次請求返回的網(wǎng)頁未修改,繼續(xù)使用上次的資源 |
305 | 使用代理 | 請求者應(yīng)該使用代理訪問該網(wǎng)頁 |
307 | 臨時(shí)重定向 | 請求的資源臨時(shí)從其他位置響應(yīng) |
400 | 錯(cuò)誤請求 | 服務(wù)器無法解析該請求 |
401 | 未授權(quán) | 請求沒有進(jìn)行身份驗(yàn)證或驗(yàn)證未通過 |
403 | 禁止訪問 | 服務(wù)器拒絕此請求 |
404 | 未找到 | 服務(wù)器找不到請求的網(wǎng)頁 |
405 | 方法禁用 | 服務(wù)器禁用了請求中指定的方法 |
406 | 不接受 | 無法使用請求的內(nèi)容響應(yīng)請求的網(wǎng)頁 |
407 | 需要代理授權(quán) | 請求者需要使用代理授權(quán) |
408 | 請求超時(shí) | 服務(wù)器請求超時(shí) |
409 | 沖突 | 服務(wù)器在完成請求時(shí)發(fā)生沖突 |
410 | 已刪除 | 請求的資源已永久刪除 |
411 | 需要有效長度 | 服務(wù)器不接受不含有效內(nèi)容長度標(biāo)頭字段的請求 |
412 | 未滿足前提條件 | 服務(wù)器未滿足請求者在請求中設(shè)置的其中一個(gè)前提條件 |
413 | 請求實(shí)體過大 | 請求實(shí)體過大,超出服務(wù)器的處理能力 |
414 | 請求 URI 過長 | 請求網(wǎng)址過長,服務(wù)器無法處理 |
415 | 不支持類型 | 請求格式不被請求頁面支持 |
416 | 請求范圍不符 | 頁面無法提供請求的范圍 |
417 | 未滿足期望值 | 服務(wù)器未滿足期望請求標(biāo)頭字段的要求 |
500 | 服務(wù)器內(nèi)部錯(cuò)誤 | 服務(wù)器遇到錯(cuò)誤,無法完成請求 |
501 | 未實(shí)現(xiàn) | 服務(wù)器不具備完成請求的功能 |
502 | 錯(cuò)誤網(wǎng)關(guān) | 服務(wù)器作為網(wǎng)關(guān)或代理,從上游服務(wù)器收到無效響應(yīng) |
503 | 服務(wù)不可用 | 服務(wù)器目前無法使用 |
504 | 網(wǎng)關(guān)超時(shí) | 服務(wù)器作為網(wǎng)關(guān)或代理,但是沒有及時(shí)從上游服務(wù)器收到請求 |
505 | HTTP 版本不支持 | 服務(wù)器不支持請求中所用的 HTTP 協(xié)議版本 |
響應(yīng)頭,即 Response Headers,包含了服務(wù)器對請求的應(yīng)答信息,如 Content-Type、Server、Set-Cookie 等。下面簡要說明一些常用的頭信息。
響應(yīng)體,即 Response Body,這可以說是最關(guān)鍵的部分了,響應(yīng)的正文數(shù)據(jù)都在響應(yīng)體中,比如請求網(wǎng)頁時(shí),它的響應(yīng)體就是網(wǎng)頁的 HTML 代碼;請求一張圖片時(shí),它的響應(yīng)體就是圖片的二進(jìn)制數(shù)據(jù)。我們做爬蟲請求網(wǎng)頁后,要解析的內(nèi)容就是響應(yīng)體,如圖 1-7 所示。
在瀏覽器開發(fā)者工具中點(diǎn)擊 Preview,就可以看到網(wǎng)頁的源代碼,也就是響應(yīng)體的內(nèi)容,它是解析的目標(biāo)。
在做爬蟲時(shí),我們主要通過響應(yīng)體得到網(wǎng)頁的源代碼、JSON 數(shù)據(jù)等,然后從中做相應(yīng)內(nèi)容的提取。
本節(jié)中,我們了解了 HTTP 的基本原理,大概了解了訪問網(wǎng)頁時(shí)背后的請求和響應(yīng)過程。本節(jié)涉及的知識點(diǎn)需要好好掌握,后面分析網(wǎng)頁請求時(shí)會經(jīng)常用到。
前面我們也提到了 HTTP 協(xié)議從 2015 年起發(fā)布了 2.0 版本,相比 HTTP/1.1 來說,HTTP/2.0 變得更快、更簡單、更穩(wěn)定,HTTP/2.0 在傳輸層做了很多優(yōu)化,HTTP/2.0 的主要目標(biāo)是通過支持完整的請求與響應(yīng)復(fù)用來減少延遲,并通過有效壓縮 HTTP 請求頭字段將協(xié)議開銷降至最低,同時(shí)增加對請求優(yōu)先級和服務(wù)器推送的支持,這些優(yōu)化一筆勾銷了 HTTP/1.1 為做傳輸優(yōu)化想出的一系列“歪招”。
有讀者這時(shí)候可能會問,為什么不叫 HTTP/1.2 而叫 HTTP/2.0 呢?因?yàn)?HTTP/2.0 在內(nèi)部實(shí)現(xiàn)上新的二進(jìn)制分幀層,這是沒法與之前的 HTTP/1.x 的服務(wù)器和客戶端實(shí)現(xiàn)向后兼容的,所以直接修改了主版本號為 2.0。
下面我們就來了解下 HTTP/2.0 相比 HTTP/1.1 來說做了哪些優(yōu)化吧。
HTTP/2.0 所有性能增強(qiáng)的核心就在于這個(gè)新的二進(jìn)制分幀層。在 HTTP/1.x 中,不管是請求(Request)還是響應(yīng)(Response),它們都是用文本格式傳輸?shù)模漕^部(Headers)、實(shí)體(Body)之間也是用文本換行符分隔開的。HTTP/2.0 對其做了優(yōu)化,將文本格式修改為了二進(jìn)制格式,使得解析起來更加高效。同時(shí)將請求和響應(yīng)數(shù)據(jù)分割為更小的幀,并采用二進(jìn)制編碼。
所以這里就引入了幾個(gè)新的概念:
在 HTTP/2.0 中,同域名下的所有通信都可以在單個(gè)連接上完成,該連接可以承載任意數(shù)量的雙向數(shù)據(jù)流,數(shù)據(jù)流是用于承載雙向消息的,每條消息都是一條邏輯 HTTP 消息(例如請求或響應(yīng)),它可以包含一個(gè)或多個(gè)幀。
簡而言之,HTTP/2.0 將 HTTP 協(xié)議通信分解為二進(jìn)制編碼幀的交換,這些幀對應(yīng)著特定數(shù)據(jù)流中的消息,所有這些都在一個(gè) TCP 連接內(nèi)復(fù)用,這是 HTTP/2.0 協(xié)議所有其他功能和性能優(yōu)化的基礎(chǔ)。
在 HTTP/1.x 中,如果客戶端要想發(fā)起多個(gè)并行請求以提升性能,則必須使用多個(gè) TCP 連接,而且瀏覽器位了控制資源,還會對單個(gè)域名有 6-8 個(gè) TCP 連接請求的限制。但在 HTTP/2.0 中,由于又了二進(jìn)制分幀技術(shù)的加持,HTTP/2.0 不用再以來 TCP 連接去實(shí)現(xiàn)多路并行了,客戶端和服務(wù)器可以將 HTTP 消息分解為互不依賴的幀,然后交錯(cuò)發(fā)送,最后再在另一端把它們重新組裝起來,讓我們可以:
這樣以來,整個(gè)數(shù)據(jù)傳輸使性能就有了極大提升:
流控制是一種阻止發(fā)送方向接收方發(fā)送大量數(shù)據(jù)的機(jī)制,以免超出后者的需求或處理能力。可以理解為,接收方已經(jīng)太繁忙了,來不及處理收到的消息了,但是發(fā)送方還在一直大量發(fā)送消息,這樣就會出現(xiàn)一些問題。
比如說,客戶端可能請求了一個(gè)具有較高優(yōu)先級的大型視頻流,但是用戶已經(jīng)暫停視頻,客戶端現(xiàn)在希望暫停或限制從服務(wù)器的傳輸,以免提取和緩沖不必要的數(shù)據(jù)。 再比如,一個(gè)代理服務(wù)器可能具有較快的下游連接和較慢的上游連接,并且也希望調(diào)節(jié)下游連接傳輸數(shù)據(jù)的速度以匹配上游連接的速度來控制其資源利用率等等。
由于 HTTP 是基于 TCP 實(shí)現(xiàn)的,雖然 TCP 原生有流量控制機(jī)制,但是由于 HTTP/2.0 數(shù)據(jù)流在一個(gè) TCP 連接內(nèi)復(fù)用,TCP 流控制既不夠精細(xì),也無法提供必要的應(yīng)用級 API 來調(diào)節(jié)各個(gè)數(shù)據(jù)流的傳輸。
為了解決這一問題,HTTP/2.0 提供了一組簡單的構(gòu)建塊,這些構(gòu)建塊允許客戶端和服務(wù)器實(shí)現(xiàn)其自己的數(shù)據(jù)流和連接級流控制:
由此可見,HTTP/2.0 提供了簡單的構(gòu)建塊實(shí)現(xiàn)了自定義策略來調(diào)節(jié)資源使用和分配,以及實(shí)現(xiàn)新傳輸能力,同時(shí)提升了網(wǎng)頁應(yīng)用的實(shí)際性能和感知性能。
HTTP/2.0 新增的另一個(gè)強(qiáng)大的新功能是,服務(wù)器可以對一個(gè)客戶端請求發(fā)送多個(gè)響應(yīng)。 換句話說,除了對最初請求的響應(yīng)外,服務(wù)器還可以向客戶端推送額外資源,而無需客戶端明確地請求。
如果某些資源客戶端是一定會請求的,這時(shí)就可以采取服務(wù)端推送的技術(shù),在客戶端發(fā)起一次請求后,額外提前給客戶端推送必要的資源,這樣就可以相對減少一點(diǎn)延遲時(shí)間。例如,服務(wù)端可以主動把 JS 和 CSS 文件推送給客戶端,而不需要客戶端解析 HTML 時(shí)再發(fā)送這些請求。
服務(wù)端可以主動推送,當(dāng)然客戶端也有權(quán)利選擇是否接收。如果服務(wù)端推送的資源已經(jīng)被瀏覽器緩存過,瀏覽器可以通過發(fā)送 RST_STREAM 幀來拒收。
另外主動推送也遵守同源策略,即服務(wù)器不能隨便將第三方資源推送給客戶端,而必須是經(jīng)過雙方確認(rèn)才行,這樣也能保證一定的安全性。
HTTP/2.0 的普及是一件任重而道遠(yuǎn)的事情,一些主流的網(wǎng)站現(xiàn)在已經(jīng)支持了 HTTP/2.0,主流瀏覽器現(xiàn)在都已經(jīng)實(shí)現(xiàn)了 HTTP/2.0 的支持,但總的來看,目前大部分網(wǎng)站依然還是以 HTTP/1.1 為主。
另外一些編程語言的庫還沒有完全支持 HTTP/2.0,比如對于 Python 來說,hyper、httpx 等庫已經(jīng)支持了 HTTP/2.0,但廣泛使用的 requests 庫依然還是只支持 HTTP/1.1。
本節(jié)介紹了關(guān)于 HTTP 的一些基礎(chǔ)知識,內(nèi)容不少,需要好好掌握,這些知識對于后面我們編寫和理解網(wǎng)絡(luò)爬蟲具有非常大的幫助。
由于本節(jié)的內(nèi)容多數(shù)為概念介紹,內(nèi)容參考了很多書籍、文檔、博客,來源如下:
更多精彩內(nèi)容,請關(guān)注我的公眾號「進(jìn)擊的 Coder」和「崔慶才丨靜覓」。
作者:崔慶才丨靜覓
鏈接:https://juejin.cn/post/7081288652034146312
*請認(rèn)真填寫需求信息,我們會在24小時(shí)內(nèi)與您取得聯(lián)系。