zoukankan      html  css  js  c++  java
  • 爬虫提高效率方式

    提高效率的方式

    • 线程池
      • map(func,alist)
    • 多任务的异步协程
      • asyncio
        • 特殊的函数
        • 协程
        • 任务对象
          • 任务对象绑定
        • 事件循环
    • from multiprocessing.dummy import Pool
    • map(func,alist):
      • 可以让func回调函数处理alist中的每一个列表元素,这个处理的过程是基于异步
    特殊函数:
        - 就是async关键字修饰的一个函数的定义
        - 特殊之处:
            - 特殊函数被调用后会返回一个协程对象
            - 特殊函数调用后内部的程序语句没有被立即执行
            
    - 协程
        - 对象。协程==特殊的函数。协程表示的就是一组特定的操作。
        
    - 任务对象
        - 高级的协程(对协程的进一步的封装)
            - 任务对象==协程==特殊的函数
                - 任务对象==特殊的函数
        - 绑定回调:
            - task.add_done_callback(task)
                - 参数task:当前回调函数对应的任务对象
                - task.result():返回的就是任务对象对应的特殊函数的返回值
                
    - 事件循环对象
        - 创建事件循环对象
        - 将任务对象注册到该对象中并且开启该对象
        - 作用:loop可以将其内部注册的所有的任务对象进行异步执行
    
    - 挂起:就是交出cpu的使用权。
    
    await:被用做在特殊函数的内部,在被阻塞的时候
    wait:给每一个任务赋予一个可被挂起的权限
    
    #【重点】在特殊函数内部的实现中,不可以出现不支持异步的模块(例如time,requests)代码,如果出现了,则会中断整个的异步效果!!!
    

    单线程+多任务异步协程

    单线程+多任务异步协程asyncio

    • 特殊函数:

      • 就是async关键字修饰的一个函数的定义
      • 特殊之处:
        • 特殊函数被调用后会返回一个协程对象
        • 特殊函数调用后内部的程序语句没有被立即执行
    • 协程

      • 对象。协程==特殊的函数。协程表示的就是一组特定的操作。
    • 任务对象

      • 高级的协程(对协程的进一步的封装)
        • 任务对象协程特殊的函数
          • 任务对象==特殊的函数
      • 绑定回调:
        • task.add_done_callback(task)
          • 参数task:当前回调函数对应的任务对象
          • task.result():返回的就是任务对象对应的特殊函数的返回值
    • 事件循环对象

      • 创建事件循环对象
      • 将任务对象注册到该对象中并且开启该对象
      • 作用:loop可以将其内部注册的所有的任务对象进行异步执行
    • 挂起:就是交出cpu的使用权。

    • 【重点】在特殊函数内部的实现中,不可以出现不支持异步的模块代码,如果出现了,
      则会中断整个的异步效果!!!

    • requests一定是不支持异步

    • aiohttp是一个支持异步的网络请求模块

      • 环境安装

      • 编码流程:

        • 大致的架构:
          with aiohttp.ClientSession() as s:

          s.get(url,headers,params,proxy="http://ip:port")

          with s.get(url) as response:
          #response.read()二进制(.content)
          page_text = response.text()
          return page_text

        • 补充细节

          • 在每一个with前加上async

          • 需要在每一个阻塞操作前加上await

            async with aiohttp.ClientSession() as s:
            #s.get(url,headers,params,proxy="http://ip:port")
            async with await s.get(url) as response:
            #response.read()二进制(.content)
            page_text = await response.text()
            return page_text

    协程基础

    将一个任务对象注册到 事件循环对象中 并且开启该任务对象

    import asyncio
    from time import sleep
    
    #特殊的函数  步骤1
    async def get_request(url):
        print('正在下载:',url)
        sleep(2)
        print('下载完毕:',url)
    
        return 'page_text'
    
    
    #特殊函数的调用 步骤2 此时特殊函数 不远行 并将对象返回给c
    c = get_request('www.1.com')
    
    #创建一个任务对象  步骤3  高级的协程(对协程的进一步的封装) 任务对象==协程==特殊的函数
    task = asyncio.ensure_future(c)
    
    #创建一个事件循环对象 步骤4 作用:loop可以将其内部注册的所有的任务对象进行异步执行 提高效率
    loop = asyncio.get_event_loop()
    
    #将任务对象注册到该对象中并且开启该对象 步骤5
    loop.run_until_complete(task)#让loop执行了一个任务
    
    
    ps注册好后 这个任务对象 就可以异步了
    

    绑定回调

    绑定回调函数 可以使 任务函数执行完 自动执行回调函数

    import asyncio
    from time import sleep
    
    #特殊的函数  步骤1
    async def get_request(url):
        print('正在下载:',url)
        sleep(2)
        print('下载完毕:',url)
    
        return 'page_text'
    
    #回调函数的定义(普通的函数) 步骤3  
    def parse(task):
        #参数表示的就是任务对象  task.result():返回的就是任务对象对应的特殊函数的返回值  比如爬取到的文本数据
        print('i am callback!!!',task.result())
    
    #特殊函数的调用 步骤2 此时特殊函数 不远行 并将对象返回给c
    c = get_request('www.1.com')
    
    #创建一个任务对象  步骤3  高级的协程(对协程的进一步的封装) 任务对象==协程==特殊的函数
    task = asyncio.ensure_future(c)
    
    #给任务对象绑定一个回调函数  步骤3 加了回调函数 parse是一个普通函数 也是回调函数
    task.add_done_callback(parse)
    
    #创建一个事件循环对象 步骤4 作用:loop可以将其内部注册的所有的任务对象进行异步执行 提高效率
    loop = asyncio.get_event_loop()
    
    #将任务对象注册到该对象中并且开启该对象 步骤5
    loop.run_until_complete(task)#让loop执行了一个任务
    
    

    多任务协程+回调

    import asyncio
    from time import sleep
    import time
    #特殊的函数
    async def get_request(url):
        print('正在下载:',url)
        await asyncio.sleep(2) #注意
        print('下载完毕:',url)
    
        return 'i am page_text!!!'
    def parse(task):
        page_text = task.result()#拿到任务对象返回值
        print(page_text)
    
    start = time.time()
    urls = ['www.1.com','www.2.com','www.3.com']
    
    tasks = []#存储的是所有的任务对象。多任务!
    for url in urls:
        c = get_request(url)#特殊函数的调用
        task = asyncio.ensure_future(c)#创建任务对象
        task.add_done_callback(parse)#增加回调函数
        tasks.append(task)
    
    loop = asyncio.get_event_loop()
    
    #asyncio.wait(tasks):给每一个任务对象赋予一个可被挂起的权限  将列表的任务对象 注册到 事件循环对象
    loop.run_until_complete(asyncio.wait(tasks))
    
    print('总耗时:',time.time()-start)
    
    ps
    在特殊函数内部的实现中,不可以出现不支持异步的模块代码,如果出现了,
    则会中断整个的异步效果!!!
    

    实践

    requests 不支持异步模块

    换aiohttp

    • aiohttp是一个支持异步的网络请求模块

      • 环境安装

      • 编码流程:

        • 大致的架构:
          with aiohttp.ClientSession() as s:

          s.get(url,headers,params,proxy="http://ip:port")

          with s.get(url) as response:
          #response.read()二进制(.content)
          page_text = response.text()
          return page_text

        • 补充细节

          • 在每一个with前加上async

          • 需要在每一个阻塞操作前加上await

            async with aiohttp.ClientSession() as s:
            #s.get(url,headers,params,proxy="http://ip:port")
            async with await s.get(url) as response:
            #response.read()二进制(.content)
            page_text = await response.text()
            return page_text

    import asyncio
    import aiohttp
    import time
    from bs4 import BeautifulSoup
    #将被请求的url全部整合到一个列表中
    urls = ['http://127.0.0.1:5000/bobo','http://127.0.0.1:5000/jay','http://127.0.0.1:5000/tom']
    start = time.time()
    
    async def get_request(url):
        async with aiohttp.ClientSession() as s:
            #s.get(url,headers,params,proxy="http://ip:port")
            async with await s.get(url) as response:
                #response.read()二进制(.content)
                page_text = await response.text()
                return page_text
    
    def parse(task):
        page_text = task.result()
        soup = BeautifulSoup(page_text,'lxml')
        data = soup.find('div',class_="tang").text
        print(data)
    tasks = []
    for url in urls:
        c = get_request(url)
        task = asyncio.ensure_future(c)
        task.add_done_callback(parse)
        tasks.append(task)
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(tasks))
    
    print('总耗时:',time.time()-start)
    

    aiohttp学习

    • aiohttp是一个支持异步的网络请求模块

      • 环境安装

      • 编码流程:

        • 大致的架构:
          with aiohttp.ClientSession() as s:

          s.get(url,headers,params,proxy="http://ip:port")

          with s.get(url) as response:
          #response.read()二进制(.content)
          page_text = response.text()
          return page_text

        • 补充细节

          • 在每一个with前加上async

          • 需要在每一个阻塞操作前加上await

            async with aiohttp.ClientSession() as s:
            #s.get(url,headers,params,proxy="http://ip:port")
            async with await s.get(url) as response:
            #response.read()二进制(.content)
            page_text = await response.text()
            return page_text

    大致的架构:
    with aiohttp.ClientSession() as s:
       #s.get(url,headers,params,proxy="http://ip:port")
       with s.get(url) as response:
           #response.read()二进制(.content)
           page_text = response.text()
           return page_text
    
    补充
    在每一个with前加上async
    需要在每一个阻塞操作前加上await
    async def get_request(url):
        async with aiohttp.ClientSession() as s:
            #s.get(url,headers,params,proxy="http://ip:port")
            async with await s.get(url) as response:
                #response.read()二进制(.content)
                page_text = await response.text()
                return page_text
    
  • 相关阅读:
    二分查找小结
    FZU みねちゃんの修罗场(从一堆出现三次的数中找出出现两次的数)
    《C陷阱与缺陷》杂记
    HDU 1846 Brave Game(巴什博弈)
    【转载】并查集详解
    第七次作业——学末总结
    STL之vector
    fzuoop期中练习
    MFC 文件对话框
    第六次作业——利用MFC实现计算器图形界面以及简单四则运算表达式批处理
  • 原文地址:https://www.cnblogs.com/saoqiang/p/12408869.html
Copyright © 2011-2022 走看看