python爬虫之JS逆向——并发爬虫

一、进程、线程以及协程的概念

1 进程

进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体

跑起来的程序才叫进程

多道技术:空间复用+时间复用,于是有了进程!

进程一般由程序、数据集合和进程控制块三部分构成

进程状态反映进程执行过程的变化。这些状态随着进程的执行和外界条件的变化而转换
    在三态模型中,进程分为三个基本状态,即运行态、就绪态和阻塞态
    在五态模型中,进程分为新建态、终止态、运行态、就绪态和阻塞态

2 线程

线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。

    一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。
    一个标准的线程由线程ID、当前指令指针(PC)、寄存器和堆栈组成,而进程由内存空间(代码、数据、进程空间、打开的文件)和一个或多个线程组成。

线程也有五种状态:创建、就绪、运行、阻塞和退出。

3 进程与线程的区别

以往所有代码都是一个进程里只有一个线程,该线程是主线程,主线程可以创建子线程

线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;


一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线;


进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)即一些进程级的资源(如打开文件和信号),抹进程内的线程在其他进程不可见;


调度和切换:线程上下文切换比进程上下文切换要快得多。

4 协程

协程,也可称为微线程,或非抢占式的多任务子例程,一种用户态的上下文切换技术(通过一个线程实现代码块间的相互切换执行)。

        这种由程序员自己写程序来管理的轻量级线程叫做 用户空间线程 具有对内核来说不可见的特性。
        正如一个进程可以拥有多个线程一样,一个线程也可以拥有多个协程

        协程解决的是线程的切换开销和内存开销的问题

二、多线程实现——threading

1 threading简单运用

首先导入实现threading库和time库

import time
import threading

 其次构建两个函数用作测试

def foo(t):print("foo开始")time.sleep(t)print("foo结束")def bar(t):print("bar 开始")time.sleep(t)print("bar 结束")

 串行版本:

foo()
bar()

 多线程并发版本:

# 基于多线程的并发
t1 = threading.Thread(target=foo, args=(2, ))  # 构建线程对象
t1.start()  # 调度线程对象
t2 = threading.Thread(target=bar, args=(5, ))  # 构建线程对象
t2.start()  # 调度线程对象
# 此时有三个线程,主线程、t1和t2# 等所有子线程结束后
t1.join()  # t1线程没有结束——阻塞
t2.join()

 构建多个线程:

# 创建多个线程
t_list = []
for i in range(10):t = threading.Thread(target=foo, args=(2,))t.start()t_list.append(t)for t in t_list:t.join()stop = time.time()

2 互斥锁

没有锁的话“并发技术下数据的不安全性“
互斥锁就是舍弃一部分的速度,在计算数据的时候保证数据的安全性

    threading.Lock()创建的lock对象
    lock.acquire()  加锁
    lock.release()  释放锁

import threading
import timelock = threading.Lock()  # 创建锁对象
x = 1000def sub():lock.acquire()  # 加锁global xtemp = x - 1time.sleep(0.0000001)x = templock.release()  # 释放锁# 并发
t_list = []
for i in range(1000):t = threading.Thread(target=sub, args=())t.start()t_list.append(t)for t in t_list:t.join()print(x)

3 线程池

    系统启动一个新线程成本比较高,因为它涉及与操作系统的交互,在这种情形下,使用线程池可以很好的提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑线程池。

    线程池在系统启动时即创建大量空闲的线程,程序只需要将一个函数提交给线程池,线程池就会启动一个空闲的线程来执行它。当该函数执行结束后,该线程不会死亡,而是再次返回到线程池中变成空闲状态,等待执行下一个函数。


    此外,使用线程池可以有效的控制系统中并发线程的数量,当系统中包含有大量的并发线程时,会导致系统性能极具下降,甚至导致解释器崩溃,而线程池的最大线程数参数库控制系统中并发线程的数量不超过此数。

构建线程池的基本方法:

import time
# 引入线程池类
from concurrent.futures import ThreadPoolExecutordef task(i):print(f"任务{i}开始")time.sleep(i)print(f"任务{i}结束")return istart = time.time()
pool = ThreadPoolExecutor(3)
pool.submit(task, 1)  # 1s
pool.submit(task, 2)  # 2s
pool.submit(task, 3)  # 3spool.shutdown()  # 阻塞
print(f"耗时{time.time()-start}s")
print(future_list)
print([future.result() for future in future_list])

循环批量构建线程池:

import time
# 引入线程池类
from concurrent.futures import ThreadPoolExecutordef task(i):print(f"任务{i}开始")time.sleep(i)print(f"任务{i}结束")return istart = time.time()
pool = ThreadPoolExecutor(3)
future_list = []
for i in range(1, 6):# 异步实现并发future = pool.submit(task, i)  # future对象future_list.append(future)# future.result()  # 结束后返回的结果# future.done()  # 返回bool值pool.shutdown()  # 阻塞
print(f"耗时{time.time()-start}s")
print(future_list)
print([future.result() for future in future_list])

4 线程应用——斗图吧案例

单线程版本:

import time
import requests
from lxml import etree# 获取网页并解析
def get_img_urls():res = requests.get("https://www.doutub.com/img_lists/new/1")res.encoding = "utf-8"selector = etree.HTML(res.text)img_names = selector.xpath('//div[@class="cell"]/a/img/@alt')img_urls = selector.xpath('//div[@class="cell"]/a/img/@data-src')return img_names, img_urls# 下载图片
def download_img(name, url):res = requests.get(url)with open(f"单线程斗图吧图片/{name}.jpg", "wb") as f:for i in res.iter_content():f.write(i)start = time.time()
img_names, img_urls = get_img_urls()
for img_name, img_url in zip(img_names, img_urls):download_img(img_name, img_url)print(f"{img_name}下载完成")
print(f"整体耗时{time.time()-start}秒")

多线程版本:

import time
import requests
from lxml import etree
import threading# 获取网页并解析
def get_img_urls():res = requests.get("https://www.doutub.com/img_lists/new/1").textselector = etree.HTML(res)img_names = selector.xpath('//div[@class="cell"]/a/img/@alt')img_urls = selector.xpath('//div[@class="cell"]/a/img/@data-src')return img_names, img_urls# 下载图片
def download_img(name, url):res = requests.get(url)with open(f"多线程斗图吧图片/{name}.jpg", "wb") as f:for i in res.iter_content():f.write(i)print(f"{name}下载完成")start = time.time()
img_names, img_urls = get_img_urls()
t_list = []
for img_name, img_url in zip(img_names, img_urls):t = threading.Thread(target=download_img, args=(img_name, img_url,))t.start()t_list.append(t)for t in t_list:t.join()print(f"整体耗时{time.time()-start}秒")

三、多进程

1 GIL锁

    GIL锁是python的历史遗留问题,使得每一个python程序上都有一把锁,使得不能完全的实现并行,但是不影响并发
    并行指的是在多个CPU上执行各个线程

2 多进程实现

    虽然多进程开销大,但是由于python有GIL锁,如果有多个进程在不同CPU上工作也能使得速度加快
    所以python的并发=多进程+协程
    多进程的代码必须写在'__main__'中

import multiprocessing
import time# multiprocessing.Process拥有和threading.Thread()同样的APIdef foo(t):print(f"任务{t}开始")time.sleep(t)print(f"任务{t}结束")if __name__ == '__main__':start = time.time()# 创建多个进程t_list = []for i in range(1, 6):t = multiprocessing.Process(target=foo, args=(i,))t.start()t_list.append(t)for t in t_list:t.join()stop = time.time()print(f"耗时{stop - start}秒")

四、协程

1 yield

功能1:
迭代器和生成器:优化存储
可以将数据存入,需要的时候再生成,时间换取空间
函数里有yield就不是函数了,返回的是generator对象

# yield:迭代器和生成器 优化存储def get_data():print("start")yield 1  # 暂时返回,保存状态print("come back")yield 2print("come back2")yield 3gen = get_data()
print(gen)  # <generator object get_data at 0x0000017025CDE5F0># gen.send(None)ret = next(gen)
print(ret)
ret = next(gen)
print(ret)
ret = next(gen)
print(ret)

功能2:
实现协程

def foo():print("foo start")yieldprint("foo stop")yielddef bar():print("bar start")yieldprint("bar stop")yieldgen_foo = foo()
gen_bar = bar()next(gen_foo)
next(gen_bar)
next(gen_foo)
next(gen_bar)

2 asyncio模块

asyncio被用作多喝提供高性能Python异步框架的基础,包括网络和网站服务,数据库链接,分布式任务队列等等。
asyncio往往是构建IO密集型和高层级机构化网络代码的最佳选择。

基本使用:

import asyncio
import timeasync def task(i):print(f"任务{i}启动")await asyncio.sleep(i)print(f"任务{i}结束")start = time.time()
# 创建事件循环对象
loop = asyncio.get_event_loop()
# 构建协程对象列表
tasks = [task(1), task(2), task(3)]  # 协程对象 coroutine object
# 启动运行
loop.run_until_complete(asyncio.wait(tasks))  # 阻塞等待所有协程结束
print("用时:", time.time()-start)

另一种方式:

在Windows中,asyncio.run(main())可能不能使用,只能用上面的方式...

import asyncio
import timeasync def foo(i):print(f"任务{i}启动")await asyncio.sleep(i)print(f"任务{i}结束")return i * iasync def main():# 构建任务对象列表tasks = [asyncio.create_task(foo(1)),asyncio.create_task(foo(2)),asyncio.create_task(foo(3))]  # 协程对象 asyncio.Task对象# 收集任务方式1# tasks[0].add_done_callback(lambda obj: print(obj.result()))# await asyncio.wait(tasks)  # 阻塞# for task in tasks:#     print(task.done(), task.result())# 收集任务方式2rets = await asyncio.gather(*tasks)  # 可以传入列表print(rets)start = time.time()
# 简写
asyncio.run(main())print("用时:", time.time()-start)

3 task任务

构建过程:
    对协程对象的进一步封装,包含任务的各个状态;
    asyncio.Task是Future的一个子类,用于实现协作式多任务的库,且Task对象不能用户手动实例化,通过以下两个函数构建:
    loop.create_task()
    asyncio.ensure_future()

task任务在上面的例子中使用到...

五、aiohttp模块

aiohttp可以看作和requests对应的异步网络请求库,是基于asyncio的异步模块,可用于实现异步爬虫
优点:更快于requests的同步爬虫
安装:pip install aiohttp
基本用法:

import aiohttp
import asyncioasync def main():async with aiohttp.ClientSession() as session:async with session.get("http://httpbin.org/headers") as response:print(await response.text())asyncio.run(main())

六、其它

拼接视频 终端输入 ffmpeg -i xx.m3u8 -c copy yy.mp4
代码实现自动化

奉上斗图吧异步并发案例:

import time
from lxml import etree
import asyncio
import aiohttp# 获取网页并解析
async def get_img_urls():async with aiohttp.ClientSession() as session:async with session.get("https://www.doutub.com/img_lists/new/1", ssl=False) as response:selector = etree.HTML(await response.text())img_names = selector.xpath('//div[@class="cell"]/a/img/@alt')img_urls = selector.xpath('//div[@class="cell"]/a/img/@data-src')return img_names, img_urls# 下载图片
async def download_img(name, url):async with aiohttp.ClientSession() as session:async with session.get(url, ssl=False) as response:with open(f"imgs/{name}.jpg", "wb") as f:f.write(await response.content.read())print(f"{name}下载完成!")async def main():img_names, img_urls = await get_img_urls()tasks = [asyncio.create_task(download_img(name, url)) for name, url in zip(img_names, img_urls)]await asyncio.wait(tasks)# 主逻辑
start = time.time()
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(main())
print(f"整体耗时{time.time()-start}秒")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/28728.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DS18B20温度传感器完整使用介绍(配合51单片机)

DS18B20是一款由Maxim Integrated&#xff08;原Dallas Semiconductor&#xff09;生产的数字温度传感器&#xff0c;以其高精度、低功耗、灵活的接口方式和易于使用的特性&#xff0c;在各种温度监测应用中被广泛采用。 以下是DS18B20的详细介绍&#xff1a; 基本特性 数字输…

C++的map

作用&#xff1a; 映射&#xff0c;相当于python的字典&#xff0c;使用一个key来寻找value&#xff0c;m[key]value; 生成&#xff1a; map<int,string> m;//无参生成&#xff0c;key是int类型&#xff0c;value是string类型 map<int,string> m{{1,"hello…

在面试中,如何展现自己的创新能力和团队合作能力

在面试中,展现自己的创新能力和团队合作能力对于求职者来说至关重要。这两个能力是现代职场中不可或缺的素质,能够提升个人的职业竞争力,也对于企业的长远发展具有重要意义。以下是一些建议,帮助你在面试中充分展示这两项关键能力。 一、展现创新能力 举例创新项目 在面试…

【docker实战】使用Dockerfile的COPY拷贝资源遇到的问题

事情是这样的。 在我负责的golang项目中&#xff0c;使用硬代码验证某块逻辑。比如&#xff1a; 于是&#xff0c;为了解决硬代码的问题&#xff0c;我制作了表格工具&#xff1a;【开源项目】Excel数据表自动生成工具v1.0版 – 经云的清净小站 (skycreator.top)。 使用表格工…

Python2.7中os.path模块常用函数记录

在Python 2.7中&#xff0c;os.path模块提供了很多用于处理文件路径的函数。这些函数帮助你进行路径名的组合、分解、查询等操作。以下是一些os.path模块中常用的函数及其简要说明&#xff1a; 注意&#xff1a;不是所有的函数在所有操作系统上都可用 os.path.abspath(path) 返…

C++ 20新特性之std::span

&#x1f4a1; 如果想阅读最新的文章&#xff0c;或者有技术问题需要交流和沟通&#xff0c;可搜索并关注微信公众号“希望睿智”。 为什么要引入std::span 在C中&#xff0c;我们经常需要传递数组或容器的一部分给函数进行处理。通常的做法是使用指针和长度来表示数组的一部分…

『C++11』基础新特性

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 前言 自从C98以来&#xff0c;C11无疑是一个相当成功的版本更新。它引入了许多重要的语言特性和标准…

ADS基础教程21 - 电磁仿真(EM)模型的远场和场可视化

模型的远场和场可视化 一、引言二、操作步骤1.定义参数2.执行远场视图&#xff08;失败案例&#xff09;3.重新仿真提取参数 三、总结 一、引言 本文介绍电磁仿真模型的远场和场可视化。 二、操作步骤 1.定义参数 1&#xff09;在Layout视图&#xff0c;工具栏中点击EM调出…

【递归、搜索与回溯】综合练习二

综合练习二 1.组合2.目标和3.组合总和4.字母大小写全排列 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&#x1f603; 1.组合 题目链接&#xff1a;77. 组…

RabbitMQ实践——定制一致性Hash交换器的路由字段

大纲 Property法定制交换器绑定队列测试 Header法定制交换器绑定队列测试 参考资料 在《RabbitMQ实践——利用一致性Hash交换器做负载均衡》一文中&#xff0c;我们熟悉了一致性Hash交换器的使用方法。默认的&#xff0c;它使用Routing key来做Hash的判断源。但是有些时候&…

Maven 快速入门

Maven 简介 Maven是apache旗下的一个开源项目&#xff0c;是一款用于管理和构建java项目的工具。 依赖管理 方便快捷的管理项目的依赖资源(jar包),避免版本冲突 配置 依赖: 指当前项目运行所需要的(jar包) 在pom.xml 中编写<dependencies> 标签 在<dependencies…

线程池监控是怎么做的?

引言&#xff1a;在现代软件开发中&#xff0c;线程池是一种重要的并发控制机制&#xff0c;它能有效管理和复用线程资源&#xff0c;提升系统的性能和响应速度。然而&#xff0c;随着应用规模的扩大和复杂性的增加&#xff0c;对线程池进行有效监控显得尤为重要。线程池监控不…

bellman-ford——AcWing 853. 有边数限制的最短路99

bellman-ford 定义 贝尔曼-福特&#xff08;Bellman-Ford&#xff09;算法是一种用于在加权有向图中计算单源最短路径的算法。 运用情况 可以处理存在负权边的图。常用于找出图中从一个特定顶点到其他所有顶点的最短路径。 注意事项 时间复杂度相对较高。如果图中包含从源…

计算机毕业设计Django+Vue.js考研推荐系统 考研分数线预测 中公考研爬虫 混合神经网络推荐算法 考研可视化 机器学习 深度学习 大数据毕业设计

Python数据分析与可视化期末项目报告 项目名称&#xff1a; 考研推荐系统数据分析与可视化 学 号&#xff1a; 姓 名&#xff1a; …

【PHP开发工程师系统性教学】——thinkPHP的分页操作,不管有几页,用这个你想分几页就分几页

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

MoneyPrinterPlus:AI自动短视频生成工具,详细使用教程

MoneyPrinterPlus是一款使用AI大模型技术,一键批量生成各类短视频,自动批量混剪短视频,自动把视频发布到抖音,快手,小红书,视频号上的轻松赚钱工具。 之前有出过一期基本的介绍&#xff0c;但是后台收到有些小伙伴说&#xff0c;不知道如何使用。 今天我将会手把手的详细介绍…

怎么加密U盘数据?U盘加密软件哪个好?

U盘是我们在生活和工作中最常用的移动存储设备&#xff0c;而为了避免U盘数据泄露&#xff0c;我们需要使用U盘加密软件来加密保护U盘数据。那么&#xff0c;U盘加密软件哪个好呢&#xff1f;下面我们就一起来了解一下吧。 BitLocker加密 BitLocker是Windows系统提供的磁盘加密…

多种传感器在钢铁工业安全风险监测预警中的应用

中国作为钢铁行业的生产与消费大国&#xff0c;其钢铁冶炼流程的复杂性和长周期性使得各环节中频繁出现的有毒有害、易燃易爆气体以及粉尘等危险物质成为行业安全管理的重大挑战。为了保障工作人员的安全&#xff0c;多种传感器在安全风险监测预警中的应用显得尤为重要。 钢铁产…

1732.找到最高海拔

有一个自行车手打算进行一场公路骑行&#xff0c;这条路线总共由 n 1 个不同海拔的点组成。自行车手从海拔为 0 的点 0 开始骑行。 给你一个长度为 n 的整数数组 gain &#xff0c;其中 gain[i] 是点 i 和点 i 1 的 净海拔高度差&#xff08;0 < i <n&#xff09;。请你…

java从红外图片提取温度,计算超过阈值的温度占总面积的百分比

灰度图是单通道图&#xff0c;像素只有一个值&#xff1a;灰度值。灰度值越高&#xff0c;则图像越亮。 现在我们已经知道我们看到一张灰度图是由许多不同灰度值的像素点构成&#xff0c;而每个像素就是一个越亮的像素&#xff0c;灰度值越高&#xff0c;最高值是255&#xff…