• 异步爬虫


    <!doctype html>

    异步爬虫

    异步爬虫

    基于线程池

    搭建模拟网站,基于Flask框架

    templates设置如下图,Flask框架只能使用jinja2进行渲染

    第二步:

    在templates中创建test.html

    下面是python搭建Flask框架

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    

    from flask import Flask,render_template
    from time import sleep

    实例化一个app

    app = Flask(name)

    创建视图函数&路由地址

    @app.route('/bobo')
    def index_1():
    sleep(2)
    return render_template('test.html')

    @app.route('/jay')
    def index_2():
    sleep(2)
    return render_template('test.html')

    @app.route('/tom')
    def index_3():
    sleep(2)
    return render_template('test.html')

    if name == "main":
    #debug=True表示开启调试模式:服务器端代码被修改后按下保存键会自动重启服务
    app.run(debug=True)

    线程池,异步爬取网站

    import requests
    

    import time
    from multiprocessing.dummy import Pool

    urls = [
    'http://127.0.0.1:5000/bobo',
    'http://127.0.0.1:5000/jay',
    'http://127.0.0.1:5000/tom',
    ]

    def get_request(url):
    page_text = requests.get(url=url).text
    return len(page_text)

    异步代码

    if name == "main":
    start = time.time()
    pool = Pool(3) #开启线程的数量
    #使用get_requests作为回调函数,需要基于异步的形式对urls列表元素进行操作
    result_list = pool.map(get_request, urls)
    pool.map(parse, result_list) #对返回的三张源码数据进行解析
    print('总耗时:',time.time()-start)

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

    特殊函数

    async是asyncio模块特有的关键字,如果不导入,没有这个关键字

    如果一个函数在定义的时候被async修饰后,则该函数就变成了一个特殊的函数

    特殊之处:

    该特殊函数被调用后,函数内部实现语句不会立即执行

    该特殊函数被调用后会立即返回一个协程对象

    协程对象

    对象。通过特殊函数的调用返回一个协程对象

    协程 == 特殊函数 == 实现内容

    协程 == 实现内容

    任务对象

    任务对象就是通过协程对象的封装

    任务 == 实现内容

    任务对象的高级之处:

    • 可以给任务对象绑定回调,绑定方式task.add_done_callback(task_callback)
    • 绑定的回调函数是在任务执行之后才执行回调函数的,并且回调函数的参数是任务对象
    • 回调函数的参数只可以有一个
    • 使用回电函数的参数调用result返回的就是任务对象表示的特殊函数的返回值

    事件循环对象

    他也是一个对象

    作用:

    • 可以将多个任务对象注册/装载到事件循环对象中
    • 如果开启了事件循环后,则其内部注册/装载的任务对象便是的制定操作就会被基于异步的被执行

    创建方式:

    loop = asyncio.ensure_future(c)

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

    loop.run_until_complete(task)

    import requests
    import asyncio
    async def get_requests(url):
        print('正在请求url', url)
        time.sleep(2)
        print('请求结束', url)
        return 'bbbb'
    

    def task_callback(t):
    print('我是回掉函数,参数t', t)
    print('t.result返回的是:', t.result()) #返回的是协程对象的返回值,也就是任务对象的返回值
    if name == "main":
    #c就是一个协程对象
    c = get_request('www.1.com')

    #任务对象就是对携程对象的进一步封装
    task = asyncio.get_event_loop()
    
    #任务对象绑定一个回调函数,回掉函数是在任务执行之后才执行
    task.add_done_callback(task_callback)
    
    #将任务对象注册到事件循环中且开启事件循环
    loop.run_until_complete(task)
    

    多任务

    import asyncio
    import requests
    

    async def get_request(url):
    print('正在请求url', url)
    await asynico.sleep(2) #await保证我们的阻塞不被跳过
    print('请求结束', url)
    return 'bbbb'
    urls = [
    'www.1.com',
    'www.2.com',
    'www.3.com',
    ]
    if name == "main":
    tasks = [] #多任务列表
    #1.创建协程对象
    for url in urls:
    c = get_requet(url)
    task =asyncio.ensure_future(c)
    tasks.append(task)

    #3创建事件循环对象
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.wait(tasks))
    #wait作用是可以将任务列表中的任务对象进行挂起操作。(每一个对象都可以被挂起)
    

    wait方法作用:

    将任务对象列表中的任务对象赋予可被挂起的权限。只有任务对象赋予了可被挂起权限后任务对象才可以被挂起

    挂起:将当前的任务对象交出cpu的使用权

    如果异步之中出现不支持异步模块,程序会被终止

    request,time模块不支持异步

    await关键字作用

    在特殊函数内部,凡是阻塞操作执行前都必须使用await进行修饰。await保证我们的阻塞在异步执行过程中不被跳过

    
    import requests
    import asyncio
    import aiohttp   #支持异步的网络请求模块
    

    async def get_request(url):
    async with aiohttp.ClientSession() as sess:
    #调用get发起请求,返回一个响应对象
    #get/post(url, headers,params/data,proxy="字符串")
    async with await sess.get(url) as response:
    #获取了字符串形式的响应数据
    page_text = await response.text()
    return page _text
    urls = [
    'http://127.0.0.1:5000/bobo',
    'http://127.0.0.1:5000/jay',
    'http://127.0.0.1:5000/tom'
    ]
    if name == "main":
    start = time.time()
    tasks = [] #多任务列表
    #1.创建协程对象
    for url in urls:
    c = get_request(url)
    #2.创建任务对象
    task = asyncio.ensure_future(c)
    tasks.append(task)

    #3.创建事件循环对象
    loop = asyncio.get_event_loop()
    # loop.run_until_complete(tasks)
    #必须使用wait方法对tasks进行封装才可
    loop.run_until_complete(asyncio.wait(tasks))
    print(&#39;总耗时:&#39;, time.time()-start)
    

  • 相关阅读:
    工作总结(二):Web Design
    工作总结(一):Linux C
    三十分钟学会AWK
    MySQL并发复制系列二:多线程复制 2016
    修改MySQL 5.7.9版本的root密码方法以及一些新变化整理
    sync_binlog innodb_flush_log_at_trx_commit 浅析
    MariaDB的"response time"插件
    Python学习九:列表生成式
    python中的深拷贝和浅拷贝理解
    Mycat 配置
  • 原文地址:https://www.cnblogs.com/g15009428458/p/12568902.html
Copyright © 2020-2023  润新知