Maison >développement back-end >Tutoriel Python >Utilisez le socket Python pour envoyer la méthode de requête http(s)
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
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!