首页 > 其他分享 >单/多线程--协程--异步爬虫

单/多线程--协程--异步爬虫

时间:2024-07-06 19:30:11浏览次数:20  
标签:异步 协程 -- 线程 time print sleep 多线程 asyncio

免责声明:本文仅做技术交流与学习... 

目录

了解进程和线程

单个线程(主线程)在执行

多线程

线程池

协程(爬虫多用)

假异步:(同步)

真异步:

爬虫代码模版

异步-爬虫

同步效果--19+秒

异步效果--7+秒


了解进程和线程

​
# -------------------->
# ------>
#       ------->
#               -------->
​
# 1-线程
#线程:执行一个软件后的操作---点赞,签到,评论等等
#进程:执行一个软件
​
​
一家公司里面人去做事.
1人,2人,多人...
(要合理分配,合理运用.)
--30万的资本,养不起10000人呀.
​
1个进程必须要有一个线程,--- 线程不是越多越好.
单线程/多线程
​
​
进程:资源单元
线程:执行单元
​
​
​
​
# 每一个py程序默认都有一个线程的,
print("111")
​

单个线程(主线程)在执行


多线程

from threading import Thread
# alt + enter 快捷键导包
​
def func(name):
    for i in range(1, 1000):
        print("func函数在执行---" + str(i),name)
​
​
# func()  # 这样写就是主线程执行.
​
# 创建线程对象,分配线程的任务是func   (公司招人要分配任务)
t = Thread(target=func,args=('my name xiaodi',))   # args的参数必须是一个元组.
# 启动线程:                       (员工先忙完手头工作,然后真正工作)
t.start()   # 线程的状态,可以开始工作的状态了,具体的执行时间由CPU决定.
​
t1 = Thread(target=func,args=('xiaosedi',))
t1.start()
​
# 主线程不会受到子线程(其他线程)的干扰.  主线程该干什么就干什么.
for i in range(1, 1000):
    print("主---" + str(i))
# 多个线程都输出到控制台上,就会乱.
​
# 传参在创建线程对象时也要传.
​
# 线程数由电脑的CPU决定,如果处理不好,反而会效率下降.
​


线程池

# 线程池 :一次性开辟一些线程,直接给线程池提交任务,具体的任务到底哪个线程执行,是由线程池分配的
from concurrent.futures.thread import ThreadPoolExecutor
​
​
def func(name):
    for i in range(1000):
        print(name, 'func函数执行', i)
​
​
# 创建一个有50个线程的线程池.(合理的利用资源~)
# -----执行10次func函数,每个func函数执行1000次.
with ThreadPoolExecutor(50) as t:
    #     t = ThreadPoolExecutor(50)
    for i in range(10):
        # 给线程去提交任务
        t.submit(func, name=f'线程{i}')
​
# 等待线程池中的任务全部执行完毕,才会继续执行
print('print执行了')


协程(爬虫多用)

import asyncio
import time
​
def func():
    print("函数开始")
    time.sleep(3)   # 当到此时,当前线程为阻塞状态,CPU不会为当前程序提供工作.
    print("函数结束")
func()
​
# 阻塞代码:(必须要等待某个结果等等
# input(等待输入)   time.sleep(强制等待)    requests(请求网络,client<->server有时间差,
# 程序基于 i(input) o(output) 操作时,线程机会处于阻塞状态,CPU就不会提供工作.
# ---阻塞的时候就会干等着,---怎么让CPU在干等着的时候也做点事情呢?--->协程!!!
​
# 协程:当程序遇见了io操作的时候,可以选择性的切换到其它任务上。
# 多任务异步操作:

假异步:(同步)

import asyncio
import time
​
​
async def func1():
    print('func1函数开始')
    time.sleep(3)  # 属于同步操作代码。
    # 只要在异步程序中出现了同步操作,异步就被中断
    # await asyncio.sleep(3)
    print('func1函数结束')
​
​
async def func2():
    print('func2函数开始')
    time.sleep(2)
    # await asyncio.sleep(2)
    print('func2函数结束')
​
​
async def func3():
    print('func3函数开始')
    time.sleep(4)
    # await asyncio.sleep(4)
    print('func3函数结束')
​
​
# 拿到函数的对象
f1 = func1()
f2 = func2()
f3 = func3()
tasks = [
    # 创建一个任务
    f1, f2, f3
]
start = time.time()
# 如果是多个任务,需要一个asyncio.wait(任务列表)搭配
asyncio.run(asyncio.wait(tasks))
print(time.time() - start)
​

9+秒结束!!! ---没有异步呀---

因为time是一个同步模块,

time.sleep()  # 属于同步操作代码。
# 只要在异步程序中出现了同步操作,异步就被中断

真异步:

import asyncio
import time
​
​
async def func1():
    print('func1函数开始')
    # time.sleep(3)         # 属于同步操作代码
    await asyncio.sleep(3)  # 异步休眠代码       --不是强制性的休眠,而是挂起,让他先去忙别的东西,等好了再回来.
    print('func1函数结束')
​
​
async def func2():
    print('func2函数开始')
    # time.sleep(2)
    await asyncio.sleep(2)
    print('func2函数结束')
​
​
async def func3():
    print('func3函数开始')
    # time.sleep(4)
    await asyncio.sleep(4)
    print('func3函数结束')
    
    
#async def main():
#     f1 = func1()
#     f2 = func2()
#     f3 = func3()
#     tasks = [
#         f1,f2,f3
#         # 创建一个任务
#         # asyncio.create_task(func1()),
#         # asyncio.create_task(func2()),
#         # asyncio.create_task(func3())
#     ]
#     await asyncio.wait(tasks)
# start = time.time()
# asyncio.run(main())
# print(time.time() - start)
​
f1 = func1()
f2 = func2()
f3 = func3()
tasks = [
    f1, f2, f3
    # 创建一个任务
]
​
start = time.time()
# 如果是多个任务,需要一个asyncio.wait(任务列表)搭配
asyncio.run(asyncio.wait(tasks))
print(time.time() - start)

4+秒 , 好快呀...


爬虫代码模版

import asyncio
​
​
async def download(url):
    print('准备开始下载')
    # await asyncio.sleep(2) # 网络请求
    # requests.get(url)      # 异步效果中断,那怎么结合呢???
    print('下载完成')
​
​
async def main():
    urls = [
        '地址1',
        '地址2',
        '地址3',
    ]
    # tasks = []
    # for url in urls:
    #    tasks.append(download(url))
​
    # 列表推导式写法 循环url列表,每循环一次,创建一个任务
    tasks = [download(url) for url in urls]
    await asyncio.wait(tasks)
​
​
asyncio.run(main())
​

requests.get(url) # 异步效果中断,那怎么结合呢???

只要出现同步操作,异步就会被终断.

-------->


异步-爬虫

因为requests模块是同步的,如果在异步协程中编写同步代码,异步效果没有。
​
如何解决?
更换支持异步的请求模块
aiohttp  == requests
pip install aiohttp
pip install aiofiles

同步效果--19+秒

import time
import requests
​
urls = [
    'https://www.cgwallpapers.com/wallpapers_free_wreoiux/wallpaper_christian_dimitrov_02_1920x1080.jpg',
    'https://www.cgwallpapers.com/wallpapers_free_wreoiux/wallpaper_pablo_carpio_17_1920x1080.jpg',
    'https://www.cgwallpapers.com/wallpapers_free_wreoiux/wallpaper_dejian_wu_04_1920x1080.jpg'
]
t = time.time()
for url in urls:
    res = requests.get(url).content
    # 文件名
    name = url.split('/')[-1]
    with open(name, 'wb') as f:
        f.write(res)
print(f'requests花费时间===》{time.time() - t}')
# requests花费时间===》19.635247230529785

异步效果--7+秒

import asyncio
import time
import aiofiles
import aiohttp
urls = [
    'https://www.cgwallpapers.com/wallpapers_free_wreoiux/wallpaper_christian_dimitrov_02_1920x1080.jpg',
    'https://www.cgwallpapers.com/wallpapers_free_wreoiux/wallpaper_pablo_carpio_17_1920x1080.jpg',
    'https://www.cgwallpapers.com/wallpapers_free_wreoiux/wallpaper_dejian_wu_04_1920x1080.jpg'
]
async def download(url):
    print('准备开始下载--->')
    # s = aiohttp.ClientSession()  == requests              #拿到对象
    # s.get() s.post  ===  requests.get() requests.post()
    # --------------------------------------
    # aiohttp                    requests
    # res.text()                  res.text
    # res.read()                  res.content
    # res.json()                  res.json()
    # --------------------------------------
    async with aiohttp.ClientSession() as s:
        async with s.get(url) as res:
            # 写入文件
            name = url.split('/')[-1]
            # 文件正常操作:
            # with open(name,'wb')as f:
            #     f.write(await res.read())
            # 文件异步操作:
            async with aiofiles.open(name, 'wb') as f:
                await f.write(await res.read())
    print('下载完成')
async def main(urls):
    tasks = [download(url) for url in urls]
    await asyncio.wait(tasks)
t = time.time()
asyncio.run(main(urls))
print(f'aiohttp花费时间===》{time.time() - t}')
# aiohttp花费时间===》7.244250774383545
​

标签:异步,协程,--,线程,time,print,sleep,多线程,asyncio
From: https://blog.csdn.net/2303_80857229/article/details/140234148

相关文章

  • Codeforces Round 951 (Div. 2)
    Preface这场由于下午四点约好了和祁神打乒乓球,因此两点开了一场VP,结果困得要死D题一个特判写挂了没看出来调了贼久然后E题秒出正解,但因为一个极其傻逼的地方挂了又没调出来,鉴定为纯纯的飞舞A.GuesstheMaximum签到,每次选的一定是相邻的两个#include<cstdio>#include<iost......
  • 大语言模型与知识图谱结合发展方向
    引言在人工智能的发展历程中,大语言模型(LLM)的出现标志着一个重要的转折点。随着深度学习技术的突破和计算能力的提升,LLM以其前所未有的规模和复杂性,开启了迈向人工通用智能(AGI)的新浪潮。模型通过海量数据的预训练,不仅能够理解自然语言,还能够生成连贯、逻辑性强的文本,但存在......
  • 基于51单片机的交通灯设计(含文档、源码与proteus仿真,以及系统详细介绍)
    目录引言实验环境原理图仿真图1设计任务与方案选择2 系统设计3 系统调试4 总结5 参考文献资源下载引言近年来随着科技的飞速发展,单片机的应用正在不断深入,同时带动传统控制检测技术日益更新。在实时检测和自动控制的单片机应用系统中,单片机往往作为一个核......
  • 计算云服务1
     前言一直以来,计算资源都是整个企业业务系统发展所需的大动脉,没有计算资源,企业业务就无法正常运行。在云计算的时代里,计算服务也是云服务中的第一大类服务,计算资源的重要性由此可见。本章,我们将带领大家了解华为云上的计算服务。目标学完本课程后,您将能够:掌握华为云上常......
  • 四种常见的Http请求方式
    在Web服务的开发中,HTTP协议是最常使用的协议。其中,常见的HTTP请求方式有四种:POST、GET、DELETE 和 PUT。本文将详细介绍这四种请求方式的概念、用法、优缺点以及常见应用场景。1.HTTP请求方式HTTP(HypertextTransferProtocol)是一种在计算机网络中用于传输超媒体文......
  • LSS (Lift, Splat, Shoot)论文精读
    图1:我们提出了一个模型,该模型给定多视图相机数据(左侧),直接在鸟瞰视图(BEV)坐标系(右侧)中推断语义。我们展示了车辆分割(蓝色)、可行驶区域(橙色)和车道分割(绿色)。然后,这些BEV预测被投影回输入图像(左侧的点)。论文地址:Lift,Splat,Shoot:EncodingImagesfromArbitrar......
  • 清华&地平线!SparseDrive:端到端自动驾驶 论文精读
    论文地址:SparseDrive:End-to-EndAutonomousDrivingviaSparseSceneRepresentation源代码:SparseDrive摘要    传统的模块化自动驾驶系统被分解为不同的独立任务,例如感知、预测和规划,这导致了信息丢失和跨模块的误差累积。相比之下,端到端范式将多任务统一到一个......
  • Linux常用面试题
    系统部分1、在linux系统中,获取命令帮助的方法有哪些?   man(查看手册页)    help(查看内部命令)   --help(查看外部命令)2、列举find命令的用法?(主要说明使用的选项及其含义)   find查找文件或目录      -name   根据目标的名称进程查找,允许使......
  • Linux系统管理面试题
    中级系统管理面试题训练内容:1)编译安装源代码的过程?      从官方网站下载源码包校验md5值   解压   tar命令解包      配置   进入解压目录配置,指定对应的模块、解包的路径   编译   源代码编译成二进制文件      安装 ......
  • HTTP请求详解及其在嵌入式系统中的应用
    前言HTTP(HyperTextTransferProtocol,超文本传输协议)是互联网中最广泛使用的应用层协议,用于客户端和服务器之间的数据传输。了解HTTP请求的工作原理对于开发网络应用和嵌入式系统中的网络通信至关重要。本文将详细介绍HTTP请求的基本概念、类型、结构,并探讨其在嵌入式系统中的......