Maison >développement back-end >Tutoriel Python >Utilisez le socket Python pour envoyer la méthode de requête http(s)

Utilisez le socket Python pour envoyer la méthode de requête http(s)

不言
不言original
2018-05-07 11:54:244378parcourir

Cet article vous présente principalement les informations pertinentes sur l'utilisation des sockets python pour envoyer des requêtes http(s). L'article le présente en détail à travers des exemples de codes. Il a une certaine valeur d'apprentissage de référence pour que tout le monde puisse l'apprendre ou l'utiliser. est nécessaire Les amis, jetons un coup d'œil ensemble

Avant-propos

C'est un problème que j'ai rencontré lorsque j'écrivais un cours sur les réseaux informatiques design. Je suis resté coincé. J'ai un jour, donc pour résumer.

En fait, j'ai déjà écrit un robot d'exploration Python utilisant des requêtes, mais le réseau informatique nécessite une implémentation de niveau inférieur. Je viens de voir [cet article]1 et j'ai découvert qu'il utilisait des sockets pour implémenter les requêtes, alors j'ai appris.

Je pensais que ça ne devrait pas être difficile au début, après tout, c'est juste pour établir une connexion TCP.

Un exemple du site Web original est le suivant :

 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)

Le site Web que j'ai choisi d'explorer est Lianjia, bien sûr. Après avoir lu de nombreux autres exemples, j'ai également utilisé fiddler pour capturer les paquets et mettre les en-têtes entiers. Tout d'abord, j'ai fait référence à cet article : https://segmentfault.com/a/1190000005126160, qui présentait :

.

Python Envoi de requêtes http via socket

Nous prenons comme exemple la visite de la page d'accueil de Baidu et utilisons socket pour envoyer des requêtes http.

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)

La programmation http basée sur socket est que les paramètres de requête sont plus contrôlables, mais la difficulté est d'autant plus grande. Les données envoyées ci-dessus sont copiées directement à partir du capteur de paquets Fiddler.

Sur la base de ce qui précède, écrivez le code suivant :

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
''')

Le résultat est toujours signalé comme 400(Bad Request). est bloqué depuis longtemps. Enfin, la solution est de les envoyer un par un, en ajoutant rn après chacun.

 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())

Le résultat est toujours redirigé avec le code de statut 301 ! Je le cherche depuis longtemps mais je n'en connais toujours pas la raison. De plus, j'ai directement saisi l'URL dans la barre d'URL du navigateur et j'ai utilisé fiddler pour capturer les paquets, mais je n'ai toujours pas capturé les paquets avec. statut 301. Enfin, utilisez le compositeur du violoniste pour saisir http://zh.lianjia.com/ershoufang et attraper 301 et 200. L'adresse de 200 est https://zh.lianjia.com/ershoufang, comme indiqué dans la figure ci-dessous.

Maintenant je connais la raison, c'est la différence entre http et https. (En fait, l'emplacement dans la partie réponse peut être observé dans le code d'état 301, mais le s est trop discret, donc je ne l'ai pas remarqué, ce qui l'a fait rester longtemps bloqué)

La prochaine étape consiste simplement à savoir comment envoyer une requête https . Voici le code qui modifie principalement la partie qui établit le socket et se connecte. Notez que le numéro de port est 443. L'article de référence est ici

 sock = ssl.wrap_socket(socket.socket())
 sock.connect(('zh.lianjia.com', 443))

J'ai l'impression de ne pas le comprendre assez profondément à de nombreux endroits, et l'école n'a pas encore parlé du couche applicative. Je l'étudierai à nouveau le moment venu et je vous prierai de signaler toute erreur ou omission.

Recommandations associées :

Exemple d'utilisation de python pour générer un pdf en txt

Utilisation de python pour exécuter des scripts shell et dynamiquement les transférer Impliqué dans l'utilisation de base du sous-processus

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn