当前位置: 首页 > 编程日记 > 正文

Python Socket请求网站获取数据

 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 += chunkchunk = sock.recv(1024)# print(response.decode())return responsedef 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:  # 非阻塞套接字捕获异常passrequest_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())breakexcept OSError:passresponse = b''while True:  # 不断地接收数据try:chunk = sock.recv(1024)  # 没有数据返回时会收到异常while chunk:  # 循环接收数据,因为一次接收不完整response += chunkchunk = sock.recv(1024)breakexcept BlockingIOError:  # 处理非阻塞异常pass# print(response.decode())return responsedef 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 = 80def 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 += chunkchunk = sock.recv(1024)# print(response.decode())return responsedef block_way():pool = ThreadPool(5)for i in range(10):pool.apply_async(blocking, args=(i,))pool.close()  # close()执行后不会有新的进程加入到poolpool.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 = 80def 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 += chunkchunk = sock.recv(1024)# print(response.decode())return responsedef block_way():pool = Pool(5)for i in range(10):pool.apply_async(blocking, args=(i,))pool.close()  # close()执行后不会有新的进程加入到poolpool.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 = 80def 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 += chunkchunk = sock.recv(1024)# print(response.decode())return responsedef 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 = 80sel = selectors.DefaultSelector()
flag = False  # 结束标志
num_list = [0] * 5class Crawler(object):def __init__(self,pn):self.pn = pnself.response = b''def req_connect(self):"""请求建立连接:return:"""sock = socket.socket()sock.setblocking(False)try:sock.connect((ACCESS_URL, ACCESS_PORT))  # 连接网站 ,发出一个HTTP请求except BlockingIOError:  # 非阻塞套接字捕获异常passsel.register(sock,selectors.EVENT_WRITE, self.conn_send)  # 监听socket,向服务端发送数据WRITEdef 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 flagchunk = sock.recv(1024)if chunk:self.response += chunkelse:# 没有数据可读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.datacallback(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 多路复用非阻塞效率要高于非阻塞方式"""

转载于:https://www.cnblogs.com/xiao-apple36/p/8673356.html

相关文章:

用户控件和服务器控件的数据绑定

一、绑定Repeater控件的数据源 aspx.cs文件中绑定Repeater控件的数据源在BindDataSource()中: protected override void BindDataSource(){ this.rpID.DataSource this.dataList; this.rpID.DataBind();}Repeater控件事件OnItemDataBound,表示在循环…

【jsp】兴唐第三十节课作业

写一个jsp调取数据库的文件显示在主页面&#xff0c;并实现查找、添加、删除和数据更新以及用户登录的功能 stuList.jsp <% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%> <% page import "…

Linux命令行好玩的命令

0.cal 2019 #输出日历并显示今天是哪一天 1.命令“date”&#xff0c;显示系统的当前日期和时间&#xff1b; 2.命令“date 040100002016”&#xff0c;屏幕显示新修改的系统时间&#xff1b; #不太明白 3.转载于:https://www.cnblogs.com/Formulate0303/p/11142997.html

Solaris下访问windows共享资源

今在做实验过程中&#xff0c;发现上传软件太费时而且解压起来也繁琐&#xff0c;还要占用很大的空间&#xff0c;就在windows上创建了共享资源&#xff0c;在linux下使用mount挂载上来&#xff0c;直接解压在windows上面&#xff0c;用完了直接将解压的文件删除即可&#xff0…

centOS外部浏览器无法访问tomcat8000端口解决办法

防火墙开放特定端口 &#xff08;iptables&#xff09; 查看状态:iptables -L -n下面添加对特定端口开放的方法&#xff1a;使用iptables开放如下端口/sbin/iptables -I INPUT -p tcp --dport 8000 -j ACCEPT保存/etc/rc.d/init.d/iptables save重启服务service iptables resta…

Linux命令行与shell脚本编程大全:第2版

《Linux命令行与shell脚本编程大全:第2版》基本信息作者&#xff1a; (美)布卢姆(Blum,R.) 布雷斯纳汉(Bresnahan.C.) [作译者介绍]译者&#xff1a; 武海峰丛书名&#xff1a; 图灵程序设计丛书出版社&#xff1a;人民邮电出版社ISBN&#xff1a;9787115288899上架时间&#x…

企业云存储云办公方案

云存储、云计算最近一直被炒得很热&#xff0c;成为了一部分人文档中既神秘又华丽的辞藻&#xff0c;总之来总之去就是"云里来雾里去"&#xff0c;其实"云技术"与历史上的"纳米技术"一词一样忽悠了很多很多的人。云存储是在云计算基础上衍生起来…

【servlete】兴唐第三十二节课知识点汇总

一、 servlet开发&#xff1a; 1、创建java类并继承HttpServlet 2、重写 doGet\doPost方法 3、将Servlet配置到web.xml中&#xff1a; <servlet> <servlet-name>自定义一个唯一的名称</servlet-name> <servlet-class>servlet全类…

悦读上品 得乎益友

悦读上品 得乎益友 ——电子工业出版社2011新年巨献不可复制的《传世经典书从》 孔子云&#xff1a;“取乎其上&#xff0c;得乎其中&#xff1b;取乎其中&#xff0c;得乎其下&#xff1b;取乎其下&#xff0c;则无所得矣。”读书求知&#xff0c;贵在能选择好书中的上品——经…

超详细的Java面试题总结(四 )之JavaWeb基础知识总结

系列文章请查看&#xff1a; 超详细的Java面试题总结&#xff08;一&#xff09;之Java基础知识篇 超详细的Java面试题总结&#xff08;二&#xff09;之Java基础知识篇 超详细的Java面试题总结&#xff08;三&#xff09;之Java集合篇常见问题 超详细的Java面试题总结&#xf…

HTML教程--多页面窗体

基本语法 <frameset> ... </frameset> <frame src"url"> <noframes> ... </noframes> 在 <noframes> 标记后的文字将只出现在不支持 FRAMES 的浏览器中。 <HTML><HEAD></HEAD><FRAMESET><FRAME SRC…

js左侧三级菜单导航代码

效果演示&#xff1a; 实例代码&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml" xml:lang&…

【jsp】页面跳转的两种方法

注&#xff1a;由index.jxp跳转到Failure.jsp request.getSession().setAttribute("msg", "45654"); 方法一&#xff1a; response.sendRedirect("Failure.jsp"); 特点&#xff1a; &#xff08;1&#xff09;不能传值 &#xff08;2&…

windows远程桌面端口修改

众所周知&#xff0c;windows 2003远程终端服务基于默认端口3389。***者一般先扫描主机开放端口&#xff0c;一旦发现其开放了3389端口&#xff0c;就会进行下一步的***&#xff0c;所以我们只需要修改该务默认端口就可以避开大多数***者的耳目。 步骤&#xff1a; 打开“开始→…

《java第二次实验》

&#xff08;一&#xff09;学习总结 1.什么是构造方法&#xff1f;什么是构造方法的重载&#xff1f;下面的程序是否可以通过编译&#xff1f;为什么&#xff1f; public class Test {public static void main(String args[]) { Foo obj new Foo(); } } class Foo…

[置顶] 当我拿车钥匙的时候,刚交的女朋友跑了。。。

转载于:https://www.cnblogs.com/james1207/p/3291906.html

【jstl】jstl的基本操作

1、jstl不属于javaEE标准&#xff0c;所以需要额外引入jar包 2、引入后需要引入标签库 代码实现&#xff1a; <% taglib prefix"c" uri"http://java.sun.com/jsp/jstl/core" %> 注&#xff1a; &#xff08;1&#xff09;可以使用 alt / 的快捷…

如何修改Sql2005注册服务器名称 {转载}

1.使用select ServerName可以看到当前数据库的服务器名 2.从Sys.SysServers表中可以看到当前的所有服务器名 3.使用 sp_dropserver servername 将这个服务器名删除。 4.使用 sp_addserver new servername,LOCAL将本地服务器重新添加到服务器表中 5.查询Sys.SysServers表&#x…

据说是腾讯php程序员面试题目 蛋疼..要是提供PHP手册就HI了..

说在前面&#xff1a;&#xff11;、以下题目&#xff0c;除了编程任务外其他都需要写在给你提供的草纸上。纸张是珍贵的地球资源&#xff0c;请节约使用。编程任务在有相应的环境时&#xff0c;会要求上机书写&#xff0c;实在没有条件&#xff0c;就只能写在草纸上了。&#…

C功底挑战Java菜鸟入门概念干货(一)

一、认识Java 1、Java 程序比较特殊&#xff0c;它必须先经过编译&#xff0c;然后再利用解释的方式来运行。 2、Byte-codes 最大的好处是——可越平台运行&#xff0c;可让“一次编写&#xff0c;处处运行”成为可能。 3、使用 classpath 可以指定 class 的运行路径。 二、走…

c# lock (obj) 与 lock (this) 区别

lock(obj) 锁定 obj 对象 lock(this) 锁定 当前实例对象&#xff0c;如果有多个类实例的话&#xff0c;lock锁定的只是当前类实例&#xff0c;对其它类实例无影响。 直接上代码。 主窗体代码如下&#xff1a; delegate void SetTextCallback(string text);public Form1() …

【js】四种自定义对象的常见方法

<html><head></head><body><script type "text/javascript">//方法1var stu1 new Object();stu1.stuName "小强1";stu1.stuNo "123";stu1.print function() {alert(stu1.stuName);}//stu1.print();//alert(s…

eclipse启动时报错An internal error occurred during: Initializing Java Tooling.

eclipse启动时报错An internal error o当前工作目录文件夹下的 /.metadata/.plugins/org.eclipse.core.resources/.project。就是把初始化的项目删除&#xff0c;然后打开eclipse以后可以重新初始化。转载于:https://www.cnblogs.com/huanlingjisi/p/8696541.html

给Sqlite数据库设置密码

免费版Sqlie是不提供设置密码功能的&#xff0c;经过查阅资料最终找到了解决方案 方案一&#xff0c;从sqlite源码入手&#xff0c;据说sqlite源码已经提供了加密的接口&#xff0c;只是免费版没有实现&#xff0c;可以参考这位仁兄的博客以了解详情&#xff1a;http://www.cnb…

《创新者》读书笔记 PB16110698 第五周(~4.5)

本周我阅读了某同学推荐的《创新者》&#xff0c;这本书实际上是两个世纪以来信息技术的编年史&#xff0c;从巴贝奇的差分机到如今互联网时代的超级计算机&#xff0c;作者通过各个时代里一位位杰出的创新者&#xff0c;将计算机诞生、发展、崛起和蓬勃的历程娓娓道来。从一篇…

001本周总结报告

在本周中&#xff0c;自己主要做了小学期的编程作业&#xff0c;因为是小学期的特殊缘故&#xff0c;自己的学习时间几乎分配给了小学期的作业的编程&#xff0c;大约每天会抽出5个小时用来编写程序&#xff0c;本周在做小学期的作业时发现自己编程力不从心&#xff0c;无论是从…

【js】创建数组的三种方法

<html><head></head><script type"text/javascript">//数组var stuName1 new Array();stuName1[1] "小强1";stuName1[2] "小强2";//alert(stuName.length);//声明并穷举数组var stuName2 new Array("小强3&quo…

JSon数据查询---Jlinq

LINQ&#xff0c;语言集成查询&#xff08;Language INtegrated Query&#xff09;是一组用于c#和Visual Basic语言的扩展。它允许编写C#或者Visual Basic代码以查询数据库相同的方式操作内存数据。 Jlinq受到LinQ的启发&#xff0c;可以像LinQ一样查询JSON数据&#xff0c;使用…

PowerShell 2.0管理事件日志(一)查看和读取事件日志

事件日志是操作系统用来保存本身及其他程序信息的工具&#xff0c;本文将会介绍如何通过PowerShell脚本阅读事件日志并创建新的日志条目。Windows系统中包含多种事件日志&#xff0c;在Windows XP系统中包括4种主要的事件日志。即应用程序、系统、安全性及Internet Explorer日志…

Applet相关知识

1、Applet定义 Applet是采用Java编程语言编写的小应用程序&#xff0c;该程序可以包含在 HTML&#xff08;标准通用标记语言的一个应用&#xff09;页中&#xff0c;与在页中包含图像的方式大致相同。含有Applet的网页的HTML文件代码中部带有<applet> 和</applet>这…