zoukankan      html  css  js  c++  java
  • Python爬虫_高性能爬取

    异步协程

    • event_loop:事件循环,相当于一个无限循环,我们可以把一些函数注册到这个事件循环上,当满足某些条件的时候,函数就会被循环执行。程序是按照设定的顺序从头执行到尾,运行的次数也是完全按照设定。当在编写异步程序时,必然其中有部分程序的运行耗时是比较久的,需要先让出当前程序的控制权,让其在背后运行,让另一部分的程序先运行起来。当背后运行的程序完成后,也需要及时通知主程序已经完成任务可以进行下一步操作,但这个过程所需的时间是不确定的,需要主程序不断的监听状态,一旦收到了任务完成的消息,就开始进行下一步。loop就是这个持续不断的监视器。

    • coroutine:中文翻译叫协程,在 Python 中常指代为协程对象类型,我们可以将协程对象注册到事件循环中,它会被事件循环调用。我们可以使用 async 关键字来定义一个方法,这个方法在调用时不会立即被执行,而是返回一个协程对象。

    • task:任务,它是对协程对象的进一步封装,包含了任务的各个状态。

    • future:代表将来执行或还没有执行的任务,实际上和 task 没有本质区别。

    • 另外我们还需要了解 async/await 关键字,它是从 Python 3.5 才出现的,专门用于定义协程。其中,async 定义一个协程,await 用来挂起阻塞方法的执行。

    基本使用

    #基本使用
    import asyncio
    async def hello(name):
        print('hello to :',name)
    #获取了一个协程对象
    c = hello('shazi')
    
    #创建一个事件循环对象
    loop = asyncio.get_event_loop()
    
    #将协程对象注册到事件循环中,然后启动事件循环对象
    loop.run_until_complete(c)

    task的使用

    import asyncio
    async def hello(name):
        print('hello to :',name)
    
    c = hello('shazi')
    loop = asyncio.get_event_loop()
    #就协程进行进一步的封装,封装到了task对象中
    task = loop.create_task(c)
    print(task)
    loop.run_until_complete(task)
    print(task)
    task的使用

     future的使用

    #future
    import asyncio
    async def hello(name):
        print('hello to :',name)
    
    c = hello('shazi')
    
    task = asyncio.ensure_future(c)
    
    loop.run_until_complete(task)

     绑定回调

    def callback(task):
        print('i am callback:',task.result())
    
    import asyncio
    async def hello(name):
        print('hello to :',name)
        return name
    
    c = hello('shazi')
    
    task = asyncio.ensure_future(c)
    #给任务对象绑定一个回调函数
    task.add_done_callback(callback)
    loop.run_until_complete(task)

    多任务异步协程

    import asyncio
    async def request(url):
        print('正在下载:',url)
        sleep(2) #非异步模块的代码:在此处如果存在非异步操作代码,则会彻底让asyncio失去异步的效果
        print('下载成功:',url)
    urls = [
        'www.baidu.com',
        'www.taobao.com',
        'www.sogou.com'
    ]
    start = time.time()
    loop = asyncio.get_event_loop()
    tasks = [] #任务列表,放置多个任务对象
    for url in urls:
        c = request(url)
        task = asyncio.ensure_future(c)
        tasks.append(task)
        
    #将多个任务对象对应的列表注册到事件循环中
    loop.run_until_complete(asyncio.wait(tasks))
    print('总耗时:',time.time()-start)
        
    失去异步的情况
    import asyncio
    async def request(url):
        print('正在下载:',url)
    #     sleep(2) #非异步模块的代码:在此处如果存在非异步操作代码,则会彻底让asyncio失去异步的效果
        await asyncio.sleep(2)
        print('下载成功:',url)
    urls = [
        'www.baidu.com',
        'www.taobao.com',
        'www.sogou.com'
    ]
    start = time.time()
    loop = asyncio.get_event_loop()
    tasks = [] #任务列表,放置多个任务对象
    for url in urls:
        c = request(url)
        task = asyncio.ensure_future(c)
        tasks.append(task)
        
    #将多个任务对象对应的列表注册到事件循环中
    loop.run_until_complete(asyncio.wait(tasks))
    print('总耗时:',time.time()-start)
    异步

    requests模块是一个非异步模块

    import requests
    async def get_page(url):
        print('正在下载:',url)
        #之所以没有实现异步操作,原因是因为requests模块是一个非异步的模块
        response = requests.get(url=url)
        print('响应数据:',response.text)
        print('下载成功:',url)
    start = time.time()
    urls = [
        'http://127.0.0.1:5000/haha',
        'http://127.0.0.1:5000/heihei',
        'http://127.0.0.1:5000/xixi'
    ]
    tasks = []
    loop = asyncio.get_event_loop()
    for url in urls:
        c = get_page(url)
        task = asyncio.ensure_future(c)
        tasks.append(task)
    loop.run_until_complete(asyncio.wait(tasks))
    print('总耗时:',time.time()-start)
    非异步模块requests

    支持异步的网络请求的模块:aiohttp

    环境安装: pip install aiohttp

     为了更好的显示效果自己搭一个简单的服务器

    from flask import Flask
    import time
    
    app=Flask(__name__)
    @app.route('/haha')
    def haha():
        time.sleep(2)
        return 'Hi haha'
    
    @app.route('/heihei')
    def heihei():
        time.sleep(2)
        return 'Hi heihei'
    
    @app.route('/xixi')
    def xixi():
        time.sleep(2)
        return 'Hi xixi'
    if __name__ == '__main__':
        app.run(threaded=True)
    服务器的简单搭建
    import aiohttp
    import asyncio
    
    async def get_page(url):
        async with aiohttp.ClientSession() as session:
            async with await session.get(url=url) as response:
                page_text = await response.text() #read()  json()
                print(page_text)
    start = time.time()
    urls = [
        'http://127.0.0.1:5000/haha',
        'http://127.0.0.1:5000/heihei',
        'http://127.0.0.1:5000/xixi',
        'http://127.0.0.1:5000/haha',
        'http://127.0.0.1:5000/heihei',
        'http://127.0.0.1:5000/xixi',
        'http://127.0.0.1:5000/haha',
        'http://127.0.0.1:5000/heihei',
        'http://127.0.0.1:5000/xixi'
    ]
    tasks = []
    loop = asyncio.get_event_loop()
    for url in urls:
        c = get_page(url)
        task = asyncio.ensure_future(c)
        tasks.append(task)
    loop.run_until_complete(asyncio.wait(tasks))
    print('总耗时:',time.time()-start)
    异步的网络请求
  • 相关阅读:
    Liunx命令集
    Jenkins,tomcat和jdk安装步骤
    《九悦学车》和《忠金融·惠生活》BUG表
    2020年12月17日总结
    思维导图加上测试用例
    2020年12月15日总结
    双肩包、椅子和电梯的测试用例(测试题)
    fastadmin 前台关联搜索
    composer安装阿里云短信
    php 生成订单号
  • 原文地址:https://www.cnblogs.com/z1115230598/p/10985645.html
Copyright © 2011-2022 走看看