<button id="2ddn7"><acronym id="2ddn7"></acronym></button>

<button id="2ddn7"><acronym id="2ddn7"></acronym></button>

  • <button id="2ddn7"><object id="2ddn7"></object></button>
      1. <s id="2ddn7"></s>
        更多課程 選擇中心


        Python培訓

        400-111-8989

        不完整的Http讀取和Python中Requests庫中的彩蛋

        • 發布:xiaocai
        • 來源:Python程序員
        • 時間:2018-05-02 14:56

        今天我們python培訓就談不完整的Http讀取和python中Requests庫中的彩蛋。requests庫可以說是Python中使用最廣泛的HTTP庫了。但是大多數用戶也許不知道requests當前穩定版本接受長度小于Content-Length頭所給出的長度的響應。如果不仔細檢查的話,可能在不經意間就使用了損壞的數據。現在告訴你這一點不知道算不算是彩蛋?為了讓大家避免同樣的問題,所以寫下這篇文章告訴大家。今天就讓我們看看為什么當前requests版本沒有做這個檢查,和如何在你的腳本中進行手動檢查。

        在正式開始本文的介紹之前,先給大家一個彩蛋:你了解python知識,就基本玩過爬蟲吧,玩爬蟲你也一定會用requests庫,這個庫的作者是大名鼎鼎的Kenneth Reitz 。很厲害的網站,發現他又出新招,變成一個把爬蟲下載器和解析器聯合在一起的庫。這個庫直接內置了html網頁的解析,相當于是自帶酒水,非常方便,號稱是給人類用的網頁解析庫。我們只需要用pip 直接install 即可。pip install requests-html ,這個庫它內置了requests庫,pyquery庫,bs庫,還有一些編碼的庫。最厲害的是,它能把隨機代理庫fake-useragent也集成進來了。關于requests庫,如果你還想了解更多,歡迎咨詢達內python培訓機構!接下來,我們來看我們今天的重點知識:

        什么是Content-Length頭?

        在HTTP協議中,Content-Length頭說明了請求或響應體的長度。它以8位字節給出,其中1個8位字節是8位。為了簡單起見,通篇文章我將使用術語字節而不是8位字節。通常,Content-Length頭用于通知接收方當前請求(或響應)何時完成。沒有它的話,你不知道你是否接收到了所有的數據或者你不知道是否有更多的數據需要讀取。當然,服務器可以在每個請求或響應結束后斷開連接(HTTP1.0就是這樣的),但是到了HTTP1.1,除非另有聲明所有的連接都被視為持續性的。這顯著地加快了通信速度,因為你無需為每個請求單獨打開一個連接。

        在閱讀完上述段落之后,下面的問題可能會出現在你的腦海中:

        如果我收到Content-Length的值比收到的字節數少會發生什么?

        在某些情況下(網絡或服務器端錯誤),服務器可能會在發送完整消息之前突然斷開連接。HTTP1.1 RFC指出:

        當允許消息體的消息中給出Content-Length時,其字段值必須與消息體中的字節數完全匹配。當接收并檢測到無效長度時,HTTP1.1用戶代理必須通知用戶。

        因此,一旦接收到比Content-Length頭部中規定的更少的字節,人們希望能收到通知。為了檢查這一點,我啟動一個簡單的HTTP服務器,它總是返回下面的響應,然后斷開連接:

        不完整的Http讀取和Python中的Requests庫

        然后,我編寫了一個Python腳本,它向服務器發送GET請求,檢查它是否成功,并打印接收到的數據:

        不完整的Http讀取和Python中的Requests庫

        當你運行它時,它成功了,而且不會引發異常:

        不完整的Http讀取和Python中的Requests庫

        那么,這難道就是所有客戶端的行為方式嗎?為了確定,我使用curl進行嘗試:

        不完整的Http讀取和Python中的Requests庫

        為了找到答案,我使用了reqwest,它是Rust的HTTP庫。我的測試客戶端的完整實現可以在這里找到。當我運行它時,它也提示我這種差異:

        不完整的Http讀取和Python中的Requests庫

        requests在這里發生一些可疑的事情...

        為什么requests庫不警告我?

        當你搜索requests庫時,您會發現大量令人驚訝的issues。

        基本上,沒有將這種檢查納入requests庫的原因有三:

        1.首先,我認為requests在技術上不是user-agent,而是庫。這使我們擺脫了user-agent行為的一些限制(事實上,我們在庫的其他地方采取了這種自由,就像我們對重定向的行為一樣)。

        那么,如果它不是user-agent,為什么默認情況下會發送以下User-Agent頭?

        不完整的Http讀取和Python中的Requests庫

        2.其次,如果我們拋出異常,我們不可改變地破壞我們讀取的數據。它變得不可能訪問。這意味著,用戶如果想要在不知情的情況下,盡可能多地讀取和保存數據,將變得困難。

        這很好理解。但是,這應該是默認行為嗎?我認為這應該作為一個可選項,requests會默認提醒你,但你應該可以禁止這個警告并使用你能夠讀取的數據。

        3.最后,即使我們確實需要這個功能,我們也需要在urllib3中實現它。Content-Length是指消息體傳輸的字節數,而不是解碼的長度,所以如果我們得到一個gzip(或DEFLATEd)響應,我們需要知道在解碼之前有多少字節。這通常不是我們在requests庫級別獲得的信息。所以如果你仍然對這種行為感興趣,我建議你在shazow / urllib3上打開一個issues。

        urllib3是requests底層的http庫。最初的發帖人在這里提交了一個issue。雖然有意愿提交PR,但是后來被關閉了。幸運的是,一年半后,提交了這樣一個PR并且被接受了。

        在閱讀了上面的第三點之后,您可能會開始高興。不好的一面是,即使urllib3 PR在2016年8月29日合并,當前穩定版本的requests(撰寫時為2.18.4,即2018-04-22)仍然使用舊版本的urllib3,它不提供這個功能。好的一面是,requests庫已經合并了新版本的urllib3,只不過是合并到了requests:proposed/3.0.0分支上。

        那么,我能做些什么來檢測腳本中的不完整讀取?

        不完整的Http讀取和Python中的Requests庫

        requests 3.x

        如果你看到這篇文章時,已經發布了requests 3.x,只需使用requests 3.x。它應該提供enforce_content_length參數,其默認值應該為True。也就是說,如果requests庫收到一個不完整的內容,它應該引發一個異常:

        不完整的Http讀取和Python中的Requests庫

        requests 2.x

        如果你使用的是requests2.x,你必須自己檢查。你可以使用下面的一段代碼:

        檢查工作如下。首先,我們確保響應具有Content-Length頭。如果沒有,檢查是毫無意義的。然后,我們得到實際讀取的字節數,并將其與預期值進行比較。如果我們讀取了更少的字節,我們會發出錯誤信號。當然,不要拋出異常,你可以做任何你想做的事情(重試,打印錯誤信息并退出,向朋友抱怨等)。

        需要驗證的話,你可以運行content-length.py HTTP服務器并通過client-with-check.py發送請求。服務器的寫入方式使其返回的字節數少于響應的Content-Length頭中所述的字節數。

        被壓縮的響應會怎么樣?

        響應可以被壓縮。例如,服務器可能會返回Content-Encoding頭設置為gzip的響應。這意味著響應體通過Lempel-Ziv編碼(LZ77)進行壓縮。當requests庫收到這樣的響應時,它會自動解壓縮它。當你再檢查response.content的長度(未壓縮響應的字節數)時,它很可能與Content-Length頭中指定的長度不同。這是我們沒有使用len(response.content)來獲取上述檢查中響應的實際長度的原因。相反,我們必須使用response.raw.tell(),它返回讀取的字節的實際數量(在解壓縮之前)。

        要驗證的話,你可以運行content-encoding-gzip.py HTTP服務器并通過client-with-check.py發送請求。服務器的寫入方式使其返回的字節數少于響應的Content-Length頭中所述的字節數。

        如果存在Transfer-Encoding:chunked?

        另外,Content-Length頭可以省略,可以使用chunked的Transfer-Encoding頭。這種流式數據傳輸自HTTP 1.1起可用,通過將響應拆分為塊。響應體具有以下形式:

        不完整的Http讀取和Python中的Requests庫

        這與Content-Length相比有幾個優點,包括為動態生成的內容維護一個持久的HTTP連接的能力,這些動態生成的內容的完整大小事先是未知的。

        當我們處理沒有Content-Length頭的分塊傳輸時,我們應該如何檢查是否收到了所有數據?幸運的是,在這種情況下,requests庫按預期工作。也就是說,如果服務器發送不完整的數據,該庫會引發異常。

        不完整的Http讀取和Python中的Requests庫

        要驗證的話,你可以運行transfer-encoding-chunked.py HTTP服務器并通過client.py發送請求。服務器的寫入方式使其返回的字節數少于塊大小中所述的字節數。

        建議

        始終驗證你收到的數據是否正確。驗證你已讀取的字節數是第一步。例如,下載散列(例如SHA-256)已知的文件時,應檢查下載文件的散列是否匹配。否則,您可能會冒險處理損壞的數據,這可能會導致惡意錯誤。

        恭喜你閱讀完了本文,知道了requests庫最近的新動向,也知道了不完整的Http讀取和Python中的Requests庫,收獲到了今天的彩蛋!相信以后碰到類似的問題,你將游刃有余,如果你還有更多關于python的問題,歡迎到達內python培訓班進行學習了解!

        免責聲明:內容和圖片源自網絡,版權歸原作者所有,如有侵犯您的原創版權請告知,我們將盡快刪除相關內容。

        預約申請免費試聽課

        填寫下面表單即可預約申請免費試聽!怕錢不夠?可就業掙錢后再付學費! 怕學不會?助教全程陪讀,隨時解惑!擔心就業?一地學習,可全國推薦就業!

        上一篇:python語言中不能忽略的else用法
        下一篇:python培訓干貨分享|14張涵蓋 Python 編程的核心知識的思維導圖

        如何運用Python編程處理大數據?用Python編程處理大數據的技巧是什么?

        Python面向對象編程的知識點都在這了!

        Python的高級特征及用法(部分)

        聽說這些Python知識,很少有人知道!

        • 掃碼領取資料

          回復關鍵字:視頻資料

          免費領取 達內課程視頻學習資料

        • 視頻學習QQ群

          添加QQ群:1143617948

          免費領取達內課程視頻學習資料

        Copyright ? 2021 Tedu.cn All Rights Reserved 京ICP備08000853號-56 京公網安備 11010802029508號 達內時代科技集團有限公司 版權所有

        選擇城市和中心
        黑龍江省

        吉林省

        河北省

        湖南省

        貴州省

        云南省

        廣西省

        海南省

        青青青草网站免费观看|青青青视频在线观看 超真实强奷视频在线看 百度 好搜 搜狗
        <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>