Python Socket请求网站获取数据
---阻塞 I/O ->收快递,快递如果不到,就干不了其他的活
---非阻塞I/0 ->收快递,不断的去问,有没有送到,有没有送到,...如果送到了就接收
---I/O多路复用 ->找个代理人(select), 去收快递。快递到了,就通知用户.
一 . 阻塞方式
blocking IO 会一直block 对应的进程,直到操作完成
# 客户端请求网站-阻塞实现(一次一次的请求)
import socket
import time # 访问网站
ACCESS_URL = 'www.baidu.com'
# 端口
ACCESS_PORT = 80 # socket阻塞请求网站
def blocking(pn):
sock = socket.socket()
sock.connect((ACCESS_URL, ACCESS_PORT)) # 连接网站 ,发出一个HTTP请求
request_url = 'GET {} HTTP/1.0\r\nHost: www.baidu.com\r\n\r\n'.format('/s?wd={}'.format(pn))
sock.send(request_url.encode())
response = b''
chunk = sock.recv(1024)
while chunk: # 循环接收数据,因为一次接收不完整
response += chunk
chunk = sock.recv(1024)
# print(response.decode())
return response def block_way():
for i in range(5):
blocking(i) if __name__ == '__main__':
start = time.time()
block_way()
print('请求5次页面耗时{}'.format(time.time() - start))
"""
请求5次页面耗时2.4048924446105957
"""
二. 非阻塞方式
non-blcoking在kernel还没准备好数据的情况下,会立即返回(会抛出异常)
# 客户端请求网站-非阻塞实现
import socket
import time # 访问网站
ACCESS_URL = 'www.baidu.com'
# 端口
ACCESS_PORT = 80 # socket非阻塞请求网站(时间消耗在不断的while循环中,和阻塞的时间差不多)
def blocking(pn):
sock = socket.socket()
sock.setblocking(False) # 设置为非阻塞
try:
# connect连接需要一定时间,非阻塞发送完请求,立即返回,如果没有数据会报异常
sock.connect((ACCESS_URL, ACCESS_PORT)) # 连接网站 ,发出一个HTTP请求
except BlockingIOError: # 非阻塞套接字捕获异常
pass
request_url = 'GET {} HTTP/1.0\r\nHost: www.baidu.com\r\n\r\n'.format('/s?wd={}'.format(pn))
while True: # 不断发送http请求
try:
sock.send(request_url.encode())
break
except OSError:
pass
response = b''
while True: # 不断地接收数据
try:
chunk = sock.recv(1024) # 没有数据返回时会收到异常
while chunk: # 循环接收数据,因为一次接收不完整
response += chunk
chunk = sock.recv(1024)
break
except BlockingIOError: # 处理非阻塞异常
pass
# print(response.decode())
return response def block_way():
for i in range(5):
blocking(i) if __name__ == '__main__':
start = time.time()
block_way()
print('请求5次页面耗时{}'.format(time.time() - start))
"""
请求5次页面耗时2.681565046310425
时间消耗在不断的while循环中,和阻塞的时间差不多
"""
三. 多线程方式
# 客户端请求网站-线程池实现
import socket
from multiprocessing.pool import ThreadPool
import time # 访问网站
ACCESS_URL = 'www.baidu.com'
# 端口
ACCESS_PORT = 80 def blocking(pn):
sock = socket.socket()
sock.connect((ACCESS_URL, ACCESS_PORT)) # 连接网站 ,发出一个HTTP请求
request_url = 'GET {} HTTP/1.0\r\nHost: www.baidu.com\r\n\r\n'.format('/s?wd={}'.format(pn))
sock.send(request_url.encode())
response = b''
chunk = sock.recv(1024)
while chunk: # 循环接收数据,因为一次接收不完整
response += chunk
chunk = sock.recv(1024)
# print(response.decode())
return response def block_way():
pool = ThreadPool(5)
for i in range(10):
pool.apply_async(blocking, args=(i,))
pool.close() # close()执行后不会有新的进程加入到pool
pool.join() # join函数等待子进程结束 if __name__ == '__main__':
start = time.time()
block_way()
print('请求10次页面耗时{}'.format(time.time() - start))
"""
请求10次页面耗时1.1231656074523926
"""
四. 多进程方式
# 客户端请求网站-进程池实现
import socket
from multiprocessing import Pool
import time # 访问网站
ACCESS_URL = 'www.baidu.com'
# 端口
ACCESS_PORT = 80 def blocking(pn):
"""
发送请求,接收数据
:param pn:
:return:
"""
sock = socket.socket()
sock.connect((ACCESS_URL, ACCESS_PORT)) # 连接网站 ,发出一个HTTP请求
request_url = 'GET {} HTTP/1.0\r\nHost: www.baidu.com\r\n\r\n'.format('/s?wd={}'.format(pn))
sock.send(request_url.encode())
response = b''
chunk = sock.recv(1024)
while chunk: # 循环接收数据,因为一次接收不完整
response += chunk
chunk = sock.recv(1024)
# print(response.decode())
return response def block_way():
pool = Pool(5)
for i in range(10):
pool.apply_async(blocking, args=(i,))
pool.close() # close()执行后不会有新的进程加入到pool
pool.join() # join函数等待子进程结束 if __name__ == '__main__':
start = time.time()
block_way()
print('请求10次页面耗时{}'.format(time.time() - start))
"""
请求10次页面耗时1.1685676574707031 略慢于线程池实现方式,因为进程相对于线程开销比较大
"""
五. 协程方式
# 客户端请求网站-协程实现
from gevent import monkey;monkey.patch_all() # 加补丁,实现非阻塞
import socket
import gevent
import time # 访问网站
ACCESS_URL = 'www.baidu.com'
# 端口
ACCESS_PORT = 80 def blocking(pn):
"""
发送请求,接收数据
:param pn:
:return:
"""
sock = socket.socket()
sock.connect((ACCESS_URL, ACCESS_PORT)) # 连接网站 ,发出一个HTTP请求
request_url = 'GET {} HTTP/1.0\r\nHost: www.baidu.com\r\n\r\n'.format('/s?wd={}'.format(pn))
sock.send(request_url.encode())
response = b''
chunk = sock.recv(1024)
while chunk: # 循环接收数据,因为一次接收不完整
response += chunk
chunk = sock.recv(1024)
# print(response.decode())
return response def block_way():
tasks = [gevent.spawn(blocking,i) for i in range (10)] #启动协程
gevent.joinall(tasks) # 阻塞等待所有操作都执行完毕 if __name__ == '__main__':
start = time.time()
block_way()
print('请求10次页面耗时{}'.format(time.time() - start))
"""
请求10次页面耗时0.6231002807617188 效率高于线程方式,协程相当于单线程并发(微线程),开销小于线程
"""
六. IO多路复用
I/O多路复用就是通过一种机制,操作系统通过一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。
# 客户端请求网站-I/O多路复用
import socket
import selectors
import time # 访问网站
ACCESS_URL = 'www.baidu.com'
# 端口
ACCESS_PORT = 80 sel = selectors.DefaultSelector()
flag = False # 结束标志
num_list = [0] * 5 class Crawler(object):
def __init__(self,pn):
self.pn = pn
self.response = b'' def req_connect(self):
"""
请求建立连接
:return:
"""
sock = socket.socket()
sock.setblocking(False)
try:
sock.connect((ACCESS_URL, ACCESS_PORT)) # 连接网站 ,发出一个HTTP请求
except BlockingIOError: # 非阻塞套接字捕获异常
pass
sel.register(sock,selectors.EVENT_WRITE, self.conn_send) # 监听socket,向服务端发送数据WRITE def conn_send(self,sock):
"""
发送请求数据
:param sock:
:return:
"""
# 取消上面注册监听的套接字
sel.unregister(sock)
request_url = 'GET {} HTTP/1.0\r\nHost: www.baidu.com\r\n\r\n'.format('/s?wd={}'.format(self.pn))
sock.send(request_url.encode()) # 当我们发送数据之后,就等接收数据
sel.register(sock,selectors.EVENT_READ, self.read) def read(self, sock):
global flag
chunk = sock.recv(1024)
if chunk:
self.response += chunk
else:
# 没有数据可读
print(self.response)
sel.unregister(sock)
num_list.pop()
if not num_list:
flag = True # 事件循环
def loop():
while not flag:
events = sel.select() # 监听发生了变化的套接字
for key, mask in events:
callback = key.data
callback(key.fileobj) if __name__ == '__main__':
start = time.time()
# print(num_list)
for i in range(5):
crawler = Crawler(i) # 实例
crawler.req_connect()
loop()
print('请求5次页面耗时{}'.format(time.time() - start))
"""
请求5次页面耗时0.5865745544433594 多路复用非阻塞效率要高于非阻塞方式
"""
Python Socket请求网站获取数据的更多相关文章
-
爬虫 Http请求,urllib2获取数据,第三方库requests获取数据,BeautifulSoup处理数据,使用Chrome浏览器开发者工具显示检查网页源代码,json模块的dumps,loads,dump,load方法介绍
爬虫 Http请求,urllib2获取数据,第三方库requests获取数据,BeautifulSoup处理数据,使用Chrome浏览器开发者工具显示检查网页源代码,json模块的dumps,load ...
-
Flutter实战视频-移动电商-08.Dio基础_伪造请求头获取数据
08.Dio基础_伪造请求头获取数据 上节课代码清楚 重新编写HomePage这个动态组件 开始写请求的方法 请求数据 .但是由于我们没加请求的头 所以没有返回数据 451就是表示请求错错误 创建请求 ...
-
React 中的 AJAX 请求:获取数据的方法
React 中的 AJAX 请求:获取数据的方法 React 只是使用 props 和 state 两处的数据进行组件渲染. 因此,想要使用来自服务端的数据,必须将数据放入组件的 props 或 st ...
-
一、表单和ajax中的post请求&;&;后台获取数据方法
一.表单和ajax中的post请求&&后台获取数据方法 最近要做后台数据接收,因为前台传来的数据太过于混乱,所以总结了一下前台数据post请求方法,顺便写了下相对应的后台接收方法. 前 ...
-
原生socket请求url获取状态码、消息报头、响应正文
需求: (1)使用socket及ssl模块写通用的web客户端 (2)向服务器发起请求 (3)接受响应内容并解析出状态码.消息报头.响应正文 (4)最核心的函数: 输入一个url,返回状态码.消息报头 ...
-
nodejs发起HTTPS请求并获取数据
摘要:在网站中有时候需要跨域请求数据,直接用Ajax无法实现跨域,采用其他方式需要根据不同的浏览器做相应的处理.用Nodejs可以很好的解决这些问题,后台引用HTTPS模块,发送和返回的数据均为JSO ...
-
python3实践-从网站获取数据(Carbon Market Data-GD) (bs4/Beautifulsoup)
结合个人需求,从某个网站获取一些数据,发现网页链接是隐藏的,需要通过浏览器看后面的代码来获取真实的链接. 下面这个案例,直接是从真实的链接中爬去数据. 此外,发现用pandas的read_html不能 ...
-
python3实践-从网站获取数据(Carbon Market Data-BJ) (pandas,bs4)
自己边看边实践一些简单的实际应用,下面的程序是从某个网站上获取需要的数据. 在编写的过程中,通过学习陆续了解到一些方法,发现Python真的是很便捷. 尤其是用pandas获取网页中的表格数据,真的是 ...
-
08-Flutter移动电商实战-dio基础_伪造请求头获取数据
在很多时候,后端为了安全都会有一些请求头的限制,只有请求头对了,才能正确返回数据.这虽然限制了一些人恶意请求数据,但是对于我们聪明的程序员来说,就是形同虚设.这篇文章就以极客时间 为例,讲一下通过伪造 ...
随机推荐
-
javascript,jQuery,trim()
JavaScript trim() Syntax string.trim() The trim() method removes whitespace from both sides of a str ...
-
hilbert矩阵
希尔伯特矩阵 希尔伯特矩阵是一种数学变换矩阵 Hilbert matrix,矩阵的一种,其元素A(i,j)=1/(i+j-1),i,j分别为其行标和列标. 即: [1,1/2,1/3,……,1/n] ...
-
NDK(2)使用eclipse + ndk开发过程演示,含CPU架构编译
环境linux + eclipse + adt + ndk 1,在ide中配置ndk 下载ndk,在eclipse中配置 2,使用ndk编程 2.1 给项目添加ndk 支持 右键 项目名 --> ...
-
关于VNC黑屏的问题
注意: 1.vncserver启动后生成的ID号(1,2,3)要和VNCview里面填入的 ip:ID要保持一致 不然看到的就是黑屏 比如:vncserver启动后 产生: localhost.lo ...
-
mysql table is marked as crashed and last (automatic?) repair failed
1.同事的服务器在mysqldump备份的时候报错了 这个原因是myisam的表数据太多,在某个时刻, 存放数据的这个MyISAM表数据急速长大. 比如一些log表, 当硬盘写满了.这个时候还在继续写 ...
-
【Luogu3808】多项式乘法FFT(FFT)
题目戳我 一道模板题 自己尝试证明了大部分... 剩下的还是没太证出来... 所以就是一个模板放在这里 以后再来补东西吧.... #include<iostream> #include&l ...
-
cas 单点登录(SSO)实验之二: cas-client
cas 单点登录(SSO)实验之二: cas-client 参考文章: http://my.oschina.net/indestiny/blog/200768#comments http://wenk ...
-
cannal&;otter源码解析
一点引用资料的整理 http://www.tianshouzhi.com/api/tutorials/canal/381 canal 同步工具 https://github.com/alibaba/c ...
-
poi操作Excel的封装类
这是一个简单的对poi的封装,只能简单的取值,设值,拷贝行,插入行等. 针对读取Excel模板后,填值再保存的应用,比较方便. poi版本:3.13 贴代码: package cn.com.gtmc. ...
-
获取table行列
var table =document.getElementById("add_purchaseOrderDetailList_table"); var rows = table. ...