socket模擬發送http請求
嗨,小夥伴們,好久不見~~~,最近博主在研究socket編程,覺得socket真的好強大。之前一直我們都是在介紹爬蟲的requests、urllib等庫,我們知道它們都是基於HTTP協議來實現的,但從來沒有講過這個是如何實現的。今天要是講的話,一時半會也說不清楚,最重要的是,我怕自己講不明白。這樣大家就變的更糊塗,所以我就不講了。今天要說的是如何基於socket來發送http請求。
大家都知道,osi有七層模型,但是我們的TCP/IP協議其實並不是完全符合這個模型的。但是有些東西兩者都具有的,我們這裏簡要說一下傳輸層和應用層。
我們知道這個傳輸層是TCP和UTP協議,應用層則是我們經常使用的HTTP、SMTP、FTP等協議。應用層的那些協議都是基於傳輸層協議來的,都是爲了實現特定的功能而進行封裝的。那麼大家就要問了,這個socket是什麼,在哪裏呢?往下看:
原來在這裏啊,Socket它是應用層與傳輸層(TCP/IP協議族)通信的中間軟件抽象層,我們可以認爲它是一組接口(api)。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來說,一組簡單的接口就是全部,讓Socket去組織數據,以符合指定的協議。我們可以利用Socket來模擬HTTP請求,從而實現僞HTTP協議的目的。
我們以get方式來請求百度首頁爲例,利用Socket來模擬發送HTTP請求。
我們可以直接仿照瀏覽器的請求頭部信息去發送請求,當然也可以通過urllib提供的urlparse方法來對url進行修改,然後通過傳遞參數的方式來發送信息,相關的代碼如下:
# /usr/bin/python # -*- coding:utf-8 -*- # @author: Envse # @file: socket_http.py # @time: 2018/10/03 16:06 # requests -->urllib -->socket import socket from urllib.parse import urlparse def get_url(url): # 通過socket請求Url url = urlparse(url) host = url.netloc path = url.path if path == "": path = "/" # 建立socket連接 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((host, 80)) client.send("GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n".format(path, host).encode('utf8'))# 相對路徑 data = b"" while True: d = client.recv(1024) if d: data += d else: break data = data.decode('utf8') html_data = data.split("\r\n\r\n")[1] print(html_data) client.close() if __name__ == '__main__': get_url("http://www.baidu.com/")
這段代碼其實很好理解,就是模擬客戶端向服務器發送請求。首先通過get_url方法來將我們需要模擬的url進行處理,然後建立socket連接,發送內容,最後接收響應內容並將其進行輸出,關閉連接,是不是很簡單呢。運行結果:
再來看看通過瀏覽器查看的百度首頁的源碼,是不是差不多:
之所以出現有些差別是因爲瀏覽器是基於HTTP協議的,而且進行了一些字更深層次的封裝。不知道今年這篇文章您看明白沒有,如果沒有,我哪天再來研究一下。