zoukankan      html  css  js  c++  java
  • python爬虫如何提高效率

    开启线程池:

    • 线程池

      • asyncio
        • 特殊的函数
        • 协程
        • 任务对象
          • 任务对象绑定
        • 事件循环
    • from multiprocessing.dummy import Pool

    • map(func,alist):

      • 可以让func回调函数处理alist中的每一个列表元素,这个处理的过程是基于异步。

    In [7]:

    import requests
    import time
    from multiprocessing.dummy import Pool
    start = time.time()
    pool = Pool(3)
    urls = [
        'http://127.0.0.1:5000/index',
        'http://127.0.0.1:5000/index',
        'http://127.0.0.1:5000/index'
    ]
    #用作与网络请求(耗时)
    def req(url):
        return requests.get(url).text
    
    page_text_list = pool.map(req,urls)
    print(page_text_list)
    print('总耗时:',time.time()-start)
    
    
    ['hello bobo!!!', 'hello bobo!!!', 'hello bobo!!!']
    总耗时: 2.1126856803894043
    

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

    1.asyncio初始

    import asyncio
    from time import sleep
    
    #特殊的函数
    async def get_request(url):
        print('正在下载:',url)
        sleep(2)
        print('下载完毕:',url)
    
        return 'page_text'
    #回调函数的定义(普通的函数)
    def parse(task):
        #参数表示的就是任务对象
        print('i am callback!!!',task.result())
    
    #特殊函数的调用
    c = get_request('www.1.com')
    
    #创建一个任务对象
    task = asyncio.ensure_future(c)
    #给任务对象绑定一个回调函数
    task.add_done_callback(parse)
    
    #创建一个事件循环对象
    loop = asyncio.get_event_loop()
    #将任务对象注册到该对象中并且开启该对象
    loop.run_until_complete(task)#让loop执行了一个任务
    
    
    解释:
    - ##### 特殊函数:
    
      - 就是async关键字修饰的一个函数的定义
      - 特殊之处:
        - 特殊函数被调用后会返回一个协程对象
        - 特殊函数调用后内部的程序语句没有被立即执行
    
    - ##### 协程
    
      - 对象,协程==特殊的函数。协程表示的就是一组特定的操作。
    
    - ##### 任务对象
    
      - 高级的协程(对协程的进一步的封装)
        - 任务对象==协程==特殊的函数
          - 任务对象==特殊的函数
      - 绑定回调: 
        - task.add_done_callback(task)
          - 参数task:当前回调函数对应的任务对象
          - task.result():返回的就是任务对象对应的特殊函数的返回值
    
    - ##### 事件循环对象
    
      - 创建事件循环对象
      - 将任务对象注册到该对象中并且开启该对象
      - 作用:loop可以将其内部注册的所有的任务对象进行异步执行
    
    - ##### 挂起:
    
      就是交出cpu的使用权。
    
    多任务异步爬虫:
    import asyncio
    import requests
    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):
        #requests模块不支持异步,中断了整个的异步效果
        page_text = requests.get(url).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)
    
    • 【重点】在特殊函数内部的实现中,不可以出现不支持异步的模块代码,如果出现了,
      则会中断整个的异步效果!!!

    • 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
          
          
              ```python
              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)
        
  • 相关阅读:
    idea 2019 版本的 破解方式
    php-fpm 服务的一些常见配置
    redis通过pipeline提升吞吐量
    redis 简易监控的几种方法
    mongodb查询操作分析
    mongodb监控常用方法
    Linux 系统监控常用命令
    mongodb 认证鉴权那点事
    使用H2数据库进行单元测试
    性能测试-Jmeter3.1 使用技巧
  • 原文地址:https://www.cnblogs.com/zhufanyu/p/11998925.html
Copyright © 2011-2022 走看看