利用python的socket发送http(s)请求方法示例


Posted in Python onMay 07, 2018

前言

这是个在写计算机网络课设的时候碰到的问题,卡了我一天,所以总结一下。

其实在之前就有用requests写过python爬虫,但是计算机网络要求更底层的实现,刚好我看到了[这篇文章]1结果发现他就是用socket来实现的请求,所以就学习了。

本来也觉得应该不难,毕竟就是建立tcp连接。

原网站的例子如下:

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)

我选择爬取的网站是链家,当然也看了很多其他例子,还用fiddler抓包,把headers整个放了上去,首先是参考了这个文章:https://segmentfault.com/a/1190000005126160 ,该文章介绍到:

Python通过socket发送http请求

我们以访问百度主页为案例,使用socket发送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)

基于socket进行http编程在于请求参数的可控性更好,但是难度相应就更大了。以上发送的数据是直接从fiddler抓包器里面复制的。

基于以上,写出如下代码:

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

结果总是报400(Bad Request) ,这个地方卡了很久,最后解决办法是一条一条发送,每一条后面加\r\n。

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

结果总是重定向,状态码301!找了好久都不知道什么原因,而且直接在浏览器网址栏输入网址,用fiddler抓包也没有抓到状态为301的包。最后使用fiddler的composer输入http://zh.lianjia.com/ershoufang 就抓到了301和200,其中200的地址就是https://zh.lianjia.com/ershoufang,如下图所示。

利用python的socket发送http(s)请求方法示例

这下知道原因了,是http和https的区别。(其实301状态码的时候应答部分的Location可以观察到,但是一个s太不显眼了所以我没有注意到,导致卡了很久)

接下来只要知道如何发送https请求就好了。下面是代码,主要是更改建立socket和连接的部分。注意端口号为443。参考文章在这里

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

感觉自己很多地方了解的不够深入,暂时学校也没有讲到应用层。到时候再研究研究,如有错漏欢迎指出。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
深入分析在Python模块顶层运行的代码引起的一个Bug
Jul 04 Python
Python浅拷贝与深拷贝用法实例
May 09 Python
python中urlparse模块介绍与使用示例
Nov 19 Python
Python实现的多叉树寻找最短路径算法示例
Jul 30 Python
python版opencv摄像头人脸实时检测方法
Aug 03 Python
python制作抖音代码舞
Apr 07 Python
Python 使用 docopt 解析json参数文件过程讲解
Aug 13 Python
在django模板中实现超链接配置
Aug 21 Python
selenium+PhantomJS爬取豆瓣读书
Aug 26 Python
Python3 shutil(高级文件操作模块)实例用法总结
Feb 19 Python
Python3.7将普通图片(png)转换为SVG图片格式(网站logo图标)动起来
Apr 21 Python
Python使用pandas导入csv文件内容的示例代码
Dec 24 Python
Python爬虫抓取代理IP并检验可用性的实例
May 07 #Python
Python视频爬虫实现下载头条视频功能示例
May 07 #Python
十分钟利用Python制作属于你自己的个性logo
May 07 #Python
Redis使用watch完成秒杀抢购功能的代码
May 07 #Python
Python文本统计功能之西游记用字统计操作示例
May 07 #Python
Python中的函数作用域
May 07 #Python
Php多进程实现代码
May 07 #Python
You might like
咖啡因含量是由谁决定的?低因咖啡怎么来?低因咖啡适合什么人喝
2021/03/06 新手入门
PHP学习之整理字符串
2011/04/17 PHP
PHP连接SQLServer2005的实现方法(附ntwdblib.dll下载)
2012/07/02 PHP
一个完整的php文件上传类实例讲解
2015/10/27 PHP
PHP配合fiddler抓包抓取微信指数小程序数据的实现方法分析
2020/01/02 PHP
ASP中进行HTML数据及JS数据编码函数
2009/11/11 Javascript
js 绑定带参数的事件以及手动触发事件
2010/04/27 Javascript
基于jQuery中对数组进行操作的方法
2013/04/16 Javascript
jquery移动listbox的值原理及代码
2013/05/03 Javascript
js获取本机的外网/广域网ip地址完整源码
2013/08/12 Javascript
js 表单提交后按钮变灰的实例代码
2013/08/16 Javascript
jquery制作select列表双向选择示例代码
2014/09/02 Javascript
jquery实现清新实用的网页菜单效果
2015/08/28 Javascript
jQuery中show与hide方法用法示例
2016/09/16 Javascript
jQuery autoComplete插件两种使用方式及动态改变参数值的方法详解
2016/10/24 Javascript
JS实现基于Sketch.js模拟成群游动的蝌蚪运动动画效果【附demo源码下载】
2017/08/18 Javascript
webpack学习笔记之优化缓存、合并、懒加载
2017/08/24 Javascript
详解element-ui日期时间选择器的日期格式化问题
2019/04/08 Javascript
详解用async/await来处理异步
2019/08/28 Javascript
跟老齐学Python之大话题小函数(2)
2014/10/10 Python
使用Python生成XML的方法实例
2017/03/21 Python
Python实现基于PIL和tesseract的验证码识别功能示例
2018/07/11 Python
python 模拟贷款卡号生成规则过程解析
2019/08/30 Python
Python sys模块常用方法解析
2020/02/20 Python
python selenium xpath定位操作
2020/09/01 Python
详解pandas中利用DataFrame对象的.loc[]、.iloc[]方法抽取数据
2020/12/13 Python
pytorch Dataset,DataLoader产生自定义的训练数据案例
2021/03/03 Python
详解如何使用CSS3中的结构伪类选择器和伪元素选择器
2020/01/06 HTML / CSS
护理专业毕业生自我鉴定
2013/10/08 职场文书
幼儿园消防安全制度
2014/01/26 职场文书
HR求职自荐信范文
2014/06/21 职场文书
留学推荐信英文范文
2015/03/26 职场文书
聚会通知怎么写
2015/04/23 职场文书
导游词之新疆尼雅遗址
2019/10/16 职场文书
TV动画《间谍过家家》公开PV
2022/03/20 日漫
了解MySQL查询语句执行过程(5大组件)
2022/08/14 MySQL