• [技术干货] Python爬虫基础笔记
    什么是网络爬虫?网络爬虫是一种从互联网抓取数据信息的自动化程序;如果我们把互联网比作一张大的蜘蛛网,数据便是存放于蜘蛛网的各个节点,而爬虫就是一只小蜘蛛(程序),沿着网络抓取自己的猎物(数据)。网络爬虫如何工作?构建网页·构造一个请求并发送给服务器;·接收到响应(页面源代码)并将其解析出来;提取信息·网页的结构有一定的规则,采用正则表达式提取;·使用Requests库,我们可以高效快速地从中提取网页信息;保存数据·将提取到的数据保存到某处以便后续使用;·保存形式有多种多样,可以保存到文本或者数据库。网络爬虫能做什么?爬虫根据不同的用途,可以分为通用爬虫和专用爬虫,本次课程中使用的抓取图片的爬虫即为专用爬虫。爬虫的主要用途有如下几种:·搜索引擎:Google、Baidu等;·图片抓取:抓取特定类型的图片,可用于个人收藏、Al图像分析等;·信息收集:新闻资讯聚合、学术信息等;·数据分析:商品价格比较、股票量化交易等;为什么使用Python编写爬虫?. Python编程语言语法简洁,易于学习,快速上手;. Python有成熟的爬虫生态,在抓取网页本身和网页抓取后的处理都有丰富的框架和库可用(如Beautiful Soup框架、Urlib2和Requests库等),编写爬虫不必从零开始;. Python在处理数据方面有天然的优势,可以把Python爬虫与后续的机器学习、数据可视化无缝对接。什么是Python?Python是一种面向对象的解释型计算机程序设计语言,主要特性有:·免费,开源;·语法简洁清晰,容易上手;·多种平台,可扩展,不区分操作系统;支持模块和包,有极为丰富、功能强大的库;·语法表达优美易读,利用缩进表示语句块的开始和退出;·在人工智能、科学计算、图形技术、动画、游戏等行业被广泛使用。Python基础:数据类型Python支持的标准数据类型主要有如下几种:·数字:如整型(123)、布尔型(True/False) 、浮点型(1.23)·字符串(String) :如'l love Python', "l do not love Python”·列表(List):如[ 'a', 'b', 'c', 'd'],[ 1,2,3,4]·元组(Tuples):如('a', 'b', 'c')元组是不可变列表,一旦创建就无法改变·字典(Dictionaries):如{'name':'Tom' , 'age': 24},键值对一—对应Python基础:变量·变量名必须是字母或_开头,以双下划线开头和结尾的变量是python特殊方法的专用标识,如_init_()代表类的构造函数,供解释器使用;·变量可以引用任何类型的对象;变量没有类型,只有对象有类型。变量在使用前必须被赋值。例如: x = 1在Python中的赋值过程如下:1、在内存中创建对象1;2、创建变量名x;3、把变量和对象建立映射关系;4、赋值是把对象的引用赋值给变量而不是值。Python基础:文件·文件是我们储存信息的地方,我们经常要对文件进行读、写等操作·在Python中,我们可用Python提供的函数和方法方便地操作文件。f.open() 打开文件f.close() 关闭文件,用open()打开文件后不关闭会占用系统文件句柄数。f.readline() 读出一行信息。(文件EOF读出的是空串)f.readlines() 读出所有行,也就是读出整个文件的信息。f.write(string) 把string字符串写入文件。f.writelines(list) 把list中的字符串一行一行地写入文件。Python基础:语句lf语句用来做条件判断,基本原理及形式如下:. for循环语句: for iter_var in iterable: suite_to_repeat·每次循环,iter_var迭代变量为可迭代对的当前元素,提供给suite_to_repeat语句块使用。Python基础:函数函数是一个能完成特定功能的代码块,可在程序中重复使用,减少程序的代码量和提高程序的执行效率。在python中函数定义语法如下:def function_name (arg1 ,arg2 [ ,...]):statement[return value]返回值不是必须的,如果没有return语句,则Python默认返回值None;·函数的参数是函数与外部沟通的桥梁,它可接收外部传递过来的值;在函数内部中给参数赋值不会影响调用者;在函数内部修改可变类型的参数会影响到调用者。Python基础:模块·函数是一个能完成特定功能的代码块,可在程序中重复使用,减少程序的代码量和提高程序函模块提供了一种逻辑的方式来组织我们的代码;·模块的物理形式就是文件。一个文件对应一个模块,文件名就是模块名+.py·通过import关键字我们可以导入模块: import module1,[module2,[...moduleN]]·推荐的import导入模块顺序: python标准库—> python第三方库一>自定义模块。·模块(module)其实就是.py文件,里面定义了一些函数、类、变量等;·包(package)是多个模块的聚合休形成的文件夹,里面可以是多个py文件·库(参考其他语言的说法)在python中就是模块和包,是指完成一定功能的代码集合。Python基础:异常处理. Python无法正常处理程序时就会发生一个异常,异常发生时我们需要捕获处理它,否则程序会终止执行;·捕捉异常使用try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。try :try_suite            #监控这里的异常except Exception [ , reason] :except_suite            #异常处理代码什么是HTML ?.HTML (HyperText Markup Language)是一种用于创建网页的超文本标记语言;. HTML可以构建WEB站点,HTML运行在浏览器上,由浏览器来解析。HTML标签HTML标签通常被称为HTML标签(HTML tag),标签是由尖括号包围,通常是成对出现的,比如<header>和</header>,<body>和</body>。HTML常用标签如下:<div>texto1</div>, <span>text02</ span>        #文本标签<input type="password"/>(text、password、checkbox)        #输入框<a href="ur1"></a>        #超文本链接<img src= "ur1"/>            #图片HTML网页结构以下是一个可视化的HTML网页示意图:HTTP协议HTTP(超文本传输协议)是一个基于请求与响应模式的应用层的协议,常基于TCP的连接方式。HTTP协议是万维网的数据通信基础,主要特点可概括如下:·简单快速:客户请求时只需传送请求方法和路径,程序规模小,因而通信速度很快;·灵活:HTTP允许传输任意类型的数据对象;·无连接:服务端每次只处理一个请求,完成即断开,节省传输时间;HTTP请求. HTTP请求由三部分组成,分别是:请求行、消息报头、请求正文;·HTTP请求格式如下:Method Request-URI HTTP-Version CRLF,其中Method表示请求方法;Request-URI是一个统一资源标识符;HTTP-Version表示请求的HTTP协议版本;CRLF表示回车和换行。GET            请求获取Request-URI所标识的资源POST        在Request-URI所标识的资源后附加新的数据HEAD        请求获取由Request-URI所标识的资源的响应消息报头PUT            请求服务器存储一个资源,并用Request-URI作为其标识DELETE        请求服务器删除Request-URI所标识的资源HTTP响应·在接收和解释请求消息后,服务器返回一个HTTP响应消息;·HTTP响应格式如下:HTTP-Version Status-Code Reason-Phrase CRLF,其中,HTTP-Version表示服务器HTTP协议的版本;Status-Code表示服务器发回的响应状态代码;Reason-Phrase表示状态代码的文本描述。1xx        指示信息--表示请求已接收,继续处理            N/A2xx        成功--表示请求已被成功接收、理解、接受        200 OK3xx        重定向--要完成请求必须进行更进—步的操作    N/A4xx        客户端错误--请求有语法错误或请求无法实现    404 Not Found/403 Forbidden5xx        服务器端错误--服务器未能实现合法的请求        503 Server UnavailableRequests库Requests是一常用的http请求库,它使用python语言编写,可以方便地发送http请求,以及方便地处理响应结果。爬虫抓取图片方案对比对比项                本地方案                    华为云方案运行环境        本地环境搭建复杂            云上ECS自带Python环境,无需配置反爬虫应对        个人PC为代理共享公网地址        独享公网EIP地址,可随时更改计算资源本地方案:受限于个人PC性能,耽误其他工作处理,无法随时在线华为云方案:容易获取、即开即用、弹性伸缩、随时在线、按需使用数据库本地方案:资源性能受限,不便于数据分享或二次利用华为云方案:即开即用,完全托管;高性能易扩展;数据安全可备份恢复;便于分享和二次利用整体解决方案架构爬虫的生命周期管理生命周期                涉及到的华为云服务                    详细信息Python运行环境                ECS弹性云主机            使用Python3环境、VIM编辑器爬虫编写与调试                ECS弹性云主机        使用Python3环境、CentOS系统爬虫程序管理        ECS弹性云主机、EIP公网地址            运行、停止Python爬虫存储抓取信息        ECS弹性云主机、OBS对象存储            CentOS系统、OBSUtil工具使用ECS运行爬虫的优势. ECS有弹性公网IP地址,有效方式网站反爬;. ECS购买方便,即开即用,运行高效(相较于个人电脑);·ECS规格丰富,可根据爬取任务负载灵活选择或者变更;.ECS按需使用,运行完成爬虫程序后即可释放资源,节省费用;. ECS可与其他华为云服务配合使用,是更适合网络爬虫的运行环境。使用OBS存储爬取内容的优势可靠OBS通过AZ内设备/数据多冗余和AZ间数据容灾等多级可靠性架构,保障数据持久性高达99.999999999%(11个9),业务连续性高达99.99%.高效OBS通过智能调度,并结合传输加速大数据垂直优化,为用户提供高并发、大带宽、稳定低时延的数据访问体验。安全OBS通过可信云认证,支持服务端加密、防盗链、VPC网络隔离、日志审计、细粒度权限控制,保障数据安全可信。易用OBS支持REST API,提供多种语言的SDK,兼容主流的客户端工具,您可以随时随地通过网络上传、下载、管理您的数据。什么是ECS ?弹性云服务器(Elastic Cloud Server)是一种可随时自助获取、可弹性伸缩的云服务器,帮助用户打造可靠、安全、灵活、高效的应用环境。ECS的主要特性如下:·数据可靠:可弹性扩展的虚拟块存储服务,高数据可靠性,高V/O吞吐能力;·弹性易用:提供控制台、远程终端和API等多种管理方式,给您完全管理权限;·规格丰富:多类型、多规格、多镜像;·多维监控:提供开放性的云监控服务平台,提供资源的实时监控、告警、通知等服务。ECS购买流程什么是OBS ?OBS对象存储服务(Object Storage Service)是一个基于对象的海量存储服务,为客户提供海量、安全、高可靠、低成本的数据存储能力,包括创建、修改、上传、下载、删除对象等。OBS相关概念:·对象(object)·桶(bucket).AK: Access Key ID安全证书.SK: Secret Access Key接入证书·区域OBS权限控制通过IAM设置用户OBS的资源操作权限Tenant Administrator        拥有该权限的用户可以对OBS对象存储资源执行任意操作。Tenant Guest                拥有该权限的用户可以查询OBS对象存储资源的利用情况。OBS Buckets Viewer    具备该权限的用户,可以执行获取桶列表、查询桶元数据和位置信息的操作。OBS服务监控.OBS管理控制支持基于桶的存储空间、对象数量、流量统计和请求次数统计;·管理员可以在桶概览页面查看到桶的监控信息。OBS使用方式. OBS对象存储服务提供了多种数据存取使用方式,覆盖各类使用场景;·本次实践采用Linux系统上的obsutils客户端来管理对象存储。洞察目的网页先洞察确认需要获得数据信息(本实验中的数据指的是明星图片),然后使用Python编程语言编写简单的爬虫,并将此爬虫程序封装为可交互的应用程序。在编写Python爬虫程序之前,需要准备以下准备爬虫抓取的目的网页关键信息:·目的网站:百度图片images.baidu.com·目的关键字:刘德华(娱乐明星)、Yao Ming(体育明星)编写Python爬虫代码在洞察目的网页后,编写Python爬虫代码的主要步骤如下·步骤1使用Windows自带记事本创建一个空的文本文件,用于编写Python爬虫代码;·步骤2导入需要使用到的正则表达式regex和requests两个Python库;·步骤3从浏览器地址栏复制百度图片当前页面的URL地址;·步骤4分析复制的地址,传入requests,编写正则表达式;·步骤5 循环抓取并处理图片异常情况,增加10秒超时控制;·步骤6 保存抓取到的图片到本地images目录,并以数字命名图片;·步骤7完成全部的Python爬虫代码。实践步骤1新建项目文件夹,创建爬虫项目步骤⒉使用pycharm打开爬虫项目步骤3编写vamll.py文件步骤4编写itmes.py文件步骤5 在pipelines.py中添加RDS信息步骤6 创建start.py文件步骤7编写settings.py文件使用OBS存储图片在华为公有云端创建OBS对象存储,并将Python爬虫抓取的明星图片从CentOS操作系统的ECS云主机上传到OBS存储桶中,方便访问和共享。1. (是非题)使用Python编写网络爬虫需要从零开始,没有可用的框架。truefalse 正确2. (单选题)网络爬虫的本质是什么?搜索引擎抓取信息的程序 正确网络上的蜘蛛网页URL3. (单选题)OBS对象存储服务通过下列哪种方式来进行用户认证?用户名/密码私钥签名公钥签名AK/SK 正确4. (多选题)HTTP协议具有哪些特点?简单快速灵活无连接有状态正确5. (多选题)创建OBS对象存储服务的存储桶时,有哪些可选的桶策略?私有公共读公共读写
  • [最佳实践] 利用Spark-mllib进行聚类,分类,回归分析的代码实现(python)
    利用Spark-mllib进行聚类,分类,回归分析的代码实现(python)前提条件安装python3环境,以及需要连接的MRS集群环境下载python3 源码 编译tar zxvf Python-3.8.0.tgz cd Python-3.8.0 mkdir -p /usr/local/python-3.8.0 ./configure --prefix=/usr/local/python-3.8.0 -enable-optimizations --with-ssl make && make install 编译 ln -s /usr/local/python-3.8.0/bin/python3 /usr/bin/python3 ln -s /usr/local/python-3.8.0/bin/pip3 /usr/bin/pip3 ll /usr/bin/python*上传加载数据集创建文件file.csvfeature1,feature2,feature3,label 1.2,3.4,2.8,0 2.1,4.5,1.7,0 3.5,2.8,6.1,1 4.2,5.1,3.9,0 5.3,1.9,2.2,1将该文件上传至hdfshdfs dfs -mkdir -p /tmp/sandboxhdfs dfs -put file.csv /tmp/sandbox在这个示例中,数据集有四个特征列(feature1、feature2、feature3)和一个标签列(label)。每一行代表一个数据样本,特征列的值用逗号分隔,最后是标签的值。这个数据集可以用于分类或回归任务的训练和测试,以下是一些可能的使用方式:分类任务:加载数据集:使用 Spark 的数据加载功能读取 file.csv 文件,并将其转换为 DataFrame 格式。特征工程:根据实际情况,对特征进行预处理、特征选择或特征提取。你可以使用 Spark ML 的特征转换器(如 VectorAssembler、StandardScaler)来创建特征向量,并对特征进行标准化等处理。划分训练集和测试集:将数据集划分为训练集和测试集,一般按照某种比例进行划分,例如 70% 的数据作为训练集,30% 的数据作为测试集。训练模型:选择合适的分类算法(如逻辑回归、决策树、随机森林等)进行模型训练。使用训练集数据拟合模型。模型评估:使用测试集数据对训练好的模型进行评估,计算分类性能指标(如准确率、精确率、召回率、F1 值等)。调优和优化:根据评估结果,调整模型参数或尝试其他的分类算法,以获得更好的性能。回归任务:加载数据集:使用 Spark 的数据加载功能读取 file.csv 文件,并将其转换为 DataFrame 格式。特征工程:根据实际情况,对特征进行预处理、特征选择或特征提取。你可以使用 Spark ML 的特征转换器(如 VectorAssembler、StandardScaler)来创建特征向量,并对特征进行标准化等处理。划分训练集和测试集:将数据集划分为训练集和测试集,一般按照某种比例进行划分,例如 70% 的数据作为训练集,30% 的数据作为测试集。训练模型:选择合适的回归算法(如线性回归、岭回归、决策树回归等)进行模型训练。使用训练集数据拟合模型。模型评估:使用测试集数据对训练好的模型进行评估,计算回归性能指标(如均方误差(MSE)、均方根误差(RMSE)、平均绝对误差(MAE)等)。调优和优化:根据评估结果,调整模型参数或尝试其他的回归算法,以获得更好的性能。聚类(Clustering)示例:K-means 算法import sys sys.path.insert(0, '/opt/140client/Spark2x/spark/python') sys.path.insert(0, '/opt/140client/Spark2x/spark/python/lib/py4j-0.10.9-src.zip') import os os.environ["PYSPARK_PYTHON"]="/usr/anaconda3/bin/python3" import pyspark from pyspark.sql import SparkSession from pyspark import SparkConf from pyspark import SparkContext from pyspark.ml.clustering import KMeans from pyspark.ml.evaluation import ClusteringEvaluator from pyspark.ml.feature import VectorAssembler os.system('source /opt/140client/bigdata_env') os.system('echo password | kinit 用户名') spark = SparkSession \ .builder \ .appName("MLlibPythonExample") \ .getOrCreate() # 加载数据集 data = spark.read.format("csv") \ .option("header", "true") \ .option("inferSchema", "true") \ .load("/tmp/sandbox/file.csv") # 创建特征向量列 assembler = VectorAssembler(inputCols=data.columns, outputCol="features") data = assembler.transform(data) # 训练 K-means 聚类模型 kmeans = KMeans(k=2, seed=123) model = kmeans.fit(data) # 进行预测 predictions = model.transform(data) # 评估聚类模型 evaluator = ClusteringEvaluator() silhouette = evaluator.evaluate(predictions) print("Silhouette with squared euclidean distance = " + str(silhouette))输出轮廓系数为0.370580730000838Silhouette(轮廓系数)是一种用于评估聚类算法效果的指标。它结合了样本与其所分配到的簇内部的紧密度和与其他簇之间的分离度,用于衡量聚类结果的紧密性和分离性。轮廓系数的取值范围在[-1, 1]之间,具体含义如下:接近 1 表示样本与所在簇的紧密度高且与其他簇的分离度好,聚类效果较好。接近 0 表示样本与所在簇的紧密度和与其他簇的分离度相当,聚类效果一般。接近 -1 表示样本与所在簇的紧密度低且与其他簇的分离度差,聚类效果较差。分类(Classification)示例:逻辑回归算法import sys sys.path.insert(0, '/opt/140client/Spark2x/spark/python') sys.path.insert(0, '/opt/140client/Spark2x/spark/python/lib/py4j-0.10.9-src.zip') import os os.environ["PYSPARK_PYTHON"]="/usr/anaconda3/bin/python3" import pyspark from pyspark.sql import SparkSession from pyspark import SparkConf from pyspark import SparkContext os.system('source /opt/140client/bigdata_env') os.system('echo password | kinit 用户名') spark = SparkSession \ .builder \ .appName("MLlibPythonExample2") \ .getOrCreate() from pyspark.ml.classification import LogisticRegression from pyspark.ml.evaluation import BinaryClassificationEvaluator from pyspark.ml.feature import VectorAssembler # 加载数据集 data = spark.read.format("csv") \ .option("header", "true") \ .option("inferSchema", "true") \ .load("/tmp/sandbox/file.csv") # 创建特征向量列和标签列 assembler = VectorAssembler(inputCols=data.columns[:-1], outputCol="features") data = assembler.transform(data) # 划分训练集和测试集 trainData, testData = data.randomSplit([0.7, 0.3], seed=123) # 训练逻辑回归模型 lr = LogisticRegression() model = lr.fit(trainData) # 进行预测 predictions = model.transform(testData) # 评估模型性能 evaluator = BinaryClassificationEvaluator(labelCol="label") accuracy = evaluator.evaluate(predictions) print("Accuracy: ", accuracy)输出准确率为1.0 准确率(Accuracy)是一种用于评估分类算法效果的指标,表示分类器正确分类的样本数量与总样本数量之比。准确率是最常用的分类性能指标之一,它简单直观,并且对于数据类别相对均衡的情况下是一种有效的度量。然而,当数据类别不平衡时,准确率可能会产生误导,因为一个简单的分类器只需要将所有样本都预测为多数类别,就能获得较高的准确率。在这种情况下,需要考虑其他性能指标(如精确率、召回率、F1 值等)来全面评估分类器的表现。回归(Regression)示例:线性回归算法import sys sys.path.insert(0, '/opt/140client/Spark2x/spark/python') sys.path.insert(0, '/opt/140client/Spark2x/spark/python/lib/py4j-0.10.9-src.zip') import os os.environ["PYSPARK_PYTHON"]="/usr/anaconda3/bin/python3" import pyspark from pyspark.sql import SparkSession from pyspark import SparkConf from pyspark import SparkContext os.system('source /opt/140client/bigdata_env') os.system('echo password | kinit 用户名') spark = SparkSession \ .builder \ .appName("MLlibPythonExample3") \ .getOrCreate() from pyspark.ml.regression import LinearRegression from pyspark.ml.evaluation import RegressionEvaluator from pyspark.ml.feature import VectorAssembler # 加载数据集 data = spark.read.format("csv") \ .option("header", "true") \ .option("inferSchema", "true") \ .load("/tmp/sandbox/file.csv") # 创建特征向量列和标签列 assembler = VectorAssembler(inputCols=data.columns[:-1], outputCol="features") data = assembler.transform(data) # 划分训练集和测试集 trainData, testData = data.randomSplit([0.7, 0.3], seed=123) # 训练线性回归模型 lr = LinearRegression() model = lr.fit(trainData) # 进行预测 predictions = model.transform(testData) # 评估模型性能 evaluator = RegressionEvaluator(labelCol="label") rmse = evaluator.evaluate(predictions, {evaluator.metricName: "rmse"}) print("RMSE: ", rmse)RMSE的值为0.8103354037267079均方根误差(Root Mean Square Error,RMSE)是一种常用的评估回归模型预测精度的指标,用于衡量实际观测值与模型预测值之间的差异程度。RMSE 的值越小,表示模型的预测精度越高,与真实观测值之间的差异程度越小。RMSE 是对误差的平均值进行开方,因此保留了误差的单位,通常与原始数据的单位相同。使用spark-submit提交任务创建脚本mllib.py,上传认证凭据user.keytab至对应目录下提交命令spark-submit --master yarn /opt/sandbox/mllib.py --keytab /opt/sandbox/user.keytab --principal sandbox聚类(Clustering)示例:K-means 算法 分类(Classification)示例:逻辑回归算法 回归(Regression)示例:线性回归算法
  • [技术干货] Python自动大麦网抢票,准点原价秒杀演唱会门票,拒绝黄牛交易!从我做起!【转】
    文章目录     前言     一、分析购票过程     二、Selenium 模拟浏览器操作     三、逆向工程:抢票接口     总结  前言  你是否错过了周杰伦的票,最近又没抢到五月天的票,不要太难过,今晚有张学友的票,后天还有其它人的票,加油哦! Python配套案例源码、资料点击领取福利  在这里插入图片描述  为了帮助你在激烈的抢票竞争中获得更大的成功机会,本文将介绍抢票软件的实现原理以及我所了解的一些抢票方式。但是,请不要过度将希望寄托于抢票软件,它有时也不灵,经过我的验证,即使你用到了抢票软件,也不一定能抢到票。  票务平台会经常调整反爬策略打击爬虫行为,如果希望抢票软件保持较高的成功率,是需要开发者针对票务平台的打击策略作出逻辑调整,这个成本是很高的,所以你能随手获得的抢票软件很大概率是抢不到票的或者说是不安全的。  在调研过程发现一个有意思的点 “黄牛的票从来不是抢来的”。相关规定,面向市场公开销售的营业性演出门票数量,不得低于核准观众数量的70%。 而剩下的那 30%,即非公开销售的票,则是黄牛票的主要来源,也叫渠道票。这里面涉及主办方对热门票和冷门票的售票策略,黄牛在这链条中扮演着重要的角色,只要演唱会门票的二级市场不会消失,黄牛就永远不会消失,对于市场本身来说,愿意花更多钱买黄牛票的人,一定是更有需求的人,黄牛不过是市场调节的人格化。 一、分析购票过程  现在无论是买火车票、飞机票、演唱会票基本都是使用电子支付网上购票,之后得到一张电子票凭证,进场前打印纸质票或者闸机核销票据二维码进场,那么我们从用户角度看下,一次完整的购票过程是什么样。  用户的购票流程:      首先用户登录 票务 APP 搜索爱豆的门票,点击查看门票详情,然后选择场次和票档。等待抢票倒计时,才能进入到下一个页面;     倒计时结束后,开抢按钮被点亮,用户进入下一步选择观演人,确认信息后选择付款方式提交订单;     如果手速足够快、运气足够好,抢到了票就会唤起所选的支付方式 APP 提示付款;如果没有抢到则会提示拥堵,跳转到票档选择页面。  下面,我将这个图补充一下,思考下哪些步骤是用户可以提高出票成功率的关键时间节点:  很显然,用户在倒计时之前看不到的页面就是竞争手速的关键时机,当这个开抢按钮被倒计时点亮的一瞬间,要以最快的速度点击到达隐藏页面,然后选中观演人,通常使用默认的支付方式,最后提交订单。一旦订单被提交成功,就说明锁定了席位抢到了票。如果用户在规定的时间内未付款,该席位会重新流入票池,捡漏的人就可以抢到。  到这里,我们知道了购票流程和提高抢票成功率的突破口,人的手速肯定没有机器快,接下来介绍下两种常用的技术抢票方案。 二、Selenium 模拟浏览器操作  在使用 Chrome 浏览器,用户可以使用鼠标滑动、按键点击以及键盘输入,作为信&*号输入设备向浏览器传达指令,浏览器收到指令后执行渲染。  这里提到的 Selenium WebDriver 是对浏览器提供的原生 API 进行封装,使用这套 API 可以操控浏览器的开启、关闭,打开网页,操作界面元素,控制 Cookie。简单说就是,可以通过写代码的方式来自动实现用户鼠标和键盘信&*号的输入。这么一来,可以做的事就非常多了。 下面是一个简单脚本,它首先打开 chrome 浏览器输入 google 的网址,等待 5 秒,浏览器网页打开后,找到输入框输入 ”ChromeDriver“,然后模拟点击搜索按钮,就能看到浏览器上搜索的结果。  import time  from selenium import webdriver from selenium.webdriver.common.by import By  browser.get("https://www.google.com") time.sleep(5) # 查找元素 search_box = browser.find_element(By.NAME, 'q') # 模拟按键输入 search_box.send_keys('ChromeDriver') # 搜索框模拟回车 search_box.submit() time.sleep(5) # 关闭所有窗口 browser.quit()  回到抢票的主题上来,我们可以使用这种技术能力,写一个 Python 脚本,在本地机器上执行起来。脚本内容是在指定的时间打开浏览器,打开票务网页,然后自动模拟用户选择观影人然后自动提交订单。(在这里我原本很想做一个演示视频,理解起来更直观,奈何时间精力有限,这里就不详细介绍 Selenium WebDriver 开发环境配置,感兴趣的可以继续深挖。) 三、逆向工程:抢票接口  什么是逆向?即通过技术手段对票务 APP 的通讯流量抓包,定位 获取票档、提交订单的关键请求解密 https 流量,然后分析解密流量数据。在这里插入图片描述 我们继续回到这张图,仔细观察会发现,用户查看门票详情以及选择票档等一些动作都是 APP 上完成的都是提前加载好的,而真正决定用户抢票的是 “提交订单” 这个关键请求。如果我们可以将这个这个请求的流量抓到,然后分析其参数构造规则,就可以编写程序自动发送请求了。  下面抓包示例,选取了一个门票,抓包获取了其票档信息。  以此类推,抓包 下单接口 观察其参数构成,编写程序模拟用户请求。  # 等待开售 def wait_for_buy():     # 抢购时间     start_timestamp = 1686475533     # 当前时间     current_timestamp = int(time.time())     while current_timestamp > start_timestamp:         # 开始购买         place_order()   这里简要介绍了下实现思路和方向,不展开逆向过程的细节。具体实现没有这么简单的,有攻击方必然有防守方,票务方为了保障平台方利益,势必会定义打击策略,例如,我们会看到验证码从文字到图片再到滑块验证的一个迭代过程。技术方面是一个问题,法律方面也是一个问题,所以全当一次攻防演练的学,不要伤害票务方的利益。 总结  生活有时很操蛋,我们会感到力不从心,但请守住你的热爱,别让它被挫折磨灭”。祝大家买票的时候都能以正常价格抢到自己心仪的演唱会门票 ~ ———————————————— 版权声明:本文为CSDN博主「Python无霸哥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_45841831/article/details/131327575 
  • [技术干货] Python 几种常见算法汇总【转】
    1、选择排序  选择排序是一种简单直观的排序算法。它的原理是这样:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的后面,以此类推,直到所有元素均排序完毕。算法实现如下:  #找到最小的元素def FindSmall(list):   min=list[0]  for i in range(len(list)):    if list[i]<min:       min=list[i]  return min      #选择排序def Select_Sort(list):   newArr=[]  for i in range(len(list)):     minValue=FindSmall(list)     newArr.append(minValue)     list.remove(minValue)  return newArr  testArr=[11,22,33,21,123]print(Select_Sort(testArr))  2、快速排序  快速排序的运行速度快于选择排序,它的工作原理是这样:设要排序的数组是N,首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。可以使用python用递归式的方法来解决这个问题:  def Quick_Sort(list):  if len(list)<2:    return list  else:     temp=list[0]     less=[i for i in list[1:] if i<=temp]     more=[i for i in list[1:] if i>temp]    return Quick_Sort(less)+[temp]+Quick_Sort(more)  testArr= [13,44,53,24,876,2]print(Quick_Sort(testArr))   3、二分查找  二分查找的输入是一个有序的列表,如果要查找的元素包含在一个有序列表中,二分查找可以返回其位置。打个比方来说明二分查找的原理:比如我随便想了个范围在1~100以内的整数,由你来猜,以最少的次数来猜出这个数字,你每次猜完给出个数字,我会回复大了或小了,第一种方法是你从1开始依次往后猜,那如果我想的数字是100,那么你就要猜100次;第二种方法是从50开始,如果我说小了,那你就猜75,就这样依次排除掉一半的剩余数字,这就是二分查找法。可以看出二分查找法更加快速。对于包含n个元素的有序列表,用简单查找最多需要n步,而二分查找法则最多只需lon2 n步。下面用python来实现该算法:  def Item_Search(list,item):   low=0   high=len(list)-1  while low<=high:     middle=(low+high)//2    print(list[middle])    if list[middle]>item:       high=middle-1    elif list[middle]<item:       low=middle+1    else:      return middle  return None      test_list=[1,3,5,7,9,11,13,15,17,19,21] Item_Search(test_list,11)   4、广度优先搜索  广度优先搜索是一种图算法,图由节点和边组成,一个节点可能与多个节点连接,这些节点称为邻居。广度优先搜索算法可以解决两类问题:第一类是从节点A出发,有没有前往节点B的路径;第二类问题是从节点A出发,前往B节点的哪条路径最短。使用广度优先搜索算法的前提是图的边没有权值,即该算法只用于非加权图中,如果图的边有权值的话就应使用狄克斯特拉算法来查找最短路径。举个例子,假如你认识alice、bob、claire,bob认识anuj、peggy,alice认识peggy,claire认识tom、jonny,你需要在最短的路径内找到通过认识的人找到tom,那么算法实现如下:  #使用字典构建图graph={} graph["you"]=["Alice","Bob","Claire"] graph["Bob"]=["Anuj","Peggy"] graph["Alice"]=["Peggy"] graph["Claire"]=["Tom","Jonny"] graph["Anuj"]=[] graph["Peggy"]=[] graph["Tom"]=[] graph["Jonny"]=[]from collections import deque#简单的判断方法def person_is_seller(name):  return name=='Tom'def Search(name):   searched=[]  #用于记录检查过的人,防止进入死循环   search_queue=deque() #创建队列   search_queue+=graph[name]  while search_queue:     person=search_queue.popleft()    if not person in searched:  #仅当这个人没检查过时才检查       if person_is_seller(person):        print("the seller is {0}".format(person))        return True      else:         search_queue+=graph[person]         searched.append(person)  #将这个人标记为检查过   return Falseprint(Search("you"))   5、贪婪算法  贪婪算法,又名贪心算法,对于没有快速算法的问题(NP完全问题),就只能选择近似算法,贪婪算法寻找局部最优解,并企图以这种方式获得全局最优解,它易于实现、运行速度快,是一种不错的近似算法。假如你是个小偷,商店里有很多箱子,箱子里有各种水果,有些箱子里有3种水果,有些箱子有2种…,你想尝到所有种类的水果,但你一个人力气有限,因此你必须尽量搬走最少的箱子,那么,算法实现如下:  fruits=set(["苹果","香蕉","梨子","西瓜","草莓","橘子","荔枝","榴莲"])   #箱子以及包含的水果box={} box["b1"]=set(["苹果","香蕉","西瓜"]) box["b2"]=set(["草莓","橘子","榴莲"]) box["b3"]=set(["梨子","荔枝","草莓"]) box["b4"]=set(["香蕉","橘子"]) box["b5"]=set(["梨子","榴莲"])  final_boxs=set() #最终选择的箱子#直到fruits为空while fruits:   best_box=None #包含了最多的未包含水果的箱子   fruits_covered=set() #包含该箱子包含的所有未包含的水果    #循环迭代每个箱子,并确定它是否为最佳箱子   for boxItem,fruitItem in box.items():     covered=fruits & fruitItem #计算交集     if len(covered)>len(fruits_covered):        best_box=boxItem       fruits_covered=covered   fruits-=fruits_covered   final_boxs.add(best_box)    print(final_boxs)  ———————————————— 版权声明:本文为CSDN博主「Python无霸哥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_45841831/article/details/128188381 
  • [技术干货] 1行Python代码,给视频加水印【转】
    大家好,这里是程序员晚枫,全网同名。最新在小破站:Python自动化办公社区录制教程《给小白的50讲Python自动化办公》,考虑到版权问题,想给视频加个水印。但是找了一圈,没找到特别好用的软件工具,那就自己写一个吧。今天把我给视频加水印的代码分享给大家。效果展示分享代码之前,先给大家展示一下效果。为了不影响观众看视频,水印是若隐若现的加在视频左下角的。代码说明给视频加水印,使用的第三方库是:povideo,下载命令如下。👇pip install povideo只需要1行代码。👇import povideo povideo.mark2video(video_path=r'D:\程序员晚枫的视频.mp4',output_path=r'D:\程序员晚枫的文件夹')一共有2个参数:video_path:需要加水印的视频位置;output_path:输出加水印视频的位置。注意事项这段代码有2点需要大家留意的:水印内容不能是中文;使用了moviepy这个库,需要额外安装一个软件:ImageMagick,并且配置一下环境变量。这一点有不懂的,可以在评论区和我交流~转自 https://mbd.baidu.com/newspage/data/landingsuper?context=%7B%22nid%22%3A%22news_9243104843027808652%22%7D&n_type=1&p_from=4
  • [技术干货] 基于Python的可视化神器--数据可视化工具Pyecharts的图形绘制【转】
    pyecharts是基于Echart图表的一个类库,而Echart是百度开源的一个可视化JavaScript库。pyecharts主要基于web浏览器进行显示,绘制的图形比较多,包括折线图、柱状图、饼图、漏斗图、地图、极坐标图等,代码量很少,而且很灵活,绘制出来的图形很美观。使用pyecharts时,需要安装相应的库,安装命令为:pip install pyecharts图形绘制过程,基本上所有的图表类型都是这样绘制的:chart_name = Type() #初始化具体类型图表chart_name .add() #添加数据及配置项chart_name .render()#生成本地文件(html/svg/jpeg/png/pdf/gif)chart_name .render_notebook #在jupyter notebook中显示#导入pyecharts库from pyecharts.charts import Bar,Funnel,Kline,Gauge,WordCloud,Mapfrom pyecharts import options as optsfrom pyecharts.charts import Page,Pie,Scatter1 、柱状图绘制利用Bar方法可以绘制柱状图。Bar对象的主要方法及其说明bar = ( Bar().add_xaxis(["衬衫", "毛衣", "领带", "裤子", "风衣", "高跟鞋", "袜子"]).add_yaxis("商家A", [114, 55, 27, 101, 125, 27, 105]).set_global_opts(title_opts = opts.TitleOpts(title = "某商场销售情况")) )bar.render() #生成html2、并列柱状图绘制bar = Bar()bar.add_xaxis(["衬衫", "毛衣", "领带", "裤子", "风衣", "高跟鞋", "袜子"])bar.add_yaxis("商家A", [114, 55, 27, 101, 125, 27, 105])bar.add_yaxis("商家B", [57, 134, 137, 129, 145, 60, 49])bar.set_global_opts(title_opts = opts.TitleOpts(title = "货品销售情况",subtitle = "A和B公司"))bar.render() #生成html3、水平直方图绘制bar = Bar()bar.add_xaxis(["衬衫", "毛衣", "领带", "裤子", "风衣", "高跟鞋", "袜子"])bar.add_yaxis("商家A", [114, 55, 27, 101, 125, 27, 105])bar.add_yaxis("商家B", [57, 134, 137, 129, 145, 60, 49])bar.set_global_opts(title_opts=opts.TitleOpts(title="货品销售情况",subtitle = "A和B公司"),toolbox_opts = opts.ToolboxOpts(is_show = True))bar.set_series_opts(label_opts=opts.LabelOpts(position = "right"))bar.reversal_axis()bar.render() #生成html4、饼图绘制L1=['教授','副教授','讲师','助教','其他']num = [20,30,10,12,8]c = Pie()c.add("", [list(z) for z in zip(L1,num)])c.set_global_opts(title_opts=opts.TitleOpts(title="Pie-职称类别比例"))c.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))bar.render() #生成html5、漏斗图绘制data = [45,86,39,52,68]labels = ['电脑','手机','彩电','冰箱','洗衣机']wf = Funnel()wf.add('电器销量图',[list(z) for z in zip(labels, data)], is_selected= True)bar.render() #生成html6、散点图绘制week = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]c = Scatter()c.add_xaxis(week)c.add_yaxis("商家A", [81,65,48,32,68,92,87])c.set_global_opts(title_opts=opts.TitleOpts(title="Scatter-一周的销售额(万元)"))bar.render() #生成html7、仪表盘绘制c = Gauge()c.add("业务指标",[("完成率", 55.5)],axisline_opts=opts.AxisLineOpts(linestyle_opts=opts.LineStyleOpts(color=[(0.3, "#67e0e3"),(0.7, "#37a2da"), (1, "#fd666d")], width=30)))c.set_global_opts(title_opts=opts.TitleOpts(title="Gauge-不同颜色"),legend_opts=opts.LegendOpts(is_show=False))bar.render() #生成html8、地图绘制自从 0.3.2 开始,为了缩减项目本身的体积以及维持 pyecharts 项目的轻量化运行,pyecharts 将不再自带地图 js 文件。如用户需要用到地图图表(Geo、Map),可自行安装对应的地图文件包。Windows下通过以下的pip命令进行安装:#安装全球国家地图,包括世界地图和 213 个国家pip install echarts-countries-pypkg#安装中国省级地图,包括23 个省,5 个自治区pip install echarts-china-provinces-pypkg#中国市级地图,包括370 个中国城市pip install echarts-china-cities-pypkgtemperature=[30,31,27,29,18]loc = ['兰州市','天水市','白银市','武威市','甘南藏族自治州']c = Map()c.add("甘肃省", [list(z) for z in zip(loc, temperature)], "甘肃",is_roam=True)# is_roam是否开启鼠标缩放和平移漫游c .set_global_opts(title_opts=opts.TitleOpts(title="甘肃省部分城市最高气温"))bar.render() #生成html总结导入相关图表包进行图表的基础设置,创建图表对象利用add()方法进行数据输入与图表设置(可以使用print_echarts_options()来输出所有可配置项)利用render()方法来进行图表保存pyecharts还有许多好玩的3D图表和地图图表,个人觉得地图图表是最好玩的,各位有兴趣可以去pyecharts的使用手册查看,有中文版的非常方便:pyecharts。转自 https://baijiahao.baidu.com/s?id=1696460244197183858&wfr=spider&for=pc
  • [技术干货] 浅谈python正则表达式
    Python 正则表达式正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。re 模块使 Python 语言拥有全部的正则表达式功能。compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。re.match函数re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match() 就返回 none。函数语法:re.match(pattern, string, flags=0)实例#!/usr/bin/python# -*- coding: UTF-8 -*-import reprint(re.match('www', 'www.runoob.com').span())  # 在起始位置匹配print(re.match('com', 'www.runoob.com'))         # 不在起始位置匹配re.search方法re.search 扫描整个字符串并返回第一个成功的匹配。函数语法:re.search(pattern, string, flags=0)实例#!/usr/bin/python# -*- coding: UTF-8 -*-import reprint(re.search('www', 'www.runoob.com').span())  # 在起始位置匹配print(re.search('com', 'www.runoob.com').span())         # 不在起始位置匹配re.match与re.search的区别re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。检索和替换Python 的 re 模块提供了re.sub用于替换字符串中的匹配项。语法:re.sub(pattern, repl, string, count=0, flags=0)实例#!/usr/bin/python# -*- coding: UTF-8 -*-import rephone = "2004-959-559 # 这是一个国外电话号码"# 删除字符串中的 Python注释num = re.sub(r'#.*$', "", phone)print "电话号码是: ", num# 删除非数字(-)的字符串num = re.sub(r'\D', "", phone)print "电话号码是 : ", numre.compile 函数compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。语法格式为:re.compile(pattern[, flags])findall在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表。注意: match 和 search 是匹配一次 findall 匹配所有。语法格式为:findall(string[, pos[, endpos]])re.finditer和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。re.finditer(pattern, string, flags=0)re.splitsplit 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:re.split(pattern, string[, maxsplit=0, flags=0])正则表达式对象re.RegexObjectre.compile() 返回 RegexObject 对象。re.MatchObjectgroup() 返回被 RE 匹配的字符串。    start() 返回匹配开始的位置    end() 返回匹配结束的位置    span() 返回一个元组包含匹配 (开始,结束) 的位置正则表达式模式模式字符串使用特殊的语法来表示一个正则表达式:字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。多数字母和数字前加一个反斜杠时会拥有不同的含义。标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。反斜杠本身需要使用反斜杠转义。由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如 r'\t',等价于 '\\t')匹配相应的特殊字符。下表列出了正则表达式模式语法中的特殊元素。如果你使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。模式描述^匹配字符串的开头$匹配字符串的末尾。.匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。[...]用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'[^...]不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。re*匹配0个或多个的表达式。re+匹配1个或多个的表达式。re?匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式re{ n}精确匹配 n 个前面表达式。例如, o{2} 不能匹配 "Bob" 中的 "o",但是能匹配 "food" 中的两个 o。re{ n,}匹配 n 个前面表达式。例如, o{2,} 不能匹配"Bob"中的"o",但能匹配 "foooood"中的所有 o。"o{1,}" 等价于 "o+"。"o{0,}" 则等价于 "o*"。re{ n, m}匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式a| b匹配a或b(re)对正则表达式分组并记住匹配的文本(?imx)正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。(?-imx)正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。(?: re)类似 (...), 但是不表示一个组(?imx: re)在括号中使用i, m, 或 x 可选标志(?-imx: re)在括号中不使用i, m, 或 x 可选标志(?#...)注释.(?= re)前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。(?! re)前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功(?> re)匹配的独立模式,省去回溯。\w匹配字母数字及下划线\W匹配非字母数字及下划线\s匹配任意空白字符,等价于 [ \t\n\r\f]。\S匹配任意非空字符\d匹配任意数字,等价于 [0-9].\D匹配任意非数字\A匹配字符串开始\Z匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。\z匹配字符串结束\G匹配最后匹配完成的位置。\b匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。\B匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。\n, \t, 等.匹配一个换行符。匹配一个制表符。等\1...\9匹配第n个分组的内容。\10匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。
  • [技术干货] Python3 命名规则
    1.项目名称每个单词的首字母都要大写 例如:ProjectName2.模块名和包名全部小写,多个单词使用下划线(_)分割module_name package_name3.类名每个单词的首字母都要大写class ClassName: pass4.方法名或函数名全部小写,多个单词使用下划线(_)分割def method_name(): pass def function_name(): pass5.全局变量、普通变量、常量全局变量和常量:全部大写,多个单词用下划线(_)分割 普通变量:全部小写,多个单词用下划线(_)分割GLOBAL_VARIABLE = '全局变量' common_variable = '普通变量' CONSTANT = '常量'6.参数全部小写,一般一个单词就可以,多个单词使用下划线(_)分割def method_name(self): print('self是参数名字')
  • [技术干货] Python入门 类class 基础篇【转】
    记住一句话:类是模板,而实例则是根据类创建的对象。我初学时对类的理解是从类的字面上,可以片面的认为它是一个种类,它是相似特征的抽像,也就是相似的东西,可以把相似特征的事务抽象成一个类。(事务可以是具体的物体或行为)以圆为例,圆是具有圆周率(pi)和半径(r)两个相似特征的属性。根据相似特征抽象出圆类,每个圆的半径可以不同,那么半径可以作为圆的实例属性;而每个圆的圆周率pi是相同的,那么圆周率pi就可以作为类属性,这样就定义出了一个圆类。而我们要知道圆的面积,周长等可以通过类方法计算出来。(看完整篇文章,还是对类不理解,回过头在来看这部分,对照列子多理解。)一、Python类的定义与实例的创建在Python中,类通过 class 关键字定义,类名通用习惯为首字母大写,Python3中类基本都会继承于object类,语法格式如下,我们创建一个Circle圆类:class Circle(object): # 创建Circle类,Circle为类名 pass # 此处可添加属性和方法注意:我们定义的类都会继承于object类,当然也可以不继承object类;两者区别不大,但没有继承于object类使用多继承时可能会出现问题。有了Circle类的定义,就可以创建出具体的circle1、circle2等实例,circle1和circle2是个实际的圆。创建实例使用 类名+(),类似函数调用的形式创建。如下我们创建两个Circle类的实例:circle1= Circle()circle2= Circle()二、Python类中的实例属性与类属性类的属性是用来表明这个类是什么的。类的属性分为实例属性与类属性两种。实例属性用于区分不同的实例;类属性是每个实例的共有属性。区别:实例属性每个实例都各自拥有,相互独立;而类属性有且只有一份,是共有的属性。1、实例属性类的属性都是用来指明这个类"是什么",实例属性是用来区分每个实例不同的基础。在上面我们创建了Circle类,大家都知道所有圆都具备半径这个通用属性,下面我们为circle1、circle2 圆实例添加半径 r 这个属性并赋值。circle1.r = 1 # r为实例属性circle2.R= 2 print(circle1.r) # 使用 实例名.属性名 可以访问我们的属性print(circle2.R)如上 circle1.r、circle2.R 大小写有区分,两个实例的属性名称不统一不利于后面的访问和使用,而且每次在创建圆后我们要再为实例添加属性会比较麻烦,所以我们可以在创建实例时给类初始属性。在定义 Circle 类时,可以为 Circle 类添加一个特殊的 __init__() 方法,当创建实例时,__init__() 方法被自动调用为创建的实例增加实例属性。我们在此为每个实例都统一加上我们需要的属性(用法类似java的构造方法):class Circle(object): # 创建Circle类 def __init__(self, r): # 初始化一个属性r(不要忘记self参数,他是类下面所有方法必须的参数) self.r = r # 表示给我们将要创建的实例赋予属性r赋值注意:__init__() 方法的第一个参数必须是 self(self代表类的实例,可以用别的名字,但建议使用约定成俗的self),后续参数则可以自由指定,和定义函数没有任何区别。拓展:__init__() 方法的用法类似java中的构造方法,但它不是构造方法,Python中创建实例的方法是__new__() ,这个方法在python大多数使用默认方法,不需要重新定义,初学者不用关注__new()__方法。相应,创建实例时就必须要提供除 self 以外的参数:circle1 = Circle(1) # 创建实例时直接给定实例属性,self不算在内circle2 = Circle(2)print(circle1.r) # 实例名.属性名 访问属性print(circle2.r) # 我们调用实例属性的名称就统一了注意:实例名.属性名 circle1.r 访问属性,是我们上面Circle类__init__() 方法中 self.r 的 r 这个实例属性名,而不是__init__(self, r)方法中的 r 参数名,如下更加容易理解:class Circle(object): # 创建Circle类 def __init__(self, R): # 约定成俗这里应该使用r,它与self.r中的r同名 self.r = Rcircle1 = Circle(1) print(circle1.r) #我们访问的是小写r面试喜欢问的问题:创建类时,类方法中的self是什么?self 代表类的实例,是通过类创建的实例 (注意,在定义类时这个实例我们还没有创建,它表示的我们使用类时创建的那个实例)2、类属性绑定在实例上的属性不会影响其他实例,但类本身也是一个对象,如果在类上绑定属性,则所有实例都可以访问该类的属性,并且所有实例访问的类属性都是同一个!!!记住,实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。圆周率π为圆的共有属性,我们可以在Circle类添加pi这个类属性,如下:class Circle(object): pi = 3.14 # 类属性 def __init__(self, r): self.r = rcircle1 = Circle(1)circle2 = Circle(2)print('----未修改前-----')print('pi=\t', Circle.pi)print('circle1.pi=\t', circle1.pi) # 3.14print('circle2.pi=\t', circle2.pi) # 3.14print('----通过类名修改后-----')Circle.pi = 3.14159 # 通过类名修改类属性,所有实例的类属性被改变print('pi=\t', Circle.pi) # 3.14159print('circle1.pi=\t', circle1.pi) # 3.14159print('circle2.pi=\t', circle2.pi) # 3.14159print('----通过circle1实例名修改后-----')circle1.pi=3.14111 # 实际上这里是给circle1创建了一个与类属性同名的实例属性print('pi=\t', Circle.pi) # 3.14159print('circle1.pi=\t', circle1.pi) # 实例属性的访问优先级比类属性高,所以是3.14111 print('circle2.pi=\t', circle2.pi) # 3.14159print('----删除circle1实例属性pi-----')输出结果:----未修改前-----pi= 3.14circle1.pi= 3.14circle2.pi= 3.14----通过类名修改后-----pi= 3.14159circle1.pi= 3.14159circle2.pi= 3.14159----通过circle1实例名修改后-----pi= 3.14159circle1.pi= 3.14111circle2.pi= 3.14159仔细观察我们通过类创建的实例修改的类属性后,通过其他实例访问类属性他的值还是没有改变。其实是通过实例修改类属性是给实例创建了一个与类属性同名的实例属性而已,实例属性访问优先级比类属性高,所以我们访问时优先访问实例属性,它将屏蔽掉对类属性的访问。我们删除circle1实例的实例属性pi,就能访问该类的类属性了。print('----删除circle1实例属性pi-----')del circle1.piprint('pi=\t', Circle.pi)print('circle1.pi=\t', circle1.pi)print('circle2.pi=\t', circle2.pi)输出结果:----删除circle1实例属性pi-----pi= 3.14159circle1.pi= 3.14159circle2.pi= 3.14159可见,千万不要在实例上修改类属性,它实际上并没有修改类属性,而是给实例绑定了一个实例属性。三、Python类的实例方法方法是表明这个类用是来做什么。在类的内部,使用 def 关键字来定义方法,与一般函数定义不同,类方法必须第一个参数为 self, self 代表的是类的实例(即你还未创建类的实例),其他参数和普通函数是完全一样。如下我们给圆类 Circle 添加求面积的方法 get_area :class Circle(object): pi = 3.14 # 类属性 def __init__(self, r): self.r = r # 实例属性 def get_area(self): """ 圆的面积 """ # return self.r**2 * Circle.pi # 通过实例修改pi的值对面积无影响,这个pi为类属性的值 return self.r**2 * self.pi # 通过实例修改pi的值对面积我们圆的面积就会改变circle1 = Circle(1)print(circle1.get_area()) # 调用方法 self不需要传入参数,不要忘记方法后的括号 输出 3.14注意:示例中的 get_area(self) 就是一个方法,它的第一个参数是 self 。__init__(self, name)其实也可看做是一个特殊的实例方法。在方法的内部需要调用实例属性采用 "self.属性名 " 调用。示例中 get_area(self) 对于 pi 属性的引用 Circle.pi 与 self.pi 存在一定区别。Circle.pi 使用的是类属性 pi,我们通过创建的实例去修改 pi 的值对它无影响。self.pi 为实例的 pi 值,我们通过创建的实例去修改 pi 的值时,由于使用 self.pi 调用的是实例属性,所以 self.pi 是修改后的值。调用实例的方法中使用实例属性可采用 实例名.方法名(除self的参数) 使用。四、总结参数的传递图,翻译与pythoncentral网转自 https://www.zhihu.com/tardis/bd/art/30024792?source_id=1001
  • [技术干货] Python工程实践之np.loadtxt()读取数据【转】
    前言机器学习中使用np.loadtxt()可以高效的导入数据,np.loadtxt()适合.txt文件和.csv文件。但是它默认读取float类型的值。1.np.loadtxt()读取txt文件1-1 基础参数12345numpy.loadtxt(    fname, dtype=, comments='#',     delimiter=None, converters=None,     skiprows=0, usecols=None,     unpack=False, ndmin=0)1-2 参数详解 fname要读取的文件、文件名、或生成器。dtype数据类型,默认float。comments注释。delimiter分隔符,默认是空格。skiprows跳过前几行读取,默认是0,必须是int整型。usecols要读取哪些列,0是第一列。例如,usecols = (1,4,5)将提取第2,第5和第6列。默认读取所有列。unpack如果为True,将分列读取。1-3 应用示例文件的存储路径为:'./data.txt', 文件内容如下:1-3-1 fnamefname可以是文件的路径也可以是要读取的文件。 12#根据文件名直接读取data = np.loadtxt('./data/data.csv')1-3-2 dtypedtype默认为np.float32类型,也可以设置为其他类型,比如int。设置为其他dtype时需要考虑数据本身的类型。1234#设置dtypedata = np.loadtxt('./data/data.csv',dtype=np.float32)#设置dtypedata = np.loadtxt('./data/data.csv',dtype=int)1-3-3 commentscomment的是指, 如果行的开头为comment的值,那在读取时就会跳过该行。示例代码中comment  = '1',则在读取数据时,会跳过开头为1的行。1data = np.loadtxt('./data.txt',dtype = int,comments='1')1-3-4 delimiter delimiter是分隔符,默认是空格。1data = np.loadtxt('./data.txt',dtype = int,comments='1',delimiter=' ')1-3-5 skiprowsskiprows跳过前几行读取,默认是0,必须是int整型。skiprows = 2则表示跳过前两行读取数据。1data = np.loadtxt('./data.txt',dtype = int,delimiter=',',skiprows=2)读取数据时,设定 skiprows = 2,则将前两行跳过,从第三行开始读取。1-3-6 usecolsusecols要读取哪些列,0是第一列。例如,usecols = (1,4,5)将提取第2,第5和第6列。默认读取所有列。读取第2列数据。1data = np.loadtxt('./data.txt',dtype = int,delimiter=',',usecols = 1)读取第2,6,9列数据。 1data = np.loadtxt('./data.txt',dtype = int,delimiter=',',usecols =(1,5,8))
  • [技术干货] python中的extend功能及用法【转】
    Python中的extend()方法用于在列表末尾一次性追加另一个列表中的多个值。源于: 执行类代码 --parallel_str_search.py – 函数combine_resultextend() 函数的功能:用于在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)12345678A = [1, 2, 3]B = [['a', 'b']]A.extend([4])A.extend([5, 6])B.extend(['c', 'd'])B.extend([['e', 'f']])print(A)print(B)结果为:[1, 2, 3, 4, 5, 6][['a', 'b'], 'c', 'd', ['e', 'f']]extend() 函数、append()函数、+ 与 += 功能比较:append()是向列表尾部追加一个新元素,列表只占一个索引位,在原有列表上增加。extend()向列表尾部追加一个列表,将列表中的每个元素都追加进来,在原有列表上增加。+与extend()在效果上具有相同的功能,但是实际上生成了一个新的列表来存放这两个列表的和,只能用在两个列表相加上。+=与extend()效果一样。append():1234A = [1, 2, 3]B = [4, 5, 6]print(A.append(B))print(A)结果为:None[1, 2, 3, [4, 5, 6]]extend():1234A = [1, 2, 3]B = [4, 5, 6]print(A.extend(B))print(A)结果为:None[1, 2, 3, 4, 5, 6]+:1234A = [1, 2, 3]B = [4, 5, 6]print(A+B)print(A)结果为:[1, 2, 3, 4, 5, 6][1, 2, 3]+=:1234A = [1, 2, 3]B = [4, 5, 6]A += Bprint(A)结果为:[1, 2, 3, 4, 5, 6]python中extend的用法将列表中的元素加入到当前列表中12345678arr1 = [1,2,3]arr2 = [[‘a',‘b']]arr1.extend([4])arr1.extend([5,6])arr2.extend([‘c',‘d'])arr2.extend([[‘e',‘f']])print(arr1)print(arr2)
  • [技术干货] Python isalnum()函数的具体使用【转】
    isalnum() 可以判断字符串的字符是否全都是「字母」和「数字」。语法1string.isalnum()返回值字符串中所有字符都是数字或字母返回True否则返回False实例:判断字符串是否由字母或数字构成1print('hello'.isalnum())输出:True1、包含字母和数字的情况只包含「数字」,数字的定义是[0-9]1print('0123456789'.isalnum())输出:True只包含「字母」,大小写都算,字母的定义是[a-z,A-Z]1print('abcABC'.isalnum())输出:True包含「数字」和「字母」1print('123abcABC'.isalnum())输出:True2、汉字和其他语言的情况不只是英语(英文字母),汉语、日语、韩语等,都可以判断。只包含「汉字」1print('汉字'.isalnum())输出:True只包含「日语」字符1print('何だよ'.isalnum())输出:True只包含「韩语」字符1print('한자'.isalnum())输出:True包含英语、汉语、韩语、日语print('12aA汉だ한'.isalnum())输出:True「其他国家」的语言也支持判断,这里就不一 一列举了。如果想区分中文和英文,可以编码后再判断1234print("汉字".isalnum())print("汉字".encode().isalnum())print("12aA汉だ한".encode().isalnum())print("12aA".encode().isalnum())输出:TrueFalseFalseTrue从输出结果可以发现,只有包含字母和数字才返回True,包含汉字时返回False。提示:Python3默认使用Unicode编码,所以汉字会返回True;encode()默认编码是UTF-8,编码成utf8之后,汉字就不会返回True了。3、空字符串、制表符、特殊符号、标点符号字符串中包含空字符串、制表符、特殊符号、标点符号时,返回False包含「空字符串」123print('12 '.isalnum())print(''.isalnum())print(' '.isalnum())输出:FalseFalseFalse包含嫩绿「制表符」123print("\\".isalnum())print('\n'.isalnum())print('\na'.isalnum())输出:FalseFalseFalse包含特殊符号、标点符号123print("1+1".isalnum())print('1,'.isalnum())print('“1”'.isalnum())输出:FalseFalseFalse
  • [技术干货] Python endswith()函数的具体使用【转】
    endwith() 可以「判断」字符串是否以指定内容「结尾」。语法1string.endwith( str, start, end )参数str :(必选,字符串或元组)指定字符串或元素start :(可选)开始的索引,默认值0end :(可选)结束的索引,默认值-1返回值以指定内容结尾返回 True不以指定内容结尾返回 False实例:判断字符串是否以 ‘world’ 结尾1print('hello world'.endswith('world'))输出:True1、指定范围设置开始和结束的「索引」来指定范围,索引从0开始。只设置「开始」的索引,默认检查到字符串末尾,即[start,末尾]1print('hello world'.endswith('world', 1))输出:True同时设置「开始」、「结束」的索引,可以检测字符串的某个范围内是否以指定内容结尾。1print('hello world'.endswith('world', 0, 5))输出:False从输出结果可以发现,字符串(0~5)索引是‘hello ’,不以‘world’结尾,所以返回False。除了在 endwith() 参数中设置索引,还可以通过字符串的索引来指定范围1print('hello world'[0:5].endswith('world'))输出:False2、str可以传入元组str 参数只能是字符串或者元祖(元素都是字符串类型),否则会报错 TypeError: endswith first arg must be str or a tuple of str传入元素都是字符串的类型的「元祖」,会自动遍历并判断字符串是否以元组中的元素结尾,只要满足一个,就返回True;全部不满足,就返回False。12print('hello world'.endswith(('world', 'a')))print('hello world'.endswith(('b', 'a')))输出:TrueFalse实例:文件后缀名黑名单12345file_name = 'shell.php'if file_name.endswith(('php', 'jsp', 'asp')):    print('被禁止的文件类型,请重新上传')else:    print('上传成功')如果只有「列表」,可以转成数组再判断123list1 = ['world', 'a', 'b']tuple1 = tuple(list1)print('hello world'.endswith(tuple1))输出:True3、空字符串为真判断字符串是否以 空字符串""结尾时,会返回True。12print('hello world'.endswith(''))print('*&ab31'.endswith(''))输出:TrueTrue「空格」就不行了,会返回False1print('hello world'.endswith(' '))输出:False4、大小写敏感endwith() 判断时,区分「大小写」,这导致我们匹配不到一些文件后缀名,比如下面这样会返回False12file_name = 'shell.PHP'print(file_name.endswith('php'))输出:False我们可以先 lower() 转成小写,再进行判断12file_name = 'shell.pHp'print(file_name.lower().endswith('php'))输出:True
  • [技术干货] Python Requests使用Cookie的几种方式详解【转】
    一、通过headers参数使用通过headers参数使用cookie,key为Cookie,值为使用;拼接的 cookie_name=cookie_value 字符串 import requests  get_url = "https://postman-echo.com/get" # key为Cookie,值为使用;拼接的 cookie_name=cookie_value 字符串 headers = {"Cookie":"cka=111a;ckb=111b"}  res = requests.get(url=get_url,headers=headers)  print(res.json().get("headers").get("cookie")) print(res.request.headers.get("Cookie")) 输出如下:cka=111a;ckb=111bcka=111a;ckb=111b二、通过cookies参数使用通过cookies参数使用cookie,cookies 值以字典形式提供,key为cookie_name,value为cookie_value import requests  get_url = "https://postman-echo.com/get" # cookies 以字典形式提供,cookies 值以字典形式提供,key为cookie_name,value为cookie_value cookies = {"cka":"222a","ckb":"222b"}  res = requests.get(url=get_url,cookies=cookies)  print(res.json().get("headers").get("cookie")) print(res.request.headers.get("Cookie")) 输出:cka=222a; ckb=222bcka=222a; ckb=222b注意:同时通过headers,cookies 参数传递Cookie时,只有headers传递的Cookie有效。三、通过Session会话使用通过Session会话管理Cookie,同一会话的多个请求可共享Cookie;在Session中添加Cookie又有多种方式方式0:自动设置在会话过程中,如果有接口响应头中有 set-cookie,则将自动添加到会话的Cookie中 import requests  session = requests.session() print("会话初始cookie:",dict(session.cookies))  get_url = "https://postman-echo.com/get" res = session.get(url=get_url)  print("响应头中set-cookie:",res.headers.get("set-cookie")) print("会话现有cookie:",dict(session.cookies)) 输出:会话初始cookie: {}响应头中set-cookie: sails.sid=s%3ALo1-iQfueg8z1DhR_SX3KxwWA85cYN65.asZ1elFlT9g54uj%2FHkHpaZFkk0rBaCFDtRrA9anWzY4; Path=/; HttpOnly会话现有cookie: {'sails.sid': 's%3ALo1-iQfueg8z1DhR_SX3KxwWA85cYN65.asZ1elFlT9g54uj%2FHkHpaZFkk0rBaCFDtRrA9anWzY4'}方式1:通过key设置直接通过key设置cookie,但不支持设置cookie的 path、domain 等值 import requests  session = requests.session() print("会话初始cookie:",dict(session.cookies))  # 直接通过key设置cookie,但不支持设置cookie的 path、domain 等值 session.cookies["cka"]="111a" session.cookies["ckb"]="111b"  get_url = "https://postman-echo.com/get" res = session.get(url=get_url)  print("本次请求使用的cookie:",res.request.headers.get("Cookie")) print("会话现有cookie:",dict(session.cookies)) 输出:会话初始cookie: {}本次请求使用的cookie: cka=111a; ckb=111b会话现有cookie: {'cka': '111a', 'ckb': '111b', 'sails.sid': 's%3AxtcEChogQfCYrRm9HDwAOFa4VlQQDsCZ.OR1TBpmuhX%2F2qI7mpTE0NdChrphD5AUcvcRqUF2y6NU'}方式2:通过set 方法设置通过set方法设置cookie,且支持设置path、domain等值 import requests  session = requests.session() print("会话初始cookie:",dict(session.cookies))  # 通过set方法设置cookie,且支持设置path、domain等值 session.cookies.set("ck2","222",path="/",domain="postman-echo.com")  get_url = "https://postman-echo.com/get" res = session.get(url=get_url)  print("本次请求使用的cookie:",res.request.headers.get("Cookie")) print("会话现有cookie:",session.cookies) 输出:会话初始cookie: {}本次请求使用的cookie: ck2=222会话现有cookie: <RequestsCookieJar[<Cookie ck2=222 for postman-echo.com/>, <Cookie sails.sid=s%3AZW2JtlIjc1m9D2vVrn1Io57gVB6lVQiK.SjYcItCh92iqDkVF7oI8C6q5P8KmQ5DwB%2BiD4A6Ag48 for postman-echo.com/>]>注意:<Cookie ck2=222 for postman-echo.com/> 可以看出 设置的 path、domain 成功了方式3:通过 add_dict_to_cookiejar 方法设置通过 requests.utils 工具包里的 add_dict_to_cookiejar 方法设置cookie,但不支持设置 path、domain 等值 import requests  session = requests.session() print("会话初始cookie:",dict(session.cookies))  # 通过 requests.utils 工具包里的 add_dict_to_cookiejar 方法设置cookie,但不支持设置 path、domain 等值 cookie_dict = {"ck3a":"333a","ck3b":"333b"} requests.utils.add_dict_to_cookiejar(session.cookies,cookie_dict=cookie_dict)  get_url = "https://postman-echo.com/get" res = session.get(url=get_url)  print("本次请求使用的cookie:",res.request.headers.get("Cookie")) print("会话现有cookie:",dict(session.cookies)) 输出:会话初始cookie: {}本次请求使用的cookie: ck3a=333a; ck3b=333b会话现有cookie: {'ck3a': '333a', 'ck3b': '333b', 'sails.sid': 's%3AFY_7nq-hA_v9BxPaft4BHgRNiZOmDZ1S.N64IaIZ2Dd2fnfDMawbXdmJl0HfUVN7hhhGrdaFE4Bs'}方式4:通过 RequestsCookieJar() 对象设置创建一个空 RequestsCookieJar()对象,然后使用对象的set方法赋值,然后update更新到当前会话cookie,支持设置 path、domain等值 import requests  session = requests.session() print("会话初始cookie:",dict(session.cookies))  # 创建一个空 RequestsCookieJar()对象,然后使用对象的set方法赋值,然后update更新到当前会话cookie,支持设置 path、domain等值 ckj = requests.sessions.RequestsCookieJar() ckj.set('ck4a', '444a', path='/', domain='postman-echo.com') session.cookies.update(ckj)  get_url = "https://postman-echo.com/get" res = session.get(url=get_url)  print("本次请求使用的cookie:",res.request.headers.get("Cookie")) print("会话现有cookie:",dict(session.cookies)) 输出:会话初始cookie: {}本次请求使用的cookie: ck4a=444a会话现有cookie: {'ck4a': '444a', 'sails.sid': 's%3ANU88BiSVQAFpVUtrvSrii14jOhO_q981.MfJkY7Aw93R0Rc4V6JGi7SXPOneNJTr3p%2FNVJ9yp4Qg'}方式5:通过 cookiejar_from_dict 方法设置通过 requests.utils 工具包里的 cookiejar_from_dict 方法将字典格式的cookie转换为cookiejar对象,然后update更新到当前会话,不支持设置 path、domain 等值 import requests  session = requests.session() print("会话初始cookie:",dict(session.cookies))  # 通过 requests.utils 工具包里的 cookiejar_from_dict 方法将字典格式的cookie转换为cookiejar对象,然后update更新到当前会话,不支持设置 path、domain 等值 cookie_dict = {"ck5a":"555a","ck5b":"555b"} ckj5 = requests.utils.cookiejar_from_dict(cookie_dict=cookie_dict) session.cookies.update(ckj5)  get_url = "https://postman-echo.com/get" res = session.get(url=get_url)  print("本次请求使用的cookie:",res.request.headers.get("Cookie")) print("会话现有cookie:",dict(session.cookies)) 输出:会话初始cookie: {}本次请求使用的cookie: ck5a=555a; ck5b=555b会话现有cookie: {'ck5a': '555a', 'ck5b': '555b', 'sails.sid': 's%3AWHa__ab1vTZVjGdlIpDgDFfntSYNqS2Y.y%2Fq4YhPv49C5jwNiYdVWrFsQm9B0Y202rI5xRrqlwsk'}
  • [技术干货] Python大批量写入数据(百万级别)的方法【转】
    背景现有一个百万行数据的csv格式文件,需要在两分钟之内存入数据库。方案方案一:多线程+协程+异步MySql方案二:多线程+MySql批量插入代码    1,先通过pandas读取所有csv数据存入列表。    2,设置N个线程,将一百万数据均分为N份,以start,end传递给线程以切片的方法读取区间数据(建议为16个线程)    3,方案二 线程内以  executemany 方法批量插入所有数据。    4,方案一 线程内使用异步事件循环遍历所有数据异步插入。     5,方案一纯属没事找事型。方案二 import threading  import pandas as pd import asyncio import time  import aiomysql import pymysql  data=[] error_data=[]  def run(start,end):     global data     global error_data     print("start"+threading.current_thread().name)     print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))     mysdb = getDb("*", *, "*", "*", "*")     cursor = mysdb.cursor()     sql = """insert into *_*_* values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"""     cursor.executemany(sql,data[start:end])     mysdb.commit()     mysdb.close()     print("end" + threading.current_thread().name)     print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))  def csv_file_read_use_pd(csvFile):     csv_result = pd.read_csv(csvFile,encoding="utf-16",sep='\t')     csv_result = csv_result.fillna(value="None")     result = csv_result.values.tolist()     return result  class MyDataBase:     def __init__(self,host=None,port=None,username=None,password=None,database=None):         self.db = pymysql.connect(host=host,port=port,user=username,password=password,database=database)     def close(self):         self.db.close()  def getDb(host,port,username,password,database):     MyDb = MyDataBase(host, port, username, password,database)     return MyDb.db  def main(csvFile):     global data  #获取全局对象  csv全量数据     #读取所有的数据   将所有数据均分成   thread_lens   份 分发给  thread_lens  个线程去执行     thread_lens=20     csv_result=csv_file_read_use_pd(csvFile)     day = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))     for item in csv_result:         item.insert(0,day)      data=csv_result     thread_exe_count_list=[]   #线程需要执行的区间     csv_lens=len(csv_result)     avg = csv_lens // thread_lens     remainder=csv_lens % thread_lens     # 0,27517  27517,55,034     nowIndex=0     for i in range(thread_lens):         temp=[nowIndex,nowIndex+avg]         nowIndex=nowIndex+avg         thread_exe_count_list.append(temp)     thread_exe_count_list[-1:][0][1]+=remainder  #余数分给最后一个线程     # print(thread_exe_count_list)      #th(thread_exe_count_list[0][0],thread_exe_count_list[0][1])      for i in range(thread_lens):         sub_thread = threading.Thread(target=run,args=(thread_exe_count_list[i][0],thread_exe_count_list[i][1],))         sub_thread.start()         sub_thread.join()         time.sleep(3)  if __name__=="__main__":     #csv_file_read_use_pd("分公司箱型箱量.csv")     main("分公司箱型箱量.csv") 方案一 import threading  import pandas as pd import asyncio import time  import aiomysql  data=[] error_data=[]  async def async_basic(loop,start,end):     global data     global error_data     print("start"+threading.current_thread().name)     print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))     conn = await aiomysql.connect(         host="*",         port=*,         user="*",         password="*",         db="*",         loop=loop     )     day = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))     sql = """insert into **** values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"""     async with conn.cursor() as cursor:         for item in data[start:end]:             params=[day]             params.extend(item)             try:                 x=await cursor.execute(sql,params)                 if x==0:                     error_data.append(item)                 print(threading.current_thread().name+"   result "+str(x))             except Exception as e:                 print(e)                 error_data.append(item)                 time.sleep(10)                 pass     await conn.close()     #await conn.commit()     #关闭连接池     # pool.close()     # await pool.wait_closed()     print("end" + threading.current_thread().name)     print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))  def csv_file_read_use_pd(csvFile):     csv_result = pd.read_csv(csvFile,encoding="utf-16",sep='\t')     csv_result = csv_result.fillna(value="None")     result = csv_result.values.tolist()     return result  def th(start,end):     loop = asyncio.new_event_loop()     loop.run_until_complete(async_basic(loop,start,end))  def main(csvFile):     global data  #获取全局对象  csv全量数据     #读取所有的数据   将所有数据均分成   thread_lens   份 分发给  thread_lens  个线程去执行     thread_lens=20     csv_result=csv_file_read_use_pd(csvFile)     data=csv_result     thread_exe_count_list=[]   #线程需要执行的区间     csv_lens=len(csv_result)     avg = csv_lens // thread_lens     remainder=csv_lens % thread_lens     # 0,27517  27517,55,034     nowIndex=0     for i in range(thread_lens):         temp=[nowIndex,nowIndex+avg]         nowIndex=nowIndex+avg         thread_exe_count_list.append(temp)     thread_exe_count_list[-1:][0][1]+=remainder  #余数分给最后一个线程     print(thread_exe_count_list)      #th(thread_exe_count_list[0][0],thread_exe_count_list[0][1])      for i in range(thread_lens):         sub_thread = threading.Thread(target=th,args=(thread_exe_count_list[i][0],thread_exe_count_list[i][1],))         sub_thread.start()         time.sleep(3)  if __name__=="__main__":     #csv_file_read_use_pd("分公司箱型箱量.csv")     main("分公司箱型箱量.csv") 
总条数:2474 到第 页
上滑加载中