利用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远程桌面协议RDPY安装使用介绍
Apr 15 Python
使用PDB简单调试Python程序简明指南
Apr 25 Python
python搭建虚拟环境的步骤详解
Sep 27 Python
Python之自动获取公网IP的实例讲解
Oct 01 Python
python面试题Python2.x和Python3.x的区别
May 28 Python
django框架F&Q 聚合与分组操作示例
Dec 12 Python
新年福利来一波之Python轻松集齐五福(demo)
Jan 20 Python
使用python从三个角度解决josephus问题的方法
Mar 27 Python
python和c语言哪个更适合初学者
Jun 22 Python
python实现扫雷游戏的示例
Oct 20 Python
python爬虫搭配起Bilibili唧唧的流程分析
Dec 01 Python
Python OpenGL基本配置方式
May 20 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
图书管理程序(一)
2006/10/09 PHP
php 按指定元素值去除数组元素的实现方法
2011/11/04 PHP
PHP三元运算符的结合性介绍
2012/01/10 PHP
[原创]php正则删除html代码中class样式属性的方法
2017/05/24 PHP
轻轻松松学JS调试(不下载任何工具)
2010/04/14 Javascript
ExtJs 表单提交登陆实现代码
2010/08/19 Javascript
JS 去除Array中的null值示例代码
2013/11/20 Javascript
根据配置文件加载js依赖模块
2014/12/29 Javascript
JavaScript实现Flash炫光波动特效
2015/05/14 Javascript
个人总结的一些JavaScript技巧、实用函数、简洁方法、编程细节
2015/06/10 Javascript
详解jQuery事件
2017/01/13 Javascript
async/await与promise(nodejs中的异步操作问题)
2017/03/03 NodeJs
Bootstrap免费字体和图标网站(值得收藏)
2017/03/16 Javascript
jQuery幻灯片插件owlcarousel参数说明中文文档
2018/02/27 jQuery
使用layer弹窗和layui表单实现新增功能
2018/08/09 Javascript
JavaScript观察者模式原理与用法实例详解
2020/03/10 Javascript
JS正则表达式验证密码强度
2020/03/18 Javascript
JS forEach跳出循环2种实现方法
2020/06/24 Javascript
js实现简单的无缝轮播效果
2020/09/05 Javascript
tensorflow使用神经网络实现mnist分类
2018/09/08 Python
pandas 根据列的值选取所有行的示例
2018/11/07 Python
对python3 中方法各种参数和返回值详解
2018/12/15 Python
基于python历史天气采集的分析
2019/02/14 Python
基于Numpy.convolve使用Python实现滑动平均滤波的思路详解
2019/05/16 Python
python实现点击按钮修改数据的方法
2019/07/17 Python
python 怎样将dataframe中的字符串日期转化为日期的方法
2019/09/26 Python
PyQt5实现画布小程序
2020/05/30 Python
服装设计专业自荐书范文
2013/12/30 职场文书
党员一帮一活动总结
2014/07/08 职场文书
捐款通知怎么写
2015/04/24 职场文书
2015年度村委会工作总结
2015/04/29 职场文书
2015年领导班子工作总结
2015/05/23 职场文书
开业庆典嘉宾致辞
2015/08/01 职场文书
教你怎么用python爬取爱奇艺热门电影
2021/05/20 Python
Python matplotlib安装以及实现简单曲线的绘制
2022/04/26 Python
前端使用svg图片改色实现示例
2022/07/23 HTML / CSS