首页 文章 精选 留言 我的

精选列表

搜索[个人博客],共10000篇文章
优秀的个人博客,低调大师

精选博客系列|将基于决策树的Ensemble方法用于边缘计算

在即将到来的边缘计算时代,越来越需要边缘设备执行本地快速训练和分类的能力。事实上,无论是手机上的健康应用程序、冰箱上的传感器还是扫地机器人上的摄像头,由于许多原因,例如需要快速响应时间、增强安全性、数据隐私,甚至考虑到盈利能力,通常都需要进行本地计算。 无论是以什么方式进行机器学习,对于此类设备来说,具有异构性、有限的连接和有限的硬件资源是一个持续存在的、我们必须解决的挑战。事实上,人们经常面临着矛盾的需求,边缘设备必须在本地执行大量的计算、存储和通信,同时还要遵守如有限的内存、网络连接和计算的资源限制。这通常是由于时间或功率限制以及增加的数据和可用信息量。 这里,我们重点讨论利用基于决策树的Ensemble方法进行计算和内存高效的本地(即设备上)训练和分类,这是处理表格数据的实际标准。 基于决策树的Ensemble方法 事实上,基于树的Ensemble方法,例如随机森林(RF)和XGBoost,由于其健壮性、易用性和泛化性,经常用于对表格数据进行分类。反过来,分类任务通常用作许多应用域中的子例程,例如金融、欺诈检测、医疗保健和入侵检测。因此,这种方法的效率和精度与效用之间的权衡至关重要。 让我们特别关注随机森林和XGBoost,并了解它们的优势: 随机森林可以说是最流行的bagging方法,它使用数据的随机子样本来生长每个决策树,从而生成不同且弱相关的树。然后,使用多数票确定分类。随机森林有几个优点,包括健壮性、快速训练、处理不平衡数据集的能力、嵌入式特征选择、处理缺失的、分类的和连续的特征,以及高级人工分析或法规要求的、任何时候的可解释性。 XGBoost是一种著名且流行的boosting算法,它在每次迭代时都会生成一个小的决策树(例如,具有8–32个终端节点)。每个这样的树都是为了减少以前树的错误分类。XGBoost分享了随机森林的大部分优点,并且由于其可控偏差,通常可以实现更高的精度。 然而,这些方法也带来了一些与资源相关的缺点: 随机森林往往受内存限制,分类速度较慢。此外,由于随机森林占用大量内存,因此通常无法部署在内存有限的边缘设备上,而这些设备通常需要执行分类任务。 XGBoost模型通常比随机森林需要更少的内存,但它们是计算密集型的,导致训练速度较慢。 我们解决了随机森林和XGBoost的资源消耗缺点。特别的是,我们引入了一种新的混合方法,该方法继承了bagging和boosting方法的良好特性,具有可比较的机器学习性能,同时大大提高了资源效率。 数据集中的冗余 众所周知,机器学习模型的资源消耗与用于训练的数据集的大小高度相关。因此,减少数据集大小是可取的。因此,我们想提出以下问题: 数据集中的所有数据实例对于基于树的ensemble模型的训练是否同样重要? 如果没有,我们应该如何在训练期间区分数据实例以节省资源?这将如何影响分类? 事实上,数据集通常包含许多简单的(例如90%)数据实例,因为它们很容易识别,因此很容易分类;以及罕见或更独特的数据实例,因此更难分类。 直观地说,如果在培训之前可以进行这种区分,那么应该能够利用这些知识来节省资源,而不会对准确性产生重大影响。其中一个想法是在培训期间使用较少的“简单”数据实例。面临的挑战是如何制定这样的计划,并以有效的方式这样做。 RADE–资源高效的异常检测模型 数据集只有两个类,其中大多数实例是正常的或良性的(例如99%)。 RADE以以下方式利用上述观察结果:它首先使用整个数据集构建一个小(粗粒度)模型。然后,它使用该模型对用于训练的所有数据实例进行分类。正确分类且具有高度可信度的实例被标记为简单实例(通常是大多数正常实例),而所有其他实例都被标记为困难实例(通常为大多数异常实例)。 如图所示,RADE引入了一种高级体系结构,只要粗粒度模型及其分类提供了有意义的分类置信水平,就可以与不同的分类模型一起使用。 直观地说,由于粗粒度模型足以正确分类简单的查询,所以我们只剩下困难查询。利用这些,我们构建了两个专家(细粒度)模型,用于处理与粗粒度模型的分类结果有关的两种不同情况:细粒度模型1负责(低置信度)正常分类和细粒度模型2用于(低置信度)异常分类。这些模型可能具有比粗粒度模型更大的内存占用需求,但明显低于基于整体的树模型。 训练效率 如前所述,RADE分两个阶段进行训练。首先,使用整个数据集训练粗粒度模型。由于我们使用的是一个小模型,所以这个训练阶段相对较快。然后,我们使用粗粒度模型对整个训练数据集进行分类,并根据所得到的分类和置信度,生成两个数据子集用于训练细粒度模型。由于我们只使用训练数据的子集(例如10%)训练每个细粒度模型,所以这个训练阶段也相对较快。 分类效率 RADE的分类也有两个阶段。首先,根据粗粒度模型对实例进行分类。如果得到的分类置信度较高(例如0.9),则完成分类。否则,根据粗粒度模型分类结果,由其中一个细粒度模型转发查询以进行重新分类。这意味着RADE的分类时间等于仅由粗粒度模型提供服务的分类,以及由粗粒度和细粒度模型提供的分类时间的加权平均值。直觉上,因为目的是为了只通过粗粒度模型(例如90%)服务大多数查询,平均分类时间预计将比标准的整体模型显著改进。 Duet–资源高效的多类分类模型 RADE是为二进制分类设计的,因此使用两个细粒度模型。就多类分类用例而言,扩展RADE的体系结构并不是一个可扩展的解决方案,因为它需要K类的K个细粒度模型,因此需要一个新的体系结构。 为此,我们开发了Duet。Duet遵循RADE的原则,即使用粗粒度模型,该模型在整个数据集上经过训练,并对简单的查询进行分类。然而,与RADE不同,Duet只使用单个细粒度分类器,该分类器在训练数据集的子集上进行训练,并对困难(低置信度)查询进行分类。 Duet的高级体系结构如图所示。从本质上讲,它使用了两个分类器:一个小型bagging分类器(随机森林),提供有意义的分类置信度、受控方差和内存限制,另一个boosting分类器(XGBoost),提供受控偏差和计算限制。总的来说,与单例分类器相比,Duet引入了一种不同且通常更好的系统/机器学习性能的权衡。 Duet的主要问题是如何确定boosting分类器的训练数据子集。 在这种情况下,使用RADE中的置信度指标是不够的,因为我们有一个多维问题。因此,我们使用类概率分布向量(通过粗粒度模型)来确定实例对训练过程的重要性。 对于六个类别的分类任务,考虑两个具有相同(第一)分类置信度的分类结果。第一个在两个类别上的概率(几乎)相等(例如[0.5,0.5,0,0,0,0]),第二个在正确类别上概率较高,而在所有剩余类别上概率低得多(例如[0.5,0.1,0.1,0.1,0.1,0.1])。显然,第一个查询比较困难,可能更有利于增强分类器的训练。 为了捕获此属性,我们定义了一个新的度量标准–可预测性这是由欧几里得距离函数给出的,该函数测量得到的类概率分布向量相对于实例的真实标签与完美分布向量之间的距离。完美分布向量在正确标签(即类)中的概率应为1。 请注意,可预测性是训练过的bagging分类器和训练数据集的具体度量,因此是Duet训练过程中的一个集成步骤。此外,使用可预测性不同于仅依赖于数据集属性的采样方法(例如,分层采样,它保留了每个类的实例百分比)。 进一步的潜力 上述设计原则可能适用于其他机器学习领域。虽然Duet主要使用可预测性度量来降低训练和分类过程的计算成本,但可以使用可预测度度量来减少训练数据集的大小,从而降低存储和通信成本。 此外,RADE和Duet还可能适用于分布式学习。例如,参与方可以联合训练一个粗粒度模型,然后使用该模型从本地数据集中选择子集,最后使用这些子集训练全局细粒度模型。 这里的挑战是确定参与方选择其子集的标准。例如,一种高级方法是使用安全计算来收集有关全局训练数据的一些统计信息。这样的统计数据可能会使每个参与者选择更好的子集,总的来说,对于细粒度模型的分布式训练,这样有更高的训练价值。 内容来源|公众号:VMware 中国研发中心

优秀的个人博客,低调大师

[python作业AI毕业设计博客]selenium工具python快速入门1简介

概述 Selenium是一个开源自动化测试套件,适用于跨浏览器和平台的Web应用程序。 它是一组软件工具,每种工具都有不同的方法来支持测试自动化。 Selenium3.*的组件如下: Selenium IDE(集成开发环境 Integrated Development Environment) Selenium WebDriver Selenium Grid Selenium3.停止直接使用Selenium RC。 Selenium Core已从最新版本的Selenium 3.中完全删除。 官网:http://www.seleniumhq.org/ Selenium开源,基于Apache 2.0 License。github: https://github.com/SeleniumHQ/selenium Selenium IDE Se

优秀的个人博客,低调大师

[python作业AI毕业设计博客]Analytic Methods in Systems and Software Testing-201...

下载地址 https://itbooks.pipipan.com/fs/18113597-335471247 使用最先进的方法和工具对系统和软件测试进行综合处理。本书提供了有关最新软件测试方法的宝贵见解,并通过示例解释了该领域中使用的统计和分析方法。许多例子用于提供将这些方法应用于现实问题的理解。应用统计学,计算机科学和软件工程的领先权威机构提出了最先进的方法,以解决参与系统和软件测试的从业者和研究人员所面临的挑战。 方法包括:机器学习,贝叶斯方法,图形模型,实验设计,广义回归和可靠性建模。系统和软件测试中的分析方法将其全面的方法集合分为四个部分:第一部分:测试概念和方法;第二部分:统计模型;第三部分:测试基础设施;第四部分:测试应用程序。它旨在保持对分析方法的关注,同时提供现代工程的背景景观,以便引入该领域中使用的相关统计和概率模型。这使得这本书成为一本非常有用的工具,为研究人员和从业人员提供有关该领域挑战的有趣见解。汇总应用统计,计算机科学和软件工程领域权威机构和软件测试的前沿方法和分析方法实例结合方法和实例,重点关注系统和软件测试的分析方面,包括逻辑回归,机器学习,贝叶斯算法方法,图形模型,实验设计,广义回归和可靠性模型由该领域的领先研究人员和从业人员撰写,来自不同背景,包括研究,商业,政府和咨询,在理论和实践层面激发研究系统和软件中的分析方法测试。 是针对工业和学术读者的极好的高级参考,他们在系统和软件开发方面的工作接近或超过现有的测试和验证程序的前沿。它对计算机科学和数学的研究生也很有价值。

优秀的个人博客,低调大师

[雪峰磁针石博客]python包管理工具:Conda和pip比较

python测试开发项目实战-目录 python工具书籍下载-持续更新 python 3.7极速入门教程 - 目录 Conda和pip通常被认为几乎完全相同。虽然这两个工具的某些功能重叠,但它们设计用于不同的目的。 Pip是Python Packaging Authority推荐的用于从Python Package Index安装包的工具。 Pip安装打包为wheels或源代码分发的Python软件。后者可能要求系统安装兼容的编译器和库。 Conda是跨平台的包和环境管理器,可以安装和管理来自Anaconda repository以 Anaconda Cloud的conda包。 Conda包是二进制文件,徐需要使用编译器来安装它们。另外,conda包不仅限于Python软件。它们还可能包含C或C ++库,R包或任何其他软件。 这是conda和pip之间的关键区别。 Pip安装Python包,而conda安装包可能包含用任何语言编写的软件的包。在使用pip之前,必须通过系统包管理器或下载并运行安装程序来安装Python解释器。而Conda可以直接安装Python包以及Python解释器。 另一个区别是conda能够创建可以包含不同版本的Python或其他软件包的隔离环境。在使用数据科学工具时,这非常有用,因为不同的工具可能包含冲突的要求,这些要求可能会阻止它们全部安装到单个环境中。 Pip没有内置的环境支持,而是依赖于virtualenv或venv 等其他工具来创建隔离环境。 pipenv,poetry和hatch wrap pip和virtualenv等工具提供了统一的方法来处理这些环境。 Pip和conda在如何实现环境中的依赖关系方面也有所不同。安装包时,pip会在递归的串行循环中安装依赖项。没有努力确保同时满足所有包的依赖性。如果较早安装的软件包与稍后安装的软件包具有不兼容的依赖性版本,则可能导致破坏的环境。conda使用可确保满足环境中安装的所有包的所有要求。此检查可能需要额外的时间,但有助于防止创建破坏的环境,前期关于依赖关系包的元数据是正确的。 考虑到conda和pip之间的相似性,有些人试图将这些工具结合起来创建数据科学环境也就不足为奇了。将pip与conda结合的主要原因是有些包只能通过pip安装。 Anaconda创酷提供超过1,500个软件包,包括最流行的数据科学,机器学习和AI框架。这些,以及包括conda-forge和bioconda在内的数据通过Anaconda云提供的数千个附加软件包,可以使用conda进行安装。尽管有大量的软件包,但与PyPI上提供的150,000多个软件包相比,它仍然很小。有时候需要的包没有conda包,但在PyPI上有,可以用pip安装。 参考资料 讨论qq群144081101 567351477 本文最新版本地址 本文涉及的python测试开发库 谢谢点赞! 本文相关海量书籍下载 python工具书籍下载-持续更新 python GUI工具书籍下载-持续更新 类别 conda pip 管理 二进制 wheel 或源码 需要编译器 no yes 语言 any Python 虚拟环境 支持 通过 virtualenv或venv等支持 依赖性检查 yes 屏幕提示用户选择 包来源 Anaconda repo和cloud PyPi

优秀的个人博客,低调大师

[雪峰磁针石博客]python 3.7极速入门教程7互联网

本文教程目录 7互联网 互联网访问 urllib urllib是用于打开URL的Python模块。 import urllib.request # open a connection to a URL using urllib webUrl = urllib.request.urlopen('https://china-testing.github.io/address.html') #get the result code and print it print ("result code: " + str(webUrl.getcode())) # read the data from the URL and print it data = webUrl.read() print (data) json json是一种受JavaScript对象文字语法启发的轻量级数据交换格式。是目前互联网最流行的数据交换格式。 json公开了标准库marshal和pickle模块的用户所熟悉的API。 >>> import json >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}]) '["foo", {"bar": ["baz", null, 1.0, 2]}]' >>> print(json.dumps("\"foo\bar")) "\"foo\bar" >>> print(json.dumps('\u1234')) "\u1234" >>> print(json.dumps('\\')) "\\" >>> print(json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)) {"a": 0, "b": 0, "c": 0} >>> from io import StringIO >>> io = StringIO() >>> json.dump(['streaming API'], io) >>> io.getvalue() '["streaming API"]' 参考资料 讨论qq群144081101 591302926 567351477 钉钉免费群21745728 本文最新版本地址 本文涉及的python测试开发库 谢谢点赞! XML XML即可扩展标记语言(eXtensible Markup Language)。它旨在存储和传输中小数据量,并广泛用于共享结构化信息。 import xml.dom.minidom doc = xml.dom.minidom.parse("test.xml"); # print out the document node and the name of the first child tag print (doc.nodeName) print (doc.firstChild.tagName) # get a list of XML tags from the document and print each one expertise = doc.getElementsByTagName("expertise") print ("{} expertise:".format(expertise.length)) for skill in expertise: print(skill.getAttribute("name")) # create a new XML tag and add it into the document newexpertise = doc.createElement("expertise") newexpertise.setAttribute("name", "BigData") doc.firstChild.appendChild(newexpertise) print (" ") expertise = doc.getElementsByTagName("expertise") print ("{} expertise:".format(expertise.length)) for skill in expertise: print (skill.getAttribute("name")) ElementTree是处理XML文件的简便方法。 import xml.dom.minidom import xml.etree.ElementTree as ET tree = ET.parse('items.xml') root = tree.getroot() # all items data print('Expertise Data:') for elem in root: for subelem in elem: print(subelem.text)

优秀的个人博客,低调大师

[雪峰磁针石博客]python 3.7极速入门教程2 Hello与变量

Hello 命令行方式 $ python Python 3.7.0 (default, Jun 28 2018, 13:15:42) [GCC 7.2.0] :: Anaconda, Inc. on linux Type "help", "copyright", "credits" or "license" for more information. >>> print("Hello, https://china-testing.github.io/") Hello, https://china-testing.github.io/ ipython方式 $ ipython Python 3.7.0 (default, Jun 28 2018, 13:15:42) Type 'copyright', 'credits' or 'license' for more information IPython 6.5.0 -- An enhanced Interactive Python. Type '?' for help. In [1]: print("Hello, https://china-testing.github.io/") Hello, https://china-testing.github.io/ IDE方式 文件方式 上面代码地址:https://github.com/china-testing/python-api-tesing/blob/master/python3.7quick/2hello.py __main__ 当Python解释器读取源文件时,它将执行其中的所有代码。 当Python运行“源文件”作为主程序时,它将特殊变量( __name __)设置为具(“ __main __”)。 “if __name __ ==” __main __“允许您将Python文件作为可重用模块或独立程序运行。 与C一样,Python使用==进行比较,而使用=进行赋值。 上面代码地址:https://github.com/china-testing/python-api-tesing/blob/master/python3.7quick/2main.py 参考资料 讨论qq群144081101 591302926 567351477 钉钉免费群21745728 本文最新版本地址 本文涉及的python测试开发库 谢谢点赞! 本文相关海量书籍下载 https://linuxize.com/post/how-to-install-anaconda-on-ubuntu-18-04/ 变量 Python变量是用于存储值的保留内存位置。 换句话说,python程序中的变量将数据提供给计算机进行处理。 Python中的每个值都有数据类型。 Python中不同的数据类型是数值,列表,元组,字符串,字典等。变量可以用任何名称声明,甚至可以用a,aa,abc等字母表来声明,命名规则和C语言的类似。字母或下划线开头,除第一位外可以包含数字。 上面代码地址:https://github.com/china-testing/python-api-tesing/blob/master/python3.7quick/2var.py 作用域 如果要在程序或模块的其余部分使用相同的变量,可声明为全局变量;如果只在特定函数或方法中使用该变量,则使用局部变量。 让我们通过以下程序理解本地变量和全局变量之间的差异。 全局变量f被赋予值101 函数中声明局部变量,赋值"I am learning Python." 上面代码地址:https://github.com/china-testing/python-api-tesing/blob/master/python3.7quick/2local.py 关键字global,可以在函数内引用全局变量。 实际上局部找不到变量也会到全局去找。上面代码地址:https://github.com/china-testing/python-api-tesing/blob/master/python3.7quick/2global.py 使用命令del“variable name”可以删除变量。 在下面的例子中,我们删除了变量f,当我们继续打印它时,得到错误“变量名未定义”,这意味着你已经删除了变量。

优秀的个人博客,低调大师

[雪峰磁针石博客]2018最佳selenium工具书籍汇总下载(持续更新)

简介 本文是https://github.com/china-testing/python-api-tesing/blob/master/books.md的节选。 欢迎转载,转载请附带此简介,谢谢! Practical Web Scraping for Data Science -Best Practices and Examples with Python - 2018.pdf https://github.com/Apress/practical-web-scraping-for-data-science 星级 低于100 本书提供了完整的现代Web抓取指南,使用Python作为编程语言。 作者建议网络抓取作为任何数据科学家的强大工具,因为许多数据科学项目都是从获得适当的数据集开始的。 作者探讨了HTTP,HTML和CSS的核心概念,以提供坚实的基础。 除了快速的Python入门,它们还包括Selenium用于JavaScript重型站点和网络爬行的详细信息。 本书最后概述了最佳实践和一系列示例,这些示例汇集了您学到的所有内容,并说明了各种数据科学用例。 -- 本书的selenium教程写得简明扼要,后面还配有丰富的实例。 Selenium自动化测试 基于 Python 语言 - 2018.pdf https://github.com/upgundecha/learnsewithpython 星级 低于100 Selenium是一个主要用于Web应用程序自动化测试的工具集合,在行业内已经得到广泛的应用。本书介绍了如何用Python语言调用Selenium WebDriver接口进行自动化测试。主要内容为:基于Python 的 Selenium WebDriver 入门知识、Selenium Python脚本、使用unittest 编写单元测试、生成HTML格式的测试报告、元素定位、Selenium Python API 介绍、元素等待机制、跨浏览器测试、移动端测试、编写一个iOS测试脚本、编写一个Android测试脚本、Page Object与数据驱动测试、Selenium WebDriver的特性、第三方工具与框架集成等核心技术。 《Selenium自动化测试 基于Python语言》适合任何软件测试人员阅读,也适合作为大专院校师生的学习用书和培训学校的教材。 -- 本书虽然为2018年翻译,但是实际基于selenium2和python2,已经过时,很多实例已经不能运行。阅读时可参考 selenium自动化测试工具python笔试面试项目实战5键盘操作,尽管有点过时,依旧是selenium书籍中的佳品。 对应的英文版:Learning Selenium Testing Tools with Python - 2014.pdf Python测试驱动开发:使用Django、Selenium和JavaScript进行Web编程(第2版)- 2018.pdf 本书从基础的知识开始,讲解Web开发的整个流程,展示如何使用Python做测试驱动开发。本书由三个部分组成。第一部分介绍了测试驱动开发和Django的基础知识,并在每个阶段进行严格的单元测试。第二部分讨论了Web开发要素,探讨了Web开发过程中不可避免的问题,以及如何通过测试解决这些问题。第三部分探讨了一些话题,如模拟技术、集成第三方认证系统、Ajax、测试固件以及持续集成等。第2版全部使用Python 3,并针对新版Django全面升级,介绍了由外而内的测试驱动开发流程。本书适合Web开发人员阅读。 https://github.com/hjwp/Book-TDD-Web-Dev-Python/ 300左右星 Selenium WebDriver 3 Practical Guide 2nd - 2018.pdf https://github.com/PacktPublishing/Selenium-WebDriver-3-Practical-Guide-Second-Edition 星级 低于100 Selenium WebDriver 3所有最新功能的跨浏览器,移动和数据驱动测试的真实示例。 释放Selenium的全部潜力,以测试您的Web应用程序使用Selenium Grid进行更快,并行运行和跨浏览器测试使用Appium测试iOS和Android应用程序 Selenium WebDriver是一个开源自动化工具,通过浏览器的驱动程序实现,该驱动程序将命令发送到浏览器并检索结果。最新版本的Selenium 3带来了许多新功能,这些功能改变了您使用和设置Selenium WebDriver的方式。本书涵盖了所有这些功能以及源代码,包括一个允许您使用HMTL5应用程序的演示网站以及本书中的其他示例。 Selenium WebDriver 3实用指南将引导您完成Selenium WebDriver的各种API,这些API用于自动化测试,然后讨论可用的各种WebDriver实现。您将学习使用高级WebDriver API制定战略和处理丰富的Web UI,以及WebDriver面临的实时挑战和处理它们的解决方案。您将发现不同类型和领域的测试,例如跨浏览器测试,负载测试和使用Selenium进行移动测试。最后,您还将了解使用TestNG进行数据驱动的测试,以创建您自己的自动化框架。 -- 比较新的selenium书籍,基于java描述,操作性不如python描述版本。 Python Web Scraping Cookbook - 2018.pdf 下载 Python Web Scraping Cookbook is a solution-focused book that will teach you techniques to develop high-performance Scrapers, and deal with cookies, hidden form fields, Ajax-based sites and proxies. You'll explore a number of real-world scenarios where every part of the development or product life cycle will be fully covered. You will not only develop the skills to design reliable, high-performing data flows, but also deploy your codebase to Amazon Web Services (AWS). If you are involved in software engineering, product development, or data mining or in building data-driven products, you will find this book useful as each recipe has a clear purpose and objective. Right from extracting data from websites to writing a sophisticated web crawler, the book's independent recipes will be extremely helpful while on the job. This book covers Python libraries, requests, and BeautifulSoup. You will learn about crawling, web spidering, working with AJAX websites, and paginated items. You will also understand to tackle problems such as 403 errors, working with proxy, scraping images, and LXML. By the end of this book, you will be able to scrape websites more efficiently and deploy and operate your scraper in the cloud. https://github.com/PacktPublishing/Python-Web-Scraping-Cookbook < 100星 -- 有涉及selenium。 Website Scraping with Python - 2018.pdf 仔细检查网站抓取和数据处理:以适合进一步分析的格式从网站提取数据的技术。您将查看要使用的工具,并比较它们的功能和效率。本书简明扼要专注于BeautifulSoup4和Scrapy,突出了常见问题,并提出了读者可以自行实施的解决方案。 您将看到如何单独或一起使用BeautifulSoup4和Scrapy以获得所需的结果。由于许多站点都使用JavaScript,因此您还将使用Selenium和浏览器模拟器来呈现这些站点。 在本书的最后,您将拥有一个完整的抓取应用程序来使用和重写以满足您的需求。 -- Selenium和BeautifulSoup4、Scrapy的结合使用 Python网络数据采集 Python网络数据采集 - 2016.pdf 本书采用简洁强大的Python语言,介绍了网络数据采集,并为采集新式网络中的各种数据类型提供了全面的指导。第 1部分重点介绍网络数据采集的基本原理:如何用Python从网络服务器请求信息,如何对服务器的响应进行基本处理,以及如何以自动化手段与网站进行交互。第 二部分介绍如何用网络爬虫测试网站,自动化处理,以及如何通过更多的方式接入网络。 Web Scraping with Python 2nd - 2018.pdf https://github.com/REMitchell/python-scraping 2000左右星 -- 这本书的github星级很高,里面有一章涉及selenium,但是实际上讲得很一般,没有太大参考价值。 参考资料 讨论 钉钉群21745728 qq群144081101 567351477 本文最新版本地址 本文涉及的python测试开发库 谢谢点赞! 本文相关海量书籍下载 用Python写网络爬虫 第2版 《用Python写网络爬虫(第 2版》讲解了如何使用Python来编写网络爬虫程序,内容包括网络爬虫简介,从页面中抓取数据的3种方法,提取缓存中的数据,使用多个线程和进程进行并发抓取,抓取动态页面中的内容,与表单进行交互,处理页面中的验证码问题,以及使用Scarpy和Portia进行数据抓取,并在最后介绍了使用本书讲解的数据抓取技术对几个真实的网站进行抓取的实例,旨在帮助读者活学活用书中介绍的技术。 《用Python写网络爬虫(第 2版》适合有一定Python编程经验而且对爬虫技术感兴趣的读者阅读。 Python Web Scraping 2nd Edition - 2017.pdf 第一版中文 用Python写网络爬虫.pdf https://github.com/kjam/wswp < 100星 -- 很肤浅地涉及了selnium 其他 Software Development From A to Z Test-Driven Development with Python, 2nd Edition Appium Recipes Practical DevOps Testing Java Microservices DevOps: Continuous Delivery, Integration, and Deployment with DevOps Python Testing Cookbook, 2nd Edition Continuous Integration, Delivery and Deployment

优秀的个人博客,低调大师

[雪峰磁针石博客]python计算机视觉深度学习2图像基础

构建自己的图像分类器之前需要了解图像是什么。 像素:图像的元素 像素是图像的基本元素。每个图像都由一组像素组成。没有比像素更细的粒度。 通常像素是光的“颜色”或“强度”。 下图的分辨率为1,000×750,这意味着它是1,000像素宽750像素高。我们可以将图像概念化为(多维)矩阵。图片中总共有1,000×750 = 750,000像素。 大多数像素以两种方式表示:1.灰度/单通道2.颜色 在灰度图像中,每个像素是0到255之间的标量值,其中零对应为“黑色”,255为“白色”。 彩色像素通常在RGB颜色空间中表示(其他颜色空间通常要转成RGB)。 黑色:(0, 0, 0)红色:(255, 0, 0) RGB色彩空间的主要缺点包括:•不使用“颜色选择器”工具时表示颜色不直观•它不像人类看待颜色的方式。 图像坐标系统 OpenCV和scikit-image用多维NumPy数组表示RGB。 import cv2 image = cv2.imread("example.png") print(image.shape) cv2.imshow("Image", image) cv2.waitKey(0) 执行结果: $ python load_display.py (248, 300, 3) 像素访问 (b, g, r) = image[20, 100] # accesses pixel at x=100, y=20 (b, g, r) = image[75, 25] # accesses pixel at x=25, y=75 (b, g, r) = image[90, 85] # accesses pixel at x=85, y=90 OpenCV的存储顺序:Blue, Green, Red 技术支持qq群144081101 591302926 567351477 钉钉免费群:21745728 缩放 多数神经网络和卷积神经网络应用于图像任务分类要求固定大小的输入,意味着你通过的所有图像的尺寸必须相同。输入的宽度和高度图像尺寸的常见选择卷积神经网络包括32×32,64×64,224×224,227×227,256×256和299×299。

优秀的个人博客,低调大师

[雪峰磁针石博客]python工具库介绍-requests:人性化的HTTP

Requests是Python基于Apache2 Licensed许可证的人性化HTTP库。 Python标准库中urllib2提供了不少HTTP 功能,但API不系统。它有点过时,完成最简单的任务也需要大量工作。 下面我们用实例演示访问github。 >>> import requests >>> r = requests.get('https://api.github.com/user', auth=('ouyangchongwu@test.com', 'password')) >>> r.status_code 200 >>> r.headers['content-type'] 'application/json; charset=utf-8' >>> r.encoding 'utf-8' >>> r.text u'{"login":"oychw",...}' >>> r.json() {u'disk_usage': 176, u'private_gists': 0, ...} Requests为Python处理了所有HTTP/1.1操作, 与Web服务的无缝集成。不需要为URL手动添加查询字符串或POST数据进行表单处理。基于urllib3, 能自动处理Keep-alive和HTTP连接池。 特点: 国际化域名和 URLs Keep-Alive & 连接池 持久的 Cookie 会话 类浏览器的SSL认证 基本/摘要式的身份认证 优雅的键/值 Cookie 自动解压 Unicode响应体 多段文件上传 连接超时 支持 .netrc 适用于 Python 2.6—3.4 线程安全 用户手册 简介 Requests关注PEP 20的部分: Beautiful is better than ugly.(美丽优于丑陋) Explicit is better than implicit.(明确优于含糊) Simple is better than complex.(简单优于复杂) Complex is better than complicated.(复杂优于繁琐) Readability counts.(可读性) 安装 安装: 推荐:pip install requests,其次:easy_install requests 最新代码: git clone git://github.com/kennethreitz/requests.git 下载tar.gz包:curl -OL https://github.com/kennethreitz/requests/tarball/master 下载zip包:curl -OL https://github.com/kennethreitz/requests/zipball/master 源码安装:python setup.py install 快速入门 发送请求: 下面获取Github的公共时间线,并在httpbin演示其他HTTP操作: >>> import requests >>> r = requests.get('https://github.com/timeline.json') >>> r = requests.post("http://httpbin.org/post") >>> r = requests.put("http://httpbin.org/put") >>> r = requests.delete("http://httpbin.org/delete") >>> r = requests.head("http://httpbin.org/get") >>> r = requests.options("http://httpbin.org/get") 在URL中传递参数 URL的查询字符串(query string)例如, httpbin.org/get?key=val,在Requests可以用字典的形式构建。比如传递key1=value1和key2=value2到 httpbin.org/get: >>> import requests >>> payload = {'key1': 'value1', 'key2': 'value2'} >>> r = requests.get("http://httpbin.org/get", params=payload) >>> print(r.url) http://httpbin.org/get?key2=value2&key1=value1 >>> payload = {'key1': 'value1', 'key2[]': ['value2', 'value3']} >>> r = requests.get("http://httpbin.org/get", params=payload) >>> print(r.url) http://httpbin.org/get?key1=value1&key2%5B%5D=value2&key2%5B%5D=value3 注意字典里值为None的键会忽略。上面第2个例子访问的是http://httpbin.org/get?key1=value1&key2[]=value2&key2[]=value3 。注意key后面需要添加中括号对。 响应 >>> import requests >>> r = requests.get('https://api.github.com/events') >>> r.text >>> u'[{"id":"2636319727","type":"PullRequestReviewCommentEvent","actor":{"id":1148601,"login":"i ...}] >>> r.encoding 'utf-8' >>> r.encoding = 'ISO-8859-1' Requests会自动解码服务器的返回。大多数unicode字符集都能无缝解码。请求发出时Requests会基于响应的HTTP头部推测响应的编码。同时还可以设置和查询编码。改变编码后,访问 r.text 将会使用 r.encoding 。 二进制响应 r.content可以以字节的方式显示响应。 >>> r.content b'[{"repository":{"open_issues":0,"url":"https://github.com/... 传输格式gzip和deflate会自动转码。处理图片实例: >>> from PIL import Image >>> from StringIO import StringIO >>> i = Image.open(StringIO(r.content)) Json响应 Requests内置了JSON解码器: >>> import requests >>> r = requests.get('https://github.com/timeline.json') >>> r.json() {u'documentation_url': u'https://developer.github.com/v3/activity/events/#list-public-events', u'message': u"Hello there, wayfaring stranger. If you're reading this then you probably didn't see our blog post a couple of years back announcing that this API would go away: http://git.io/17AROg Fear not, you should be able to get what you need from the shiny new Events API instead."} JSON解码失败时r.json 就会抛出异常。例如, 401 (Unauthorized) , ValueError: No JSON object could be decoded等。 原始响应 极端的情况下需要查看服务器的原始套接字响应,请求时设置 stream=True: >>> import requests >>> r = requests.get('https://api.github.com/events', stream=True) >>> r.raw <urllib3.response.HTTPResponse object at 0x7f807dd6f4d0> >>> r.raw.read(10) '\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03' 通常需要存为文件: with open(filename, 'wb') as fd: for chunk in r.iter_content(chunk_size): fd.write(chunk) Response.iter_content 能减少直接使用Response.raw的大量处理,下载流时尤其推荐。 自定义头 >>> import requests >>> import json >>> url = 'https://api.github.com/some/endpoint' >>> payload = {'some': 'data'} >>> headers = {'content-type': 'application/json'} >>> r = requests.post(url, data=json.dumps(payload), headers=headers) 更加复杂的POST请求 表单直接以字典形式发送: >>> import requests >>> payload = {'key1': 'value1', 'key2': 'value2'} >>> r = requests.post("http://httpbin.org/post", data=payload) >>> print(r.text) { "args": {}, "data": "", "files": {}, "form": { "key1": "value1", "key2": "value2" }, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate, compress", "Content-Length": "23", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "python-requests/2.2.1 CPython/2.7.6 Linux/3.13.0-53-generic" }, "json": null, "origin": "119.122.150.177", "url": "http://httpbin.org/post" } string则会被直接发布出去。Github API v3中接受编码为JSON的POST/PATCH数据 >>> import requests >>> import json >>> url = 'https://api.github.com/some/endpoint' >>> payload = {'some': 'data'} >>> r = requests.post(url, data=json.dumps(payload)) POST复杂编码的文件 >>> import requests >>> url = 'http://httpbin.org/post' >>> files = {'file': open('/home/andrew/test.xls', 'rb')} >>> r = requests.post(url, files=files) >>> url = 'http://httpbin.org/post' >>> r.text u'{\n "args": {}, \n "data": "", \n "files": {\n ... "url": "http://httpbin.org/post"\n}\n' 可以显式地设置文件名,文件类型和请求头: >>> import requests >>> files = {'file': ('report.xls', open('/home/andrew/test.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})} >>> url = 'http://httpbin.org/post' >>> r = requests.post(url, files=files) >>> r.text u'{\n "args": {}, \n "data": ""..."url": "http://httpbin.org/post"\n}\n' 还可以直接用文字代替文件: >>> import requests >>> url = 'http://httpbin.org/post' >>> files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')} >>> r = requests.post(url, files=files) >>> r.text u'{\n "args": {}, \n "data": "", \n "files": {\n ... "json": null, \n "origin": "14.153.22.104", \n "url": "http://httpbin.org/post"\n}\n' multipart/form-data不支持特别大的文件,建议使用requests-toolbelt,参考:toolbelt 响应状态码 >>> import requests >>> r = requests.get('http://httpbin.org/get') >>> r.status_code 200 >>> r.status_code == requests.codes.ok True >>> bad_r = requests.get('http://httpbin.org/status/404') >>> bad_r.status_code 404 >>> bad_r.raise_for_status() >>> r.raise_for_status() 上面的requests.codes.ok是内置的状态码查询对象。可以使用 Response.raise_for_status()跑出失败请求(4XX客户端错误或5XX服务器异常),我们可以通过 Response.raise_for_status() 来抛出异常。r的返回为200,所以返回None,不产生异常。 响应头 >>> r.headers {'content-length': '275', 'server': 'nginx', 'connection': 'keep-alive', 'access-control-allow-credentials': 'true', 'date': 'Tue, 10 Mar 2015 08:21:36 GMT', 'access-control-allow-origin': '*', 'content-type': 'application/json'} >>> r.headers['Content-Type'] 'application/json' >>> r.headers.get('content-type') 'application/json' 根据 RFC 2616,HTTP头部不区分大小写。根据RFC 7230,接收方会对服务端对同一key的不同value进行组合。 Cookies 可以访问响应中包含的Cookie: >>> import requests >>> url = 'http://automationtesting.sinaapp.com/login' >>> r = requests.get(url) >>> r.cookies.keys() ['saeut', 'trac_form_token', 'trac_session'] >>> r.cookies['saeut'] 'CkMPGlT+tfQiXS9uGYviAg==' 使用cookies参数可以发送你的cookies到服务器: >>> import requests >>> url = 'http://httpbin.org/cookies' >>> cookies = dict(cookies_are='working') >>> r = requests.get(url, cookies=cookies) >>> r.text u'{\n "cookies": {\n "cookies_are": "working"\n }\n}\n' 重定向与请求历史 默认对HEAD以外其他所有动作进行位置重定向。Response.history可以看到重定向的记录。 >>> import requests >>> r = requests.get('http://github.com') >>> r.url u'https://github.com/' >>> r.status_code 200 >>> r.history [<Response [301]>] GET, OPTIONS, POST, PUT, PATCH 或者 DELETE可以通过allow_redirects参数禁用重定向,这个设置对HEAD也生效: >>> import requests >>> r = requests.get('http://github.com', allow_redirects=False) >>> r.status_code 301 >>> r.history [] >>> r = requests.head('http://github.com', allow_redirects=True) >>> r.url u'https://github.com/' >>> r.history [<Response [301]>] 超时 超时告诉requests在经过timeout参数的秒之后停止等待响应: >>> import requests >>> requests.get('http://github.com', timeout=0.1) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python2.7/dist-packages/requests/api.py", line 55, in get return request('get', url, **kwargs) File "/usr/lib/python2.7/dist-packages/requests/api.py", line 44, in request return session.request(method=method, url=url, **kwargs) File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 455, in request resp = self.send(prep, **send_kwargs) File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 558, in send r = adapter.send(request, **kwargs) File "/usr/lib/python2.7/dist-packages/requests/adapters.py", line 387, in send raise Timeout(e) requests.exceptions.Timeout: (<urllib3.connectionpool.HTTPConnectionPool object at 0x7f807dd6f050>, 'Connection to github.com timed out. (connect timeout=0.1)') >>> 注: 超时不是对整个响应下载的时间限制, 而且指定时间没有收到服务器返回就抛出异常。 错误与异常 ConnectionError:网络问题(如DNS失败、拒绝连接等)。 HTTPError: 比较罕见的无效HTTP响应时。 Timeout:请求超时。 TooManyRedirects:超过了设定的最大重定向次数。 requests.exceptions.RequestException是所有具体异常的基类。 高级用法 Session对象 Session对象能够跨请求保持参数,Session实例发出的所有请求共享cookies。 Session对象具有主Requests API的所有方法。 >>> s = requests.Session() >>> s.get('http://httpbin.org/cookies/set/sessioncookie/123456789') <Response [200]> >>> r = s.get("http://httpbin.org/cookies") >>> print(r.text) { "cookies": { "sessioncookie": "123456789" } } Session也可为request方法提供缺省数据,添加属性即可: >>> import requests >>> s = requests.Session() >>> s.auth = ('user', 'pass') >>> s.headers.update({'x-test': 'true'}) >>> s.get('http://httpbin.org/headers', headers={'x-test2': 'true'}) <Response [200]> 传递给request方法的字典都会与已有session层的值合并。方法层的参数会覆盖会话的参数。在方法层参数中将键值设置为None,会被自动忽略key。参考: session api 请求(Request)和响应(Response)对象 requests.get()等请求主要做两件的事情。一为构建Request 对象。二为收到服务器响应时产生Response 对象。Response对象包含服务器返回和原来的 Request 对象。 >>> import requests >>> r = requests.get('http://en.wikipedia.org/wiki/Monty_Python') >>> r.headers {'content-length': '67559', ...} >>> r.request.headers {'Connection': 'keep-alive', 'Accept-Encoding': ...} 预请求 当从API或会话调用接收Response对象时,request属性实际上是PreparedRequest。如果你需要修改body或header,可以如下方式进行处理: from requests import Request, Session s = Session() req = Request('GET', url, data=data, headers=header ) prepped = req.prepare() # do something with prepped.body # do something with prepped.headers resp = s.send(prepped, stream=stream, verify=verify, proxies=proxies, cert=cert, timeout=timeout ) print(resp.status_code) 这里没有对Request对象进行特殊处理,而是修改PreparedRequest对象。然后用requests.* 或Session.*.发送。 上述代码没有Request Session。Session层状态,如cookie不会使用。用Session.prepare_request()替换Request.prepare()即可增加状态支持: from requests import Request, Session s = Session() req = Request('GET', url, data=data headers=headers ) prepped = s.prepare_request(req) # do something with prepped.body # do something with prepped.headers resp = s.send(prepped, stream=stream, verify=verify, proxies=proxies, cert=cert, timeout=timeout ) print(resp.status_code) SSL证书验证 使用 verify 参数可以像web浏览器一样为HTTPS请求验证SSL证书: 参考资料 讨论qq群144081101 591302926 567351477 钉钉群21745728 requests英文文档 requests-docs-cn.readthedocs.org docs.python-requests.org/en/latest/ HTTP相关python库 本文最新版本地址 本文涉及的python测试开发库 谢谢点赞! 本文相关海量书籍下载

优秀的个人博客,低调大师

[雪峰磁针石博客]flask构建自动化测试平台3-模板

3-模板 理想情况下,前端和后端组件之间的完全隔离。我们可以在很大程度上使用Jinja来实现这一目标。 到本章将扩展我们的应用程序,为所选出版物显示不止一个标题。我们将为每个出版物显示多篇文章,每篇文章都链接到原始文章,我们的逻辑和视图组件将在很大程度上分开。在本章中,我们将介绍以下主题: 介绍Jinja Jinja模板使用 本文最新版本 介绍Jinja Jinja是一个Python模板引擎。它允许我们轻松定义由Python填充的动态HTML块。即使对于多个静态网页的网站,HTML模板也很有用有,如修改页眉和页脚。Flask基于Jinja,尽管可以单独使用Jinja,但Jinja仍然是Flask的固有部分。Flask和Flask提供了几种直接与Jinja工作的方法。默认情况下,Flask假定你存储了所有的Jinja模板位于您的应用程序的templates子目录中。 Jinja模板使用 home.html <html> <head> <title>Headlines</title> </head> <body> <h1>Headlines</h1> {% for article in articles %} <b><a href="{{article.link}}">{{article.title}}</a></b><br /> <i>{{article.published}}</i><br /> <p>{{article.summary}}</p> <hr /> {% endfor %} </body> </html> import feedparser from flask import Flask from flask import render_template app = Flask(__name__) RSS_FEEDS = {'bbc': 'http://feeds.bbci.co.uk/news/rss.xml', 'cnn': 'http://rss.cnn.com/rss/edition.rss', 'fox': 'http://feeds.foxnews.com/foxnews/latest', 'iol': 'http://www.iol.co.za/cmlink/1.640'} @app.route("/") @app.route("/<publication>") def get_news(publication="bbc"): feed = feedparser.parse(RSS_FEEDS[publication]) return render_template("home.html", articles=feed['entries']) if __name__ == "__main__": app.run(host='0.0.0.0',port=8000, debug=True) 参考资料 本文相关书籍下载 讨论 钉钉免费群21745728 qq群144081101 567351477 本文涉及的python测试开发库 谢谢点赞! 本文代码地址

优秀的个人博客,低调大师

[雪峰磁针石博客]flask构建自动化测试平台1-hello

简介 第一部分 Flask实例。学习使用Flask开发,构建功能完备的Web应用程序。我们开发了动态的头条新闻应用程序,可显示最新的新闻标题以及最新的货币和天气信息。在项目二中,我们构建了由MySQL数据库支持的犯罪地图应用程序,允许用户提交犯罪信息和犯罪地点,以便绘制区域内的危险区域和其他犯罪趋势。在最后的项目中,我们将Flask与更多现代技术结合在一起,例如Twitter的Bootstrap和NoSQL数据库MongoDB,以创建Waiter Caller应用程序,允许餐厅顾客轻松地将服务员叫到他们的桌子。 第二部分 Flask框架菜谱。涉及Flask的不同配置方式,如何使用模板并学习ORM和视图层。您将看到如何编写管理界面,随后进行错误调试和记录。最后,你会了解平台上的不同部署。 第三部分 掌握Flask,从简单的Flask应用程序展示

优秀的个人博客,低调大师

[雪峰磁针石博客]python库介绍-collections:高性能容器数据类型

简介 2.4新增 源代码:Lib/collections.py and Lib/_abcoll.py 提供了替换dict, list, set和tuple的数据类型。 主要类型如下: namedtuple(): 命名元组,创建有名字域的元组子类的工厂函数。python 2.6新增。 deque:双端队列,类似于列表,两端进栈和出栈都比较快速。python 2.4新增。 Counter:字典的子类,用于统计哈希对象。python 2.7新增。 OrderedDict:有序字典,字典的子类,记录了添加顺序。python 2.7新增。 defaultdict:dict的子类,调用一个工厂函数支持不存在的值。python 2.5新增。 还提供了抽象基类,用来测试类是否提供了特殊接口,不管是哈希或者映射。 Counter 计数器(Counter)是一个容器,用来跟踪值出现了多少次。和其他语言中的bag或multiset类似。 计数器支持三种形式的初始化。构造函数可以调用序列,包含key和计数的字典,或使用关键字参数。 import collections print(collections.Counter(['a', 'b', 'c', 'a', 'b', 'b'])) print(collections.Counter({'a': 2, 'b': 3, 'c': 1})) print(collections.Counter(a=2, b=3, c=1)) 执行结果: $ python3 collections_counter_init.py Counter({'b': 3, 'a': 2, 'c': 1}) Counter({'b': 3, 'a': 2, 'c': 1}) Counter({'b': 3, 'a': 2, 'c': 1}) 注意key的出现顺序是根据计数的从大到小。 可以创建空的计数器,再update: import collections c = collections.Counter() print('Initial :{0}'.format(c)) c.update('abcdaab') print('Sequence:{0}'.format(c)) c.update({'a': 1, 'd': 5}) print('Dict :{0}'.format(c)) 执行结果: python3.5 collections_counter_update.py* Initial :Counter() Sequence:Counter({'a': 3, 'b': 2, 'c': 1, 'd': 1}) Dict :Counter({'d': 6, 'a': 4, 'b': 2, 'c': 1}) 访问计数 import collections c = collections.Counter('abcdaab') for letter in 'abcde': print('{0} : {1}'.format(letter, c[letter])) 执行结果: $ python3.5 collections_counter_get_values.py a : 3 b : 2 c : 1 d : 1 e : 0 注意这里不存在的元素也会统计为0。 elements方法可以列出所有元素: import collections c = collections.Counter('extremely') c['z'] = 0 print(c) print(list(c.elements())) 执行结果: $ python3.5 collections_counter_elements.py Counter({'e': 3, 'y': 1, 'r': 1, 'x': 1, 'm': 1, 'l': 1, 't': 1, 'z': 0}) ['y', 'r', 'x', 'm', 'l', 't', 'e', 'e', 'e'] 注意后面并没有输出计数为0的元素。 most_common()可以提取出最常用的元素。 import collections c = collections.Counter() with open('/etc/adduser.conf', 'rt') as f: for line in f: c.update(line.rstrip().lower()) print('Most common:') for letter, count in c.most_common(3): print('{0}: {1}'.format(letter, count)) 执行结果: $ python3.5 collections_counter_most_common.py Most common: : 401 e: 310 s: 221 Counter还支持算术和集合运算,它们都只会保留数值为正整数的key。 import collections import pprint c1 = collections.Counter(['a', 'b', 'c', 'a', 'b', 'b']) c2 = collections.Counter('alphabet') print('C1:') pprint.pprint(c1) print('C2:') pprint.pprint(c2) print('\nCombined counts:') print(c1 + c2) print('\nSubtraction:') print(c1 - c2) print('\nIntersection (taking positive minimums):') print(c1 & c2) print('\nUnion (taking maximums):') print(c1 | c2) 执行结果: $ python3 collections_counter_arithmetic.py C1: Counter({'b': 3, 'a': 2, 'c': 1}) C2: Counter({'a': 2, 't': 1, 'l': 1, 'e': 1, 'b': 1, 'p': 1, 'h': 1}) Combined counts: Counter({'b': 4, 'a': 4, 'p': 1, 'e': 1, 'c': 1, 't': 1, 'l': 1, 'h': 1}) Subtraction: Counter({'b': 2, 'c': 1}) Intersection (taking positive minimums): Counter({'a': 2, 'b': 1}) Union (taking maximums): Counter({'b': 3, 'a': 2, 'p': 1, 'e': 1, 'c': 1, 't': 1, 'l': 1, 'h': 1}) 上面的例子让人觉得collections只能处理单个字符。其实不是这样的,请看标准库中的实例。 from collections import Counter import pprint import re cnt = Counter() for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']: cnt[word] += 1 pprint.pprint(cnt) cnt = Counter(['red', 'blue', 'red', 'green', 'blue', 'blue']) pprint.pprint(cnt) words = re.findall('\w+', open('/etc/adduser.conf').read().lower()) print(Counter(words).most_common(10)) 执行结果: $ python3 collections_counter_normal.py Counter({'blue': 3, 'red': 2, 'green': 1}) Counter({'blue': 3, 'red': 2, 'green': 1}) [('the', 27), ('is', 13), ('be', 12), ('if', 12), ('will', 12), ('user', 10), ('home', 9), ('default', 9), ('to', 9), ('users', 8)] 第1段代码和第2段的代码效果式样的,后面一段代码通过Counter实现了简单的单词的统计功能。比如面试题:使用python打印出/etc/ssh/sshd_config出现次数最高的10个单词及其出现次数。 下面看看Counter的相关定义: class collections.Counter([iterable-or-mapping]) 。注意Counter是无序的字典。在key不存在的时候返回0. c['sausage'] = 0。设置值为0不会删除元素,要使用del c['sausage']。 除了标准的字典方法,额外增加了: elements() :返回一个包含所有元素的迭代器,忽略小于1的计数。 most_common([n]):返回最常用的元素及其计数的列表。默认返回所有元素。 subtract([iterable-or-mapping]) :相减。 namedtuple 命名元组和普通元组的的内存效率差不多。它不会针对每个实例生成字典。 import collections Person = collections.namedtuple('Person', 'name age gender') print('Type of Person:{0}'.format(type(Person))) bob = Person(name='Bob', age=30, gender='male') print('\nRepresentation: {0}'.format(bob)) jane = Person(name='Jane', age=29, gender='female') print('\nField by name: {0}'.format(jane.name)) print('\nFields by index:') for p in [bob, jane]: print('{0} is a {1} year old {2}'.format(*p)) 执行结果: $ python3 collections_namedtuple_person.py Type of Person:<class 'type'> Representation: Person(name='Bob', age=30, gender='male') Field by name: Jane Fields by index: Bob is a 30 year old male Jane is a 29 year old female 从上例可以看出命名元组Person类和excel的表头类似,给下面的每个列取个名字,真正excel行数据则存储在Person类的实例中。好处在于可以jane.name这样的形式访问,比记元组的index要直观。 注意列名在实现内部其实是个标识符,所以不能和关键字冲突,只能用字母或者下划线开头。下例会报错: import collections try: collections.namedtuple('Person', 'name class age gender') except ValueError as err: print(err) try: collections.namedtuple('Person', 'name age gender age') except ValueError as err: print(err) 执行结果: $ python3 collections_namedtuple_bad_fields.py Type names and field names cannot be a keyword: 'class' Encountered duplicate field name: 'age' 设置rename=True,列名会在冲突时自动重命名,不过这种重命名并不美观。 import collections with_class = collections.namedtuple('Person', 'name class age gender', rename=True) print(with_class._fields) two_ages = collections.namedtuple('Person', 'name age gender age', rename=True) print(two_ages._fields) 执行结果: $ python collections_namedtuple_rename.py ('name', '_1', 'age', 'gender') ('name', 'age', 'gender', '_3') 定义 collections.namedtuple(typename, field_names, verbose=False) 返回一个命名元组类。如果verbose为True,会打印类定义信息 命名元组在处理数据库的时候比较有用: ChainMap 映射链 用于查找多个字典。 ChainMap管理一系列字典,按顺序根据key查找值。 访问值: API和字典类似。 collections_chainmap_read.py import collections a = {'a': 'A', 'c': 'C'} b = {'b': 'B', 'c': 'D'} m = collections.ChainMap(a, b) print('Individual Values') print('a = {}'.format(m['a'])) print('b = {}'.format(m['b'])) print('c = {}'.format(m['c'])) print() print('m = {}'.format(m)) print('Keys = {}'.format(list(m.keys()))) print('Values = {}'.format(list(m.values()))) print() print('Items:') for k, v in m.items(): print('{} = {}'.format(k, v)) print() print('"d" in m: {}'.format(('d' in m))) 执行结果: $ python3 collections_chainmap_read.py Individual Values a = A b = B c = C m = ChainMap({'c': 'C', 'a': 'A'}, {'c': 'D', 'b': 'B'}) Keys = ['c', 'a', 'b'] Values = ['C', 'A', 'B'] Items: c = C a = A b = B "d" in m: False 调整顺序 collections_chainmap_reorder.py import collections a = {'a': 'A', 'c': 'C'} b = {'b': 'B', 'c': 'D'} m = collections.ChainMap(a, b) print(m.maps) print('c = {}\n'.format(m['c'])) # reverse the list m.maps = list(reversed(m.maps)) print(m.maps) print('c = {}'.format(m['c'])) 执行结果: $ python3 collections_chainmap_reorder.py [{'c': 'C', 'a': 'A'}, {'c': 'D', 'b': 'B'}] c = C [{'c': 'D', 'b': 'B'}, {'c': 'C', 'a': 'A'}] c = D 更新值 更新原字典: collections_chainmap_update_behind.py import collections a = {'a': 'A', 'c': 'C'} b = {'b': 'B', 'c': 'D'} m = collections.ChainMap(a, b) print('Before: {}'.format(m['c'])) a['c'] = 'E' print('After : {}'.format(m['c'])) 执行结果 $ python3 collections_chainmap_update_behind.py Before: C After : E 直接更新ChainMap: collections_chainmap_update_directly.py import collections a = {'a': 'A', 'c': 'C'} b = {'b': 'B', 'c': 'D'} m = collections.ChainMap(a, b) print('Before:', m) m['c'] = 'E' print('After :', m) print('a:', a) 执行结果 $ python3 collections_chainmap_update_directly.py Before: ChainMap({'c': 'C', 'a': 'A'}, {'c': 'D', 'b': 'B'}) After : ChainMap({'c': 'E', 'a': 'A'}, {'c': 'D', 'b': 'B'}) a: {'c': 'E', 'a': 'A'} ChainMap可以方便地在前面插入字典,这样可以避免修改原来的字典。 collections_chainmap_new_child.py import collections a = {'a': 'A', 'c': 'C'} b = {'b': 'B', 'c': 'D'} m1 = collections.ChainMap(a, b) m2 = m1.new_child() print('m1 before:', m1) print('m2 before:', m2) m2['c'] = 'E' print('m1 after:', m1) print('m2 after:', m2) 执行结果 $ python3 collections_chainmap_new_child.py m1 before: ChainMap({'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'}) m2 before: ChainMap({}, {'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'}) m1 after: ChainMap({'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'}) m2 after: ChainMap({'c': 'E'}, {'a': 'A', 'c': 'C'}, {'b': 'B', 'c': 'D'}) 还可以通过传入字典的方式 collections_chainmap_new_child_explicit.py import collections a = {'a': 'A', 'c': 'C'} b = {'b': 'B', 'c': 'D'} c = {'c': 'E'} m1 = collections.ChainMap(a, b) m2 = m1.new_child(c) print('m1["c"] = {}'.format(m1['c'])) print('m2["c"] = {}'.format(m2['c'])) 执行结果 $ python3 collections_chainmap_new_child_explicit.py m1["c"] = C m2["c"] = E 另外一种等价的方式: m2 = collections.ChainMap(c, *m1.maps) 参考资料 本文最新版本地址 讨论 钉钉免费群21745728 qq群144081101 567351477 本文涉及的python测试开发库 谢谢点赞! 本文相关海量书籍下载 python官方文档:https://docs.python.org/3/library/collections.html https://pymotw.com/3/collections/chainmap.html http://collections-extended.lenzm.net/ https://pypi.python.org/pypi/collections-extended/ 本文代码地址

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册