100天玩转python语言
文章平均质量分 86
本专栏专门针对零基础和需要进阶提升的同学所准备的一套完整教学,从0到100的不断进阶深入
程序员小马软件开发定制
10年软件开发经验,app开发,小程序开发,软件定制开发,物联网项目、政企信息化建设等软件技术服务、手机软件、电商商城、分销系统、拼团团购
知无不言,欢迎私信
展开
-
99-100.面试中的公共问题
REST数据接口如何设计(URL、域名、版本、过滤、状态码、安全性)。关系型数据库相关问题(ACID、事务隔离级别、锁、SQL优化)。进程和线程之间的关系。非关系型数据库相关问题(CAP/BASE、应用场景)。使用ORM框架实现CRUD操作的相关问题。如何实现页面缓存和查询缓存?中间件的执行流程以及如何自定义中间件。HTTP和HTTPS相关问题。生成式、生成器、迭代器的编写。列表、集合、字典的底层实现。如何执行异步任务和定时任务。装饰器的作用、原理和实现。协程和异步I/O相关知识。使用过哪些魔法方法。原创 2023-11-25 11:30:26 · 923 阅读 · 0 评论 -
98.项目部署上线和性能调优
是一个用Python写的进程管理工具,可以很方便的用来在类Unix系统下启动、重启(自动重启程序)和关闭进程,目前Supervisor暂时还没有提供对Python 3的支持,可以通过Python 2来安装和运行Supervisor,再通过Supervisor来管理Python 3的程序。按照下面的方式可以启动uWSGI服务器。到此为止,我们可以启动Nginx来访问我们的应用程序,HTTP和HTTPS都是没有问题的,如果Nginx已经运行,在修改配置文件后,我们可以用下面的命令重新启动Nginx。原创 2023-11-25 11:29:46 · 1047 阅读 · 0 评论 -
97.电商网站技术要点剖析
第三方登录是指利用第三方网站(通常是知名社交网站)的账号进行登录验证(主要是通过知名第三方网站获取到用户相关信息),比如国内的 QQ、微博,国外的Google、Facebook等。第三方登录大部分都是使用。静态资源的管理可以自己架设文件服务器或者分布式文件服务器(FastDFS),但是一般的项目中没有必要这样做而且效果未必是最好的,我们建议使用云存储服务来管理网站的静态资源,国内外的云服务提供商如。等都提供了非常优质的云存储服务,而且价格也是一般公司可以接受的,具体的操作可以参考官方文档,例如:阿里云的。原创 2023-11-24 14:54:55 · 1242 阅读 · 0 评论 -
96.软件测试和自动化测试
软件测试是一种用来促进鉴定软件的正确性、完整性、安全性和品质的过程,也就是在规定的条件下对程序进行操作以发现程序中的错误,衡量软件的品质并对其是否能满足设计要求进行评估的过程。原创 2023-11-24 14:53:06 · 821 阅读 · 0 评论 -
95.使用Django开发商业项目
问题1:描述一个Web应用的工作流程。问题2:描述项目的物理架构。(上图中补充负载均衡(反向代理)服务器、数据库服务器、文件服务器、邮件服务器、缓存服务器、防火墙等,而且每个节点都有可能是多节点构成的集群。当然,架构都是根据业务的需要一步步演进而不是一蹴而就的。)问题3:描述Django项目的工作流程。(如下图所示)问题1:为什么要使用MVC架构模式?(模型和视图解耦合)问题2:MVC架构中每个部分的作用?(如下图所示)对象的属性和方法:中间件添加的属性:对象的属性和方法:(的子类型)对象数据模原创 2023-11-23 11:59:42 · 142 阅读 · 0 评论 -
94.网络API接口设计
如果API接口的设计是根据用户的操作或者界面上的功能设置来设计,随着需求的变更,用户界面也会进行调整,需要的数据也在发生变化,那么后端开发者就要不停的调整API,或者给一个API设计出多个版本,这些都会使项目的开发和维护成本增加。API是应用程序的编程接口的缩写,网络API通常指的是基于一个URL(统一资源定位符)可以访问到的资源,也就是说通过这个URL我们就可以请求服务器对某个资源进行操作并返回操作的结果。,当然这两篇文章大家也要批判的阅读,因为上面阐述的观点并不完全正确,有些内容甚至是自相矛盾的。原创 2023-11-23 11:55:35 · 105 阅读 · 0 评论 -
93.MySQL性能优化
数据表设计的规范程度称之为范式(Normal Form),要提升表的规范程度通常需要将大表拆分为更小的表,范式级别越高数据冗余越小,而且在插入、删除、更新数据时出问题的可能性会大幅度降低,但是节省了空间就意味着查询数据时可能花费更多的时间,原来的单表查询可能会变成连表查询。调用存储过程可以简化应用程序开发人员的工作,减少与数据库服务器之间的通信,对于提升数据操作的性能是有帮助的,这些我们在之前的。MySQL支持做数据分区,通过分区可以存储更多的数据、优化查询,获得更大的吞吐量并快速删除过期的数据。原创 2023-11-22 12:03:03 · 34 阅读 · 0 评论 -
88-92.Docker容器技术详解
软件开发中最为麻烦的事情可能就是配置环境了。由于用户使用的操作系统具有多样性,即便使用跨平台的开发语言(如Java和Python)都不能保证代码能够在各种平台下都可以正常的运转,而且在不同的环境下我们安装的软件需要依赖的软件包也是不一样的。那么问题来了,我们安装软件的时候可不可以把软件运行的环境一并安装?我们是不是可以把原始环境一模一样地复制过来呢?原创 2023-11-22 12:01:44 · 87 阅读 · 0 评论 -
87.团队项目开发的问题和解决方案
Git是诞生于2005年的一个开源分布式版本控制系统,最初是Linus Torvalds(Linux之父) 为了帮助管理Linux内核开发而开发的一个版本控制软件。Git与常用的版本控制工具Subversion等不同,它采用了分布式版本控制的方式,在没有中央服务器支持的环境下也能够实施版本控制。Git是分布式的,SVN是集中式的,SVN需要中央服务器的支持才能工作。Git把内容按元数据方式存储,而SVN是按文件,即把文件的元信息隐藏在一个.svn文件夹里。原创 2023-11-21 12:05:22 · 367 阅读 · 0 评论 -
86.k最近邻分类
值,就相当于用较小的邻域中的训练实例进行预测,“学习”的近似误差会减小,只有与输入实例较近(相似的)训练实例才会对预测结果起作用;但缺点是“学习”的估计误差会增大,预测结果会对近邻的实例点非常敏感,如果近邻的实例点刚好是噪声,预测就会出错。值,就相当于用较大的邻域中的训练实例进行预测,其优点是可以减少学习的估计误差,但缺点是学习的近似误差会增大。代表所有的训练实例的数量),那么无论输入实例是什么,都会预测它属于训练实例中最多的类,很显然,这样的模型完全忽略了训练实例中大量的有用信息,是不可取的。原创 2023-11-21 11:53:42 · 119 阅读 · 0 评论 -
85.人工智能和机器学习概述
所谓“人工智能”通常是泛指让机器具有像人一样的智慧的技术,其目的是让机器像人一样能够感知、思考和解决问题;而“机器学习”通常是指让计算机通过学习现有的数据,实现认知的更新和进步。显然,机器学习是实现人工智能的一种途径,这也是我们的课程要讨论的内容。原创 2023-11-20 11:21:00 · 273 阅读 · 0 评论 -
84.方差分析和参数估计
在实际生产环境中,可能无法获得所有的数据,或者即便获取了所有的数据,但是没有足够的资源来分析所有的数据,在这种情况下,我们都需要用非常小量的样本特征去评估总体数据的特征,这其中的一项工作就是参数估计。蓝色分组的购买率平均值(蓝色线)比整体平均值(黑色线)要高,有可能是最右边那个很高的购买率把分组的均值抬升的,同时蓝色分组的数据分布很散(方差大),此时不能有十足把握说明该组用户的购买转化率很高。如下图所示,对于上面蓝色和绿色分组的“组内方差”,显然蓝色的组内方差更大,绿色的组内方差更小。原创 2023-11-20 11:17:45 · 469 阅读 · 0 评论 -
83.相关和回归
我们可以通过历史数据(已知的 $ X $ 和 $ Y $ ),确定参数 $ a $ 和 $ b $ 的值,还原出回归方程,从而实现预测。如果把真实值记为 $ y $,把预测值记为 $ \hat{y} $,那么让 $ SSR $ 值最小的 $ a $ 和 $ b $ 就是最好的 $ a $ 和 $ b $ ,称之为。留存的运营中我们最常看的就是新客的留存和活跃客群的留存,用来评估哪个客群的留存与整体的留存联系更紧密,以便制定后续运营的策略。的值,可以通过向凹函数的拐点进行逼近的方式来找到更好的。原创 2023-11-19 12:08:50 · 21 阅读 · 0 评论 -
82.概率基础
描述性统计通常用于研究表象,将现象用数据的方式描述出来(用整体的数据来描述整体的特征);推理性统计通常用于推测本质(通过样本数据特征去推理总体数据特征),也就是你看到的表象的东西有多大概率符合你对隐藏在表象后的本质的猜测。原创 2023-11-19 12:08:11 · 41 阅读 · 0 评论 -
81.NumPy的应用-2
属性对应的元组中最后一个元素的值(从后往前数最后一个维度的值),例如,我们之前打开的图像对应的数组后缘维度为3,3行4列的二维数组后缘维度为4,而有5个元素的一维数组后缘维度为5。简单的说,只有两个数组后缘维度相同或者其中一个数组后缘维度为1时,广播机制会被触发,而通过广播机制如果能够使两个数组的形状一致,才能进行二元运算。上面的例子中,两个二元运算的数组形状是完全相同的,我们再来研究一下,两个形状不同的数组是否可以直接做二元运算或使用二元函数进行运算,请看下面的例子。中的数据执行元素级运算的函数。原创 2023-11-18 11:04:56 · 19 阅读 · 0 评论 -
80.NumPy的应用-1
切片操作虽然创建了新的数组对象,但是新数组和原数组共享了数组中的数据,简单的说,如果通过新数组对象或原数组对象修改数组中的数据,其实修改的是同一块数据。花式索引和布尔索引也会创建新的数组对象,而且新数组复制了原数组的元素,新数组和原数组并不是共享数据的关系,这一点通过前面讲的数组的。,对于同样的数值计算任务,使用 NumPy 不仅代码要简洁的多,而且 NumPy 的性能远远优于原生 Python,基本是一个到两个数量级的差距,而且数据量越大,NumPy 的优势就越明显。通过上面的代码可以发现,原创 2023-11-18 11:04:20 · 21 阅读 · 0 评论 -
79.Pandas的应用-4
例如,我们要“统计每个销售区域的销售总额”,那么“销售区域”就是我们的 A 列,而“销售额”就是我们的 B 列,在。上面的例子中,“统计每个销售区域每个月的销售总额”会产生一个看起来很长的结果,在实际工作中我们通常把那些行很多列很少的表成为“窄表”,如果我们不想得到这样的一个“窄表”,可以使用。一图胜千言,我们对数据进行透视的结果,最终要通过图表的方式呈现出来,因为图表具有极强的表现力,能够让我们迅速的解读数据中隐藏的价值。,但也是一个长长的“窄表”,如果希望做成一个行比较少列比较多的“宽表”,可以将。原创 2023-11-17 14:50:48 · 56 阅读 · 0 评论 -
78.Pandas的应用-3
实际工作中,有些异常值可能是由系统或人为原因造成的,但有些异常值却不是,它们能够重复且稳定的出现,属于正常的极端值,例如很多游戏产品中头部玩家的数据往往都是离群的极端值。离散化也叫分箱,如果变量的取值是连续值,那么它的取值有无数种可能,在进行数据分组的时候就会非常的不方便,这个时候将连续变量离散化就显得非常重要。之所以把离散化叫做分箱,是因为我们可以预先设置一些箱子,每个箱子代表了数据取值的范围,这样就可以将连续的值分配到不同的箱子中,从而实现离散化。中的数据也可能存在格式不统一、量纲不统一等各种问题。原创 2023-11-17 14:49:48 · 34 阅读 · 0 评论 -
77.Pandas的应用-2
如果需要上面例子中的 CSV 文件,可以通过下面的百度云盘地址进行获取,数据在《从零开始学数据分析》目录中。参数是一个 Lambda 函数,通过该 Lambda 函数指定只读取 Excel 文件的表头和其中 10%的数据,跳过其他的数据。有的时候,我们做数据分析需要的原始数据可能并不是来自一个地方,就像上面的例子中,我们从关系型数据库中读取了三张表,得到了三个。则代表了基于哪个列实现表的合并,相当于 SQL 表连接中的连表条件,如果左右两表对应的列列名不同,可以用。,然后再运行上面的代码。原创 2023-11-16 14:08:36 · 82 阅读 · 0 评论 -
76.Pandas的应用-1
print(ser2['一季度'], ser2['三季度'])ser2['一季度'] = 380350 300一季度 380二季度 180三季度 300四季度 360。原创 2023-11-16 14:07:44 · 20 阅读 · 0 评论 -
75.常见反爬策略及应对方案
代理服务 - 快代理 / 讯代理 / 芝麻代理 / 蘑菇代理 / 云代理。User-Agent - 三方库fake-useragent。OCR(Tesseract) - 商业项目一般不考虑。专业识别平台 - 超级鹰 / 云打码。洋葱路由 - 国内需要翻墙才能使用。检查网站生成的Cookie。构造合理的HTTP请求头。处理表单中的隐藏域。处理表单中的验证码。原创 2023-11-16 14:00:30 · 625 阅读 · 0 评论 -
74.Scrapy分布式实现
Scrapy爬虫框架分布式实现分布式爬虫原理Scrapy分布式实现安装Scrapy-Redis。配置Redis服务器。修改配置文件。SCHEDULER = ‘scrapy_redis.scheduler.Scheduler’DUPEFILTER_CLASS = ‘scrapy_redis.dupefilter.RFPDupeFilter’REDIS_HOST = ‘1.2.3.4’REDIS_PORT = 6379REDIS_PASSWORD = ‘1qaz2wsx’SCHEDUL原创 2023-11-16 13:57:52 · 19 阅读 · 0 评论 -
73.Scrapy高级应用
在Scrapy框架中,我们自定义的蜘蛛都继承自scrapy.spiders.Spider,这个类有一系列的属性和方法,具体如下所示:原创 2023-11-16 13:57:20 · 64 阅读 · 0 评论 -
72.Scrapy入门
Scrapy是Python开发的一个非常流行的网络爬虫框架,可以用来抓取Web站点并从页面中提取结构化的数据,被广泛的用于数据挖掘、数据监测和自动化测试等领域。下图展示了Scrapy的基本架构,其中包含了主要组件和系统的数据处理流程(图中带数字的红色箭头)。原创 2023-11-16 13:56:48 · 18 阅读 · 0 评论 -
71.表单交互和验证码处理
光学字符识别(OCR)是从图像中抽取文本的工具,可以应用于公安、电信、物流、金融等诸多行业,例如识别车牌,身份证扫描识别、名片信息提取等。在爬虫开发中,如果遭遇了有文字验证码的表单,就可以利用OCR来进行验证码处理。Tesseract-OCR引擎最初是由惠普公司开发的光学字符识别系统,目前发布在Github上,由Google赞助开发。很多网站为了分别出提供验证码的是人还是机器使用了更为复杂的验证码,例如拼图验证码、点触验证码、九宫格验证码等。有较为详细的讲解,有兴趣的可以购买阅读。原创 2023-11-16 13:54:41 · 15 阅读 · 0 评论 -
70.解析动态内容
那么结论就很简单了,只要我们找到了这些网络API接口,那么就能通过这些接口获取到数据,当然实际开发的时候可能还要对这些接口的参数以及接口返回的数据进行分析,了解每个参数的意义以及返回的JSON数据的格式,这样才能在我们的爬虫中使用这些数据。尽管很多网站对自己的网络API接口进行了保护,增加了获取数据的难度,但是只要经过足够的努力,绝大多数还是可以被逆向工程的,但是在实际开发中,我们可以通过浏览器渲染引擎来避免这些繁琐的工作,WebKit就是一个利用的渲染引擎。为了解决上面的问题,可以到Selenium的。原创 2023-11-16 13:53:18 · 29 阅读 · 0 评论 -
69.并发下载
要实现将资源和持有资源的线程进行绑定的操作,最简单的做法就是使用threading模块的local类,在网络爬虫开发中,就可以使用local类为每个线程绑定一个MySQL数据库连接或Redis客户端对象,这样通过线程可以直接获得这些资源,既解决了资源竞争的问题,又避免了在函数和方法调用时传递这些资源。要解决多个线程竞争资源的问题,其中一个方案就是让每个线程都持有资源的副本(拷贝),这样每个线程可以操作自己所持有的资源,从而规避对资源的竞争。使用多进程的时候,可以将进程部署在多个主机节点上,Python的。原创 2023-11-16 13:52:14 · 17 阅读 · 0 评论 -
68.存储数据
一文,我们已经知道了如何从指定的页面中抓取数据,以及如何保存抓取的结果,但是我们没有考虑过这么一种情况,就是我们可能需要从已经抓取过的页面中提取出更多的数据,重新去下载这些页面对于规模不大的网站倒是问题也不大,但是如果能够把这些页面缓存起来,对应用的性能会有明显的改善。可以使用Redis来提供高速缓存服务,关于Redis的知识,我们在。如果要存储海量的低价值数据,文档数据库也是不错的选择,MongoDB是文档数据库中的佼佼者,之前我们已经讲解过MongDB的相关知识,在此不再进行赘述。原创 2023-11-16 13:51:40 · 20 阅读 · 0 评论 -
67.数据采集和解析
如果你对上面的代码并不感到陌生,那么你一定知道HTML页面通常由三部分构成,分别是用来承载内容的Tag(标签)、负责渲染页面的CSS(层叠样式表)以及控制交互式行为的JavaScript。当然,我们也可以通过浏览器提供的开发人员工具来了解更多的信息。通过上一个章节的讲解,我们已经了解到了开发一个爬虫需要做的工作以及一些常见的问题,下面我们给出一个爬虫开发相关技术的清单以及这些技术涉及到的标准库和第三方库,稍后我们会一一介绍这些内容。对于上面的XML文件,我们可以用如下所示的XPath语法获取文档中的节点。原创 2023-11-16 13:51:06 · 17 阅读 · 0 评论 -
65-66.网络爬虫和相关工具
在开始讲解爬虫之前,我们稍微对HTTP(超文本传输协议)做一些回顾,因为我们在网页上看到的内容通常是浏览器执行HTML语言得到的结果,而HTTP就是传输HTML数据的协议。HTTP和其他很多应用级协议一样是构建在TCP(传输控制协议)之上的,它利用了TCP提供的可靠的传输服务实现了Web应用中的数据交换。按照维基百科上的介绍,设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法,也就是说这个协议是浏览器和Web服务器之间传输的数据的载体。原创 2023-11-16 13:50:14 · 645 阅读 · 0 评论 -
64.WebSocket的应用
WebSocket 协议在2008年诞生,2011年成为国际标准(RFC 6455),现在的浏览器都能够支持它,它可以实现浏览器和服务器之间的全双工通信。我们之前学习或了解过Python的Socket编程,通过Socket编程,可以基于TCP或UDP进行数据传输;而WebSocket与之类似,只不过它是基于HTTP来实现通信握手,使用TCP来进行数据传输。WebSocket的出现打破了HTTP请求和响应只能一对一通信的模式,也改变了服务器只能被动接受客户端请求的状况。原创 2023-11-16 13:46:56 · 17 阅读 · 0 评论 -
63.异步化
当然,要实现异步化还得靠其他的支持异步操作的三方库来支持,如果请求处理函数中用到了不支持异步操作的三方库,就需要靠自己写包装类来支持异步化。方法中出现了耗时间的操作,不仅仅是当前请求被阻塞,按照Tornado框架的工作模式,其他的请求也会被阻塞,所以我们需要对耗时间的操作进行异步化处理。在Tornado稍早一些的版本中,可以用装饰器实现请求方法的异步化或协程化来解决这个问题。下面的代码演示了在读写数据库时如何实现请求处理的异步化。封装,实现了对MySQL操作的异步化。,这些都是支持异步操作的三方库。原创 2023-11-16 13:45:42 · 18 阅读 · 0 评论 -
62.Tornado入门
Python的Web框架种类繁多(比Python语言的关键字还要多),但在众多优秀的Web框架中,Tornado框架最适合用来开发需要处理长连接和应对高并发的Web应用。Tornado框架在设计之初就考虑到性能问题,通过对非阻塞I/O和epoll(Linux 2.5.44内核引入的一种多路I/O复用方式,旨在实现高性能网络服务,在BSD和macOS中是kqueue)的运用,Tornado可以处理大量的并发连接,更轻松的应对C10K(万级并发)问题,是非常理想的实时通信Web框架。原创 2023-11-16 13:42:46 · 42 阅读 · 0 评论 -
61.预备知识
对于一次I/O操作(以读操作为例),数据会先被拷贝到操作系统内核的缓冲区中,然后从操作系统内核的缓冲区拷贝到应用程序的缓冲区(这种方式称为标准I/O或缓存I/O,大多数文件系统的默认I/O都是这种方式),最后交给进程。模块中的类类似,由于进程间的内存是相互隔离的(操作系统对进程的保护),进程间通信(共享数据)必须使用管道、套接字等方式,这一点从编程的角度来讲是比较麻烦的,为此,Python的。最后,如果程序不需要真正的并发性或并行性,而是更多的依赖于异步处理和回调时,异步I/O就是一种很好的选择。原创 2023-11-15 13:43:28 · 21 阅读 · 0 评论 -
56-60.用FastAPI开发数据接口
FastAPI 是一个用于构建API(网络数据接口)的现代、高性能的Web框架,基于Python 3.6+,使用了Python中的类型提示进行类型检查,非常符合工程化开发的需求,在业界有非常好的口碑。SQLAlchemy是一个ORM(对象关系映射)框架,ORM框架可以解决Python程序的面向对象模型和关系型数据库的关系模型并不匹配的问题,使得我们可以用面向对象的方式实现数据的CRUD操作。参数会在代码发生变更时自动重新加载新的内容,这个参数在开发阶段非常的有用。自动为数据接口生成对应的文档。原创 2023-11-15 13:42:47 · 33 阅读 · 0 评论 -
55.项目上线
请各位读者移步到[《项目部署上线和性能调优》]原创 2023-11-15 13:39:30 · 16 阅读 · 0 评论 -
54.单元测试
Python标准库中提供了名为unittest 的模块来支持我们对代码进行单元测试。所谓单元测试是指针对程序中最小的功能单元(在Python中指函数或类中的方法)进行的测试。原创 2023-11-15 13:38:36 · 17 阅读 · 0 评论 -
53.异步任务和定时任务
上一章节中讲到的发短信和上传文件到云存储为例,这两个操作前者属于时间不确定的操作(因为作为调用者,我们不能确定三方平台响应的时间),后者属于耗时间的操作(如果文件较大或者三方平台不稳定,都可能导致上传的时间较长),很显然,这两个操作都可以做异步化处理。在Web应用中,如果一个请求执行了耗时间的操作或者该请求的执行时间无法确定,而且对于用户来说只需要知道服务器接收了他的请求,并不需要马上得到请求的执行结果,这样的操作我们就应该对其进行异步化处理。,那么将耗时间或执行时间不确定的任务。原创 2023-11-15 13:37:53 · 37 阅读 · 0 评论 -
52.接入三方平台
国内外比较有名的云存储服务(如:亚马逊的S3、阿里的OSS2等)一般都物美价廉,相比自己架设静态资源服务器,云存储的代价更小,而且一般的云存储平台都提供了CDN服务,用于加速对静态资源的访问,所以不管从哪个角度出发,使用云存储的方式管理Web应用的数据和静态资源都是非常好的选择,除非这些资源涉及到个人或商业隐私,否则就可以托管到云存储中。例如,我们的Web项目中需要做个人或企业的实名认证,很显然我们并没有能力判断用户提供的认证信息的真实性,这个时候我们就要借助三方平台提供的服务来完成该项操作。原创 2023-11-15 13:28:51 · 33 阅读 · 0 评论 -
51.使用缓存
比较常见的解决缓存击穿的办法是使用互斥锁,简单的说就是在缓存失效的时候,不是立即去数据库加载数据,而是先设置互斥锁(例如:Redis中的setnx),只有设置互斥锁的操作成功的请求,才能执行查询从数据库中加载数据并写入缓存,其他设置互斥锁失败的请求,可以先执行一个短暂的休眠,然后尝试重新从缓存中获取数据,如果缓存还没有数据,则重复刚才的设置互斥锁的操作,大致的参考代码如下所示。当然,先更新数据库再删除缓存的做法在理论上也存在风险,但是发生问题的概率是极低的,所以不少的项目都使用了这种方式。原创 2023-11-15 13:26:00 · 19 阅读 · 0 评论