zoukankan      html  css  js  c++  java
  • 高性能相关----爬虫

    2. 高性能相关 

    基本原理:
    IO多路复用:select,用于检测socket对象是否发生变化(是否连接成功,是否有数据到来)
    Socket:socket客户端

    import socket
    import select

    class Request(object):
    def __init__(self,sock,func,url):
    self.sock = sock
    self.func = func
    self.url = url

    def fileno(self):
    return self.sock.fileno()

    def async_request(url_list):

    input_list = []
    conn_list = []

    for url in url_list:
    client = socket.socket()
    client.setblocking(False)
    # 创建连接,不阻塞
    try:
    client.connect((url[0],80,)) # 100个向百度发送的请求
    except BlockingIOError as e:
    pass

    obj = Request(client,url[1],url[0])

    input_list.append(obj)
    conn_list.append(obj)

    while True:
    # 监听socket是否已经发生变化 [request_obj,request_obj....request_obj]
    # 如果有请求连接成功:wlist = [request_obj,request_obj]
    # 如果有响应的数据: rlist = [request_obj,request_obj....client100]
    rlist,wlist,elist = select.select(input_list,conn_list,[],0.05)
    for request_obj in wlist:
    # print('连接成功')
    # # # # 发送Http请求
    # print('发送请求')
    request_obj.sock.sendall("GET / HTTP/1.0 host:{0} ".format(request_obj.url).encode('utf-8'))
    conn_list.remove(request_obj)

    for request_obj in rlist:
    data = request_obj.sock.recv(8096)
    request_obj.func(data)
    request_obj.sock.close()
    input_list.remove(request_obj)

    if not input_list:
    break

    使用一个线程完成并发操作,如何并发?
    当第一个任务到来时,先发送连接请求,此时会发生IO等待,但是我不等待,我继续发送第二个任务的连接请求....

    IO多路复用监听socket变化
    先连接成功:
    发送请求信息: GET / http/1.0 host....
    遇到IO等待,不等待,继续检测是否有人连接成功:
    发送请求信息: GET / http/1.0 host....
    遇到IO等待,不等待,继续检测是否有人连接成功:
    发送请求信息: GET / http/1.0 host....

    有结果返回:
    读取返回内容,执行回调函数
    读取返回内容,执行回调函数
    读取返回内容,执行回调函数
    读取返回内容,执行回调函数
    读取返回内容,执行回调函数
    读取返回内容,执行回调函数
    读取返回内容,执行回调函数



    问题:什么是协程?
    单纯的执行一端代码后,调到另外一端代码执行,再继续跳...

    异步IO:
    - 【基于协程】可以用 协程+非阻塞socket+select实现,gevent
    - 【基于事件循环】完全通用socket+select实现,Twsited

    1. 如何提高爬虫并发?
    利用异步IO模块,如:asyncio,twisted,gevent
    本质:
    - 【基于协程】可以用 协程+非阻塞socket+select实现,gevent
    - 【基于事件循环】完全通用socket+select实现,Twsited,tornado

    2. 异步非阻塞
    异步:回调 select
    非阻塞:不等待 setblocking(False)

    3. 什么是协程?
    pip3 install gevent

    from greenlet import greenlet

    def test1():
    print(12)
    gr2.switch()
    print(34)
    gr2.switch()


    def test2():
    print(56)
    gr1.switch()
    print(78)

    gr1 = greenlet(test1)
    gr2 = greenlet(test2)
    gr1.switch()
  • 相关阅读:
    HDU1720 A+B Coming
    HDU1390 ZOJ1383 Binary Numbers
    HDU1390 ZOJ1383 Binary Numbers
    HDU2504 又见GCD
    HDU2504 又见GCD
    HDU1335 POJ1546 UVA389 UVALive5306 ZOJ1334 Basically Speaking
    HDU1335 POJ1546 UVA389 UVALive5306 ZOJ1334 Basically Speaking
    HDU1020 ZOJ2478 Encoding
    HDU1020 ZOJ2478 Encoding
    HDU2097 Sky数
  • 原文地址:https://www.cnblogs.com/onda/p/7715030.html
Copyright © 2011-2022 走看看