python爬虫---单线程+多任务异步协程

python爬虫—单线程+多任务异步协程

  • 协程
    • 在函数定义(特殊函数)的时候,如果使用了async修饰的化,则该函数调用后会返回一个协程对象,并且函数内部的实现语句不会被立即执行
  • 任务对象
    • 任务对象就是对协程对象的进一步封装。任务对象就等于一个高级的协程对象,就等于特殊的函数。
    • 任务对象时必须要注册到事件循环对象中的。
    • 给任务对象绑定回调:爬虫的数据解析中。
  • 事件循环
    • 当作是一个容器,容器中必须存放任务对象。
    • 当启动事件循环对象时,则事件循环对象会对其内部的存储任务对象进行异步的执行。
  • aiohttp:支持异步发送请求

使用multiprocessing.dummy.Pool

from multiprocessing.dummy import Pool
from time import sleep, time

start = time()


def get_request(url):
    print('正在下载:', url)
    sleep(2)
    print('下载结束:', url)


urls = [
    'http://127.0.0.1:5000/index',
    'http://127.0.0.1:5000/index',
    'http://127.0.0.1:5000/index',
]

# 串行
# for url in urls:
#     get_request(url)
"""
正在下载: https://www.baidu.com/
下载结束: https://www.baidu.com/
正在下载: https://www.cnblog.com/
下载结束: https://www.cnblog.com/
正在下载: https://www.csdn.com/
下载结束: https://www.csdn.com/
6.001115322113037
"""

pool = Pool(3)
pool.map(get_request, urls)  # 自定义函数   列表
"""
正在下载: https://www.baidu.com/
正在下载: https://www.cnblog.com/
正在下载: https://www.csdn.com/
下载结束: https://www.baidu.com/
下载结束: https://www.csdn.com/
下载结束: https://www.cnblog.com/
2.0132570266723633
"""

end = time()
print(end-start)

协程和绑定回调

server.py

from flask import Flask

app = Flask(__name__)
@app.route('/index')
def index():
    return 'hello'


@app.route('/index1')
def index1():
    return 'hello1'


@app.route('/index2')
def index2():
    return 'hello2'


if __name__ == '__main__':
    app.run()

协程.py

import asyncio


# 作为任务对象的回调函数
def callback(task):
    # ask.result() 协程对象函数内部的返回值
    print('i am callback', task.result())

async def test():
    print('i am test')
    return 'haha'

c = test()  # c是一个协程对象
# 封装了一个任务对象
task = asyncio.ensure_future(c)
# 绑定回调
task.add_done_callback(callback)
# 创建了一个事件循环对象
loop = asyncio.get_event_loop()
loop.run_until_complete(task)

多任务协程

import asyncio
import time

start = time.time()


# 在特殊函数内部的实现中不可以出现不支持异步的模块代码
async def get_request(url):
    # time.sleep(2)  # time就不支持异步
    await asyncio.sleep(2)  # 支持异步  等待阻塞操作执行
    print('下载成功:', url)


urls = [
    'http://127.0.0.1:5000/index',
    'http://127.0.0.1:5000/index',
    'http://127.0.0.1:5000/index',
]

tasks = []

for url in urls:
    c = get_request(url)

    # 封装了一个任务对象
    task = asyncio.ensure_future(c)
    tasks.append(task)
# 创建了一个事件循环对象
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))  # 如果有任务阻塞,挂起
print(time.time() - start)
"""
下载成功: http://127.0.0.1:5000/index
下载成功: http://127.0.0.1:5000/index
下载成功: http://127.0.0.1:5000/index
2.0011091232299805
"""

运用到爬虫

import requests
import asyncio
import time
import aiohttp

start = time.time()

urls = [
    'http://127.0.0.1:5000/index',
    'http://127.0.0.1:5000/index1',
    'http://127.0.0.1:5000/index2',
]

tasks = []


async def get_request(url):
    # page_text = requests.get(url).text  # requests 会产生阻塞终止异步
    # return page_text
    async with aiohttp.ClientSession() as s:
        async with await s.get(url=url) as response:
            page_text = await response.text()
            print(page_text)

    return page_text


for url in urls:
    c = get_request(url)
    task = asyncio.ensure_future(c)
    tasks.append(task)

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

print(time.time()-start)  # 0.011995553970336914
# 0.013938665390014648  用aiohttp 后的事件

作业:获取梨视频的视频

猜你喜欢

转载自blog.csdn.net/qq_31910669/article/details/111596447