python异步爬虫示例2

### threading
### 多线程,适合处理IO密集型任务,如网络通信,文件操作等,因为线程具有低开销和轻量级的特点,适合创建大量的并发任务。
import threading
import time

def print_numbers():
    for i in range(1, 6):
        print(f"{threading.current_thread().name}: {i}")
        time.sleep(1)

if __name__ == "__main__":

    print("start!!!")
    # 创建两个线程
    thread1 = threading.Thread(target=print_numbers, name="Thread-1")
    thread2 = threading.Thread(target=print_numbers, name="Thread-2")

    # 启动线程
    thread1.start()
    thread2.start()

    # 等待两个线程结束
    thread1.join()
    thread2.join()

    print("finish!!!")
### Pool
### 创建进程池,适合处理CPU密集型任务,如数值计算,图像处理等,因为进程可以利用多核处理器的并行性能,加速计算过程。
from multiprocessing import Pool
import time


def get_page(str):
    print('正在下载:', str)
    time.sleep(2)
    print('下载成功:', str)

if __name__ == "__main__":
    start_time = time.time()
    # 创建一个具有多个进程的进程池
    with Pool(processes=4) as pool:
        # 在进程池中并行地执行函数 get_page(),传入参数列表 [1, 2, 3, 4, 5]
        pool.map(get_page, [1, 2, 3, 4, 5])

    end_time = time.time()
    print(f'消耗的时间:{end_time - start_time}')
### asyncio
### 利用单线程来处理并发任务,通过事件循环和协程实现异步执行,消耗资源较少,适用于IO密集型任务,如网络通信,文件操作,因为它能够高效的处理大量并发的IO操作。

import asyncio

# 定义协程对象
async def get_request(url):
    print("正在请求的url是:", url)
    # 模拟异步请求
    await asyncio.sleep(2)
    print('请求成功的url:', url)
    return url

# 创建一个事件循环对象
loop = asyncio.get_event_loop()

# loop.create_task和asyncio.ensure_future都是将协程对象包装为任务,并将任务添加到事件循环中
# 其实也可以不必包装成任务,跳过此步骤,直接loop.run_until_complete(get_request('http://www.baidu.com'))
# 只接受协程对象作为参数,如果传递的是可等待对象,它会隐式地调用asyncio.ensure_future()将其包装成任务
task = loop.create_task(get_request('http://www.baidu.com'))
# 可以接受任何可等待对象作为参数,包括协程对象,任务对象,及其他支持“__await__”方法的对象
# task = asyncio.ensure_future(get_request('http://www.baidu.com'))

# 启动事件循环,直到任务完成
result = loop.run_until_complete(task)
print("返回的结果是:", result)

# 关闭事件循环
loop.close()
### asyncio
### 利用单线程来处理并发任务,通过事件循环和协程实现异步执行,消耗资源较少,适用于IO密集型任务,如网络通信,文件操作,因为它能够高效的处理大量并发的IO操作。

import asyncio

# 定义协程对象
async def get_request(url):
    print("正在请求的url是:", url)
    # 模拟异步请求
    await asyncio.sleep(1)
    print('请求成功的url:', url)
    return url

# 回调函数
def callback_func(task):
    print("执行任务完成后的逻辑代码")
    print(task.get_name())

# 创建一个事件循环对象
loop = asyncio.get_event_loop()

# 将协程对象包装为任务,并将任务添加到事件循环中
task = asyncio.ensure_future(get_request('http://www.baidu.com'))

# 添加回调函数,当任务完成时,回调函数被调用,可以处理任务完成后的逻辑
task.add_done_callback(callback_func)

#除此之外,还可以对task如下操作
#取消任务
#task.cancel()
#获取任务结果
#task.result()
#等待任务完成
# await task  #或者 await asyncio.wait([task])
#检查任务状态
#task.status()
#获取任务创建时间
#task.get_created()
#获取任务名称
#task.get_name()
#设置任务名称
#task.set_name('name')
#检验任务是否已经完成
#task.done()

# 启动事件循环,直到任务完成
result = loop.run_until_complete(task)
print("返回的结果是:", result)

# 关闭事件循环
loop.close()
### 多任务协程
import time
import asyncio
import aiohttp


# 异步访问请求
async def getPage(url):
    print("开始爬取网站", url)
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            page_text = await response.text()
            print(page_text)

    print("爬取完成!!!", url)


# 调用异步访问函数
async def main():
    url = 'http://www.baidu.com'
    tasks = [getPage(url) for _ in range(10)]
    await asyncio.gather(*tasks)

async def measure_time():
    beginTime = time.time()
    await main()
    endTime = time.time()
    print("完成时间%d" % (endTime - beginTime))

asyncio.run(measure_time())
### 多任务协程加多进程
### 意外的是,不如多任务协程消耗时间短,之所以如此,是因为多进程会增加额外开销,例如进程间的通信,进程创建和销毁等。
### 所以在某些情况下,单纯使用多任务协程会更有效率。
### 切记,在异步协程中如果出现同步模块相关的代码,那么很有可能出现阻塞,从而无法异步,所以必须保证后续操作也是异步才行
import aiohttp
import asyncio
from aiomultiprocess import Pool
import time

# 异步访问请求
async def get(url):
    # 每一步都是需要挂起的
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            result = await response.text()
            print(result)
            print("下载完成", url)

# 调用异步访问函数
async def request():
    url = 'http://www.baidu.com'
    urls = [url for _ in range(10)]
    async with Pool() as pool:
        result = await pool.map(get, urls)
        return result

if __name__ == '__main__':
    start_time = time.time()
    coroutine = request()
    task = asyncio.ensure_future(coroutine)
    loop = asyncio.get_event_loop()
    loop.run_until_complete(task)
    end_time = time.time()
    print(f'消耗时间secode:{end_time - start_time}')
    loop.close()