在学习使用scrapy爬虫框架之前,需要了解一些基础原理
我们知道HTTP请求是基于socket模块进行发送和接受的,但是socket套接字的在使用的中存在着阻塞,不利用爬虫的高性能运行,所以我们就需要对框架进行一些高性能设置,使用select模块,检测socket请求的IO操作,实现对socket的高性能运行:
以下是代码示例:
import socket import select class Request(object): ''' request类的定义是应对请求的连接不同时,做的低耦合操作 ''' def __int__(self,sock,info): self.sock=sock self.info=info def fileno(self): ''' 因为select模块在检测IO操作但是针对socket对象,该对象中必须有fileno方法才能调用, 因此需要我们自己定义一个request类,在类下包含fileno方法 :return: ''' return self.sock.fileno() class Mysocket(object): def __int__(self): ''' 初始化两个列表,存储socket对象 :return: ''' self.sock_list=[] self.conns=[] def add_request(self,req_info): ''' 创建请求 :param req_info: {'host':'www.baidu.com','port':80} :return: ''' sock=socket.socket() sock.setblocking(False)#设置socket为非阻塞状态 try: sock.connect((req_info['host'],req_info['post'])) except BaseException as e: pass #使用try方法防止sock在非阻塞状态下报错 obj=Request(sock,req_info)#示例话Request类,此类就是socket实例化的对象 self.sock_list.append(obj) self.conns.append(obj) def run(self): ''' 开始事件循环,检测:连接是否成功,是否有数据返回 :return: ''' while True: r,w,e=select.select(self.sock_list,self.conns,[],0.05) #select。select([socket对象,]),可以是任何对象,但是对象一定要有 #fileno方法,所以需要自己去定义request类 #在此处就调用request对象 #seclet参数w数值就是检测请求是否成功 for obj in w: #检查obj.request对象 data="GET %s http/1.1 host:%s " %(obj.info['path'],obj.info['host']) obj.sock.send(data.encode('utf8')) self.conns.remove(obj)#该连接在成功请求过后,为防止重复发送请求,需请求列表中将其删除 #数据返回,接受到数据 for obj in r: response=obj.sock.recv(8096) obj.info["callback"](response) self.sock_list.remove(obj) from .. import Mysocket def data(response): ''' 回调函数,对返回的数据进行操作 :param response: :return: ''' print(response) def file(response): ''' 回调函数,对返回数值的第二种操作方式 :param response: :return: ''' print(response) url_list = [ {'host': 'www.baidu.com', 'port': 80, 'path': '/','callback': data}, {'host': 'www.cnblogs.com', 'port': 80, 'path': '/index.html','callback': file}, {'host': 'www.bing.com', 'port': 80, 'path': '/','callback': data}, ] obj=Mysocket() for item in url_list: obj.add_request(item) obj.run()