El rastreador coroutine del rastreador pequeño de Python se inicia rápidamente

prefacio

Los reptiles son algo bueno, y los voy a usar recientemente, así que, por cierto, enviaré las pequeñas cosas que solía hacer y escribiré algunos blogs ~

rutina

En primer lugar, está claro que el subproceso no es multiproceso, y el subproceso es esencialmente un solo subproceso, pero la característica de este subproceso es que cuando el subproceso actual ingresa al estado IO, la CPU cambiará automáticamente las tareas para mejorar la eficiencia operativa global del sistema. Sí, esta rutina es en realidad la misma que el mecanismo de multiprocesamiento del sistema operativo. El efecto de la implementación es algo similar al uso de subprocesos múltiples o agrupación de subprocesos, pero la rutina es más liviana, esencialmente un solo subproceso que cambia de un lado a otro.

Las corrutinas se inician rápidamente

Entonces primero entendamos el efecto de esta rutina.
Para usar corrutinas en python, es decir, asincrónicas, necesitamos dominar dos palabras clave, await y async. Por supuesto, también hay una biblioteca que admite rutinas, asyncio.
Veamos primero el código.

import asyncio
import time
# 协程函数
async def do_some_work(x):
    print('doing: ', x)
    await asyncio.sleep(2)
    return 'done {}'.format(x)

# 协程对象
xs = [1,2,3]
# 将协程转成task,并组成list
tasks = []
start  = time.time()
for x in xs:
    c = do_some_work(x)
    tasks.append(asyncio.ensure_future(c))

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

print(time.time()-start

inserte la descripción de la imagen aquí

A primera vista, parece que hemos implementado subprocesos múltiples, así que cambiaré el código.
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
Al ver que no hay 6 segundos, ¿cómo puede ser esto? Si es multiproceso, debe ser de 2 segundos. Entonces , las corrutinas no son de subprocesos múltiples, este es el primer punto

Bueno, dado que no es de subprocesos múltiples, ¿por qué son solo dos segundos?

Las corrutinas se ejecutan de forma asíncrona

Esto es realmente muy simple, antes de que tengamos que hablar sobre un método

asyncio.sleep(2)
es lo que tiene de especial, sí, el punto especial es que esta suspensión es equivalente a realizar una operación IO, ¿entiendes lo que quiero decir?
Esta suspensión es una operación IO

Comenzamos 3 operaciones asincrónicas aquí, y todos los IO se entregaron al sistema para su ejecución, por lo que solo dedicamos 2 segundos al final.

Proceso de trabajo

Bueno, ahora hemos experimentado el resultado, así que es hora de hablar de por qué.
En primer lugar, la primera palabra clave async es declarar este método. El bloque de código es algo asíncrono, lo que equivale a decir
lo que significa await. Es por eso que somos el "secreto" de dos segundos. Esta cosa, cuando descubre que la cosa modificada por ella es una operación de E/S que consume mucho tiempo, le indicará al sistema operativo que realice la operación de E/S y permitirá que la CPU cambie otras tareas. múltiples tareas. .

administración de tareas

Dijimos esas dos palabras clave, entonces la pregunta es quién le dirá al sistema operativo y quién hará el trabajo por mí. En este momento, necesita usar asyncio.
inserte la descripción de la imagen aquí

Así es, esta parte del código.

Por supuesto, hay muchas formas de crear rutinas, pero esta se usa más en rastreadores, así que solo escribo esta aquí, de hecho tres. (Esto es algo similar a furtertask en java)

aiohttp

Ahora es el momento de nuestro rastreo asincrónico. Solicite uno, ¿cuál es el recurso de rastreo? Esta es en realidad una operación de IO. Entonces podemos usar async, pero en este momento, ya no podemos usar solicitudes.

Tienes que usar esto, primero descarga

pip install aiohttp
import asyncio
import time
import aiohttp

#随便访问三次bing主页吧
urls = ["https://cn.bing.com/?FORM=Z9FD1",
        "https://cn.bing.com/?FORM=Z9FD1",
        "https://cn.bing.com/?FORM=Z9FD1"]

async def get_page(url):
    print("开始爬取网站", url)
    #异步块,在执行异步方法的时候加上await才能切换,不然就是串行咯
    async with aiohttp.ClientSession() as session:
        async with await session.get(url) as resp:
            page = await resp.text()
    print("爬取完成->",url)
    return page

tasks = []
start  = time.time()
for url in urls:
    c = get_page(url)
    tasks.append(asyncio.ensure_future(c))

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

print(time.time()-start)

Entonces, ¿qué pasa con esto de aiohttp? ¿Cómo decirlo? Hay muchos métodos que son similares a las solicitudes. Por ejemplo, el método de ahora es el mismo que las solicitudes.Session() (muy similar)

Guardar asíncrono

Habiendo dicho esto, naturalmente también hay aiofiles.

import asyncio
import time
import aiohttp
import aiofiles
#随便访问三次bing主页吧
urls = ["https://cn.bing.com/?FORM=Z9FD1",
        "https://cn.bing.com/?FORM=Z9FD1",
        "https://cn.bing.com/?FORM=Z9FD1"]

async def get_page(url):
    print("开始爬取网站", url)
    #异步块,在执行异步方法的时候加上await才能切换,不然就是串行咯
    async with aiohttp.ClientSession() as session:
        async with await session.get(url) as resp:
            page = await resp.text()
    print("爬取完成->",url)
    # async with aiofiles.open("a.html",'w',encoding='utf-8') as f:
    #     await f.write(page)
    #     await f.flush()
    #     await f.close()
    with open("a.html",'w',encoding='utf-8') as f:
        f.write(page)
        f.flush()
        f.close()
    return page

tasks = []
start  = time.time()
for url in urls:
    c = get_page(url)
    tasks.append(asyncio.ensure_future(c))

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

print(time.time()-start)

Primero, permítanme explicar que esto no es necesariamente mejor que escribir bloques de archivos directamente, ¡y algunas bibliotecas de terceros no lo admiten!

devolución de llamada asíncrona

Ahora guardamos el archivo de forma asíncrona.El problema es que quiero obtener el resultado directamente y luego analizarlo. Así que tenemos que hacer una devolución de llamada asincrónica.
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

import asyncio
import time
import aiohttp
import aiofiles
#随便访问三次bing主页吧
urls = ["https://cn.bing.com/?FORM=Z9FD1",
        "https://cn.bing.com/?FORM=Z9FD1",
        "https://cn.bing.com/?FORM=Z9FD1"]

async def get_page(url):
    print("开始爬取网站", url)
    #异步块,在执行异步方法的时候加上await才能切换,不然就是串行咯
    async with aiohttp.ClientSession() as session:
        async with await session.get(url) as resp:
            page = await resp.text()
    print("爬取完成->",url)
    return page

def parse(task):
    page = task.result() #得到返回结果
    print(len(page))

tasks = []
start  = time.time()
for url in urls:
    c = get_page(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)

Bueno, esto es algo asíncrono. Esta es la razón por la que uso la tarea futura, porque puedo obtener los parámetros. En Java, es la etiqueta de llamada.
A continuación, hay una herramienta de nivel dios, scapy, que se actualizará más adelante (mira la situación, ¡será el viernes!)

Supongo que te gusta

Origin blog.csdn.net/FUTEROX/article/details/123284841
Recomendado
Clasificación