Home >Backend Development >Python Tutorial >Use python socket to send http(s) request method
This article mainly introduces you to the relevant information about using python sockets to send http(s) requests. The article introduces it in great detail through sample codes. It has certain reference learning value for everyone to learn or use python. It is needed Friends, let’s take a look together
Preface
This is a problem I encountered when I was writing a computer network course design, and it got stuck. I have a day, so to summarize.
In fact, I have written a python crawler using requests before, but the computer network requires a lower-level implementation. I just happened to see [this article]1 and found that he used sockets to implement requests, so I learned .
I originally thought it shouldn’t be difficult, after all, it is just to establish a tcp connection.
The example of the original website is as follows:
def fetch(url): sock = socket.socket() # 建立socket sock.connect(('xkcd.com', 80)) # 远程连接 request = 'GET {} HTTP/1.0\r\nHost: xkcd.com\r\n\r\n'.format(url) # 构建请求 sock.send(request.encode('ascii')) # 向socket发送数据 response = b'' chunk = sock.recv(4096) # 从socket接收数据 while chunk: response += chunk chunk = sock.recv(4096) # Page is now downloaded. links = parse_links(response) q.add(links)
The website I chose to crawl is Lianjia, and of course I also read it In many other examples, fiddler is also used to capture packets and put the entire headers. First, refer to this article: https://segmentfault.com/a/1190000005126160. The article introduces:
Python through socket Send http request
We take visiting Baidu homepage as an example and use socket to send http request.
import socket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect(('www.baidu.com',80)) s.send('''GET https://www.baidu.com/ HTTP/1.1 Host: www.baidu.com Connection: keep-alive Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36 Accept-Language: zh-CN,zh;q=0.8 ''') buf=s.recv(1024) while len(buf): print buf buf = s.recv(1024)
http programming based on socket has better controllability of request parameters, but the difficulty is correspondingly greater. The data sent above is copied directly from the fiddler packet capturer.
Based on the above, write the following code:
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect(('www.baidu.com',80)) s.send('''GET / HTTP/1.1 Host: zh.lianjia.com Connection: keep-alive Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Referer: https://www.baidu.com/link?url=4J5Kx--GLdLFESJhkfRePU8Ac_0agnTcOtB-b3kfnX8VNdZ_6TPqOyJGKVXkTczg&ck=6140.3.83.296.315.287.208.155&shh=www.baidu.com&sht=94886267_hao_pg&wd=&eqid=af98b98700060b77000000065aef0524 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en-CA;q=0.8,en;q=0.7 Cookie: lianjia_uuid=ce61c41c-25b0-46d6-a0a0-d57a75ee8706; UM_distinctid=1631f588055f9-0286722badd3ec-b34356b-1fa400-1631f58805657f; _ga=GA1.2.43397143.1525239286; _smt_uid=5ae94e02.558be516; _jzqx=1.1525248800.1525335927.1.jzqsr=zh%2Elianjia%2Ecom|jzqct=/ershoufang/xiangzhouqu/.-; _jzqc=1; _jzqckmp=1; _gid=GA1.2.1028411676.1525594529; select_city=440400; all-lj=c60bf575348a3bc08fb27ee73be8c666; _qzjc=1; CNZZDATA1254525948=963210960-1525238218-https%253A%252F%252Fwww.lianjia.com%252F%7C1525608956; CNZZDATA1255633284=1054798284-1525238580-https%253A%252F%252Fwww.lianjia.com%252F%7C1525608969; lianjia_ssid=c046ddb3-3e66-4809-998a-52ade335fdfc; _qzja=1.1070225156.1525239298260.1525603274282.1525613866775.1525609113492.1525613866775.0.0.0.92.9; _qzjto=29.3.0; _jzqa=1.3750161754444366000.1525239284.1525603274.1525613867.9; _jzqy=1.1525239284.1525613867.3.jzqsr=baidu.jzqsr=baidu; Hm_lvt_9152f8221cb6243a53c83b956842be8a=1525607433,1525607626,1525609113,1525613867; Hm_lpvt_9152f8221cb6243a53c83b956842be8a=1525613867; _qzjb=1.1525613866775.1.0.0.0; _jzqb=1.1.10.1525613867.1; CNZZDATA1255604082=964175865-1525237915-https%253A%252F%252Fwww.lianjia.com%252F%7C1525612833 ''')
The result is always reported 400 (Bad Request)
, this The place was stuck for a long time, and the final solution was to send them one by one, adding \r\n after each one.
sock = socket.socket() sock.connect(('zh.lianjia.com', 80)) sock.send('GET /ershoufang/ HTTP/1.1\r\n'.encode()) sock.send('Host: zh.lianjia.com\r\n'.encode()) sock.send('Connection: keep-alive\r\n'.encode()) sock.send('Cache-Control: no-cache\r\n'.encode()) sock.send('Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n'.encode()) sock.send('Upgrade-Insecure-Requests: 1\r\n'.encode()) sock.send('User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36\r\n'.encode()) sock.send('Accept-Encoding: gzip, deflate, br\r\n'.encode()) sock.send('Cookie: lianjia_uuid=ce61c41c-25b0-46d6-a0a0-d57a75ee8706; UM_distinctid=1631f588055f9-0286722badd3ec-b34356b-1fa400-1631f58805657f; _ga=GA1.2.43397143.1525239286; _smt_uid=5ae94e02.558be516; _jzqx=1.1525248800.1525335927.1.jzqsr=zh%2Elianjia%2Ecom|jzqct=/ershoufang/xiangzhouqu/.-; _jzqc=1; _jzqy=1.1525239284.1525594526.2.jzqsr=baidu.jzqsr=baidu|jzqct=%E9%93%BE%E5%AE%B6; _jzqckmp=1; _gid=GA1.2.1028411676.1525594529; Hm_lvt_9152f8221cb6243a53c83b956842be8a=1525594526,1525594536,1525594804,1525595210; select_city=440400; all-lj=c60bf575348a3bc08fb27ee73be8c666; _qzjc=1; lianjia_ssid=99306d63-8ee5-a53c-a740-2d3021f3db2f; CNZZDATA1255604082=964175865-1525237915-https%253A%252F%252Fwww.lianjia.com%252F%7C1525602095; _jzqa=1.3750161754444366000.1525239284.1525594526.1525603274.8; CNZZDATA1254525948=963210960-1525238218-https%253A%252F%252Fwww.lianjia.com%252F%7C1525603556; CNZZDATA1255633284=1054798284-1525238580-https%253A%252F%252Fwww.lianjia.com%252F%7C1525603557; Hm_lpvt_9152f8221cb6243a53c83b956842be8a=1525606057; _jzqb=1.9.10.1525603274.1; _qzja=1.1070225156.1525239298260.1525597069547.1525603274282.1525605398368.1525606071025.0.0.0.86.8; _qzjb=1.1525603274282.9.0.0.0; _qzjto=23.2.0\r\n\r\n'.encode())
The result is always redirected, status code 301! I have been looking for it for a long time but I still don’t know the reason. Moreover, I directly entered the URL in the browser URL bar and used fiddler to capture the packets, but I still didn’t capture the packets with status 301. Finally, use fiddler's composer to enter http://zh.lianjia.com/ershoufang and catch 301 and 200. The address of 200 is https://zh.lianjia.com/ershoufang, as shown in the figure below.
Now I know the reason, it is the difference between http and https. (Actually, the Location in the response part can be observed in the 301 status code, but the s is too inconspicuous, so I didn't notice it, which caused it to be stuck for a long time)
The next step is just to know how to send an https request. . The following is the code, which mainly changes the part that establishes the socket and connects. Note that the port number is 443. The reference article is here
sock = ssl.wrap_socket(socket.socket()) sock.connect(('zh.lianjia.com', 443))
I feel that I don’t understand many places deeply enough, and the school has not talked about the application layer for the time being. I will study it again when the time comes, and please point out any mistakes or omissions.
Related recommendations:
Example of using python to output pdf to txt
The above is the detailed content of Use python socket to send http(s) request method. For more information, please follow other related articles on the PHP Chinese website!