異步非阻塞socket的實現
阿新 • • 發佈:2017-09-01
print except 事件循環 port int 性能 run utf8 try
在學習使用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\r\nhost:%s\r\n\r\n" %(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()
異步非阻塞socket的實現