网站首页 包含标签 Python 的所有文章

  • Json格式弊端及优化方案

    Json介绍 Json(JavaScript Object Notation)是一种轻量级的数据交换格式,常用于前后端数据传输和存储。 它使用简洁的文本格式来表示结构化的数据,易于阅读和编写,并且可以被多种编程语言解析和生成。 Json的基本语法包括键值对(key-value pairs)和数据类型。 键值对由一个键(key)和一个值(value)组成,中间用冒号(:)分隔。 多个键值对之间用逗号(,)分隔。值可以是字符串、数字、布尔值、数组、对象或null。 以下是一个Json对象的示例: { "name": "Raysen", "age": 27, "isStudent": true, "hobbies": ["唱", "RAP", "篮球"], "address": { "street": "23号大街", "city": "杭州", "country": "China" }, "favoriteFruit": null } 键值对的键是字符串,值可以是字符串(如”name”和”Raysen”)、数字(如”age”和30)、布尔值(如”isStudent”和true)、数组(如”hobbies”)或对象(如”address”)。键值对之间用逗号分隔,整个Json对象用花括号括起来。 Json的优点包括易于理解和编写、数据结构清晰、可读性强、支持多种编程语言等。它广泛应用于Web开发、API接口设计、配置文件等场景。 Json格式弊端 缺乏类型信息:Json格式的数据没有明确的类型信息,只能通过字段名来推断数据类型。这导致在处理复杂数据结构时,需要额外的逻辑来解析和处理数据。 不支持注释:Json格式不支持注释,这使得在复杂的数据结构中添加注释变得困难。注释对于代码的可读性和维护性非常重要,但在Json中无法直接添加注释。 不支持多行字符串:Json格式中的字符串必须在一行内表示,不支持多行字符串。这在处理较长的文本或包含换行符的字符串时,会导致可读性下降。 不支持原生日期类型:Json格式没有原生的日期类型,日期通常以字符串的形式表示。这使得在处理日期相关的操作时,需要额外的转换和处理。 不支持引用和循环引用:Json格式不支持引用其他对象或循环引用。这在处理复杂的数据关系时,可能会导致数据冗余和难以维护。 Json格式在一般的数据交换和存储场景中表现良好,但在处理复杂数据结构和需要更多元信息的情况下,存在一些不足之处。 Json弊端优化方案 使用压缩算法:可以使用压缩算法对Json格式进行压缩,减小数据的存储空间占用。 使用二进制格式:可以将Json格式转换为二进制格式,减少数据的存储空间和传输带宽。 使用Schema验证:可以使用Schema验证Json数据的结构和类型,提高数据的可靠性和可读性。 使用更紧凑的数据格式:可以考虑使用其他更紧凑的数据格式,如MessagePack、Protocol Buffers等,减小数据的存储空间和传输带宽。 ...

    2023-11-12 198
  • 什么是猴子补丁,有什么用

    一、什么是猴子补丁? 猴子补丁:Monkey Patch,主要功能就是动态的属性的替换,模块运行时替换的功能。 说直接点就是程序功能的追加或者变更。 二、Monkey Patch功能简介 Monkey Patch允许在程序运行期间动态的修改一个类或者模块。 三、举个例子 之前一个做游戏的,在很多地方都用了**import json,后来发现ujson比Python自带的json快很多,于是问题来了,几十几百个文件难道要一个一个的把import json替换成import ujson as json吗? 那也太痛苦了,其实只需要在进程开始的地方使用monkey patch**就行了,它是会影响整个进程空间的,同一进程空间中一个module只会被执行一次。 """ file:json_serialize.py """ import time import json # 时间测试装饰器 def run_time(func): def inner(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() print(f'程序用时:{end_time - start_time}') return result return inner @run_time def json_dumps(obj): return json.dumps(obj) # 生成测试字典 test_dict = {i: 1 for i in range(1, 10000001)} 使用json模块执行原程序: """ file:run.py """ from json_serialize import json_dumps, test_dict print(f'json.dumps编码用时:', end='') r1 = json_dumps(test_dict) 原程序的性能太低,我们可以使用ujson将json替换掉! 使用monkey patch修改后: """ file:run.py """ import json import ujson from json_serialize import json_dumps, test_dict def monkey_patch_json(): json.dumps = ujson.dumps monkey_patch_json() print(f'使用猴子补丁之后json.dumps编码用时:', end='') json_dumps(test_dict) 这个时候在这个项目中json模块就被monkey patch修改为了ujson模块。 ...

    2023-11-09 120
  • 编程语言排行榜及其特点、优缺点

    无论你是正在学习编程,还是已经是一位经验丰富的开发者,对于选择合适的编程语言都是一个不可回避的问题。 在这篇文章中,不念将比较并探讨八种常见的编程语言,帮助你选择最适合你的编程语言。 下图是2023年11月,由全球知名编程语言社区TIOBE公布的榜单,排在前5名的分别为Python,C,C++,Java,C#. 但我并不打算按照排名逐个介绍,而是从我的角度,我自认为的学习复杂度,由简单到复杂开始。这里排除了C语言,因为这个大家都太熟悉了,作为程序员,大学肯定都会学过C语言,即使非计算机专业,也都多少会了解一些C语言。 这里主要介绍其他的几个常用的高级语言,介绍其特点,优缺点以及使用场景等。 1. Python Python是一种高级、通用、解释型的编程语言。 它具有以下特点: 简洁易读:Python采用简洁的语法和明确的代码排版风格,使得代码具有良好的可读性,降低了学习和阅读代码的难度。 多用途:Python适用于各种领域的开发,包括Web开发、数据分析、人工智能、科学计算等,成为了非常通用的编程语言。 强大的库支持:Python拥有丰富的第三方库和框架,如Django、Flask、NumPy、Pandas等,为开发者提供了快速、高效的开发工具。 Python的主要优点有: 简单易学:Python的语法简洁清晰,初学者可以很快上手。 高效开发:Python提供了大量的库和开发工具,可以帮助开发者快速高效地完成项目。 广泛应用:Python可用于各种领域的开发,非常受前沿技术领域的青睐。 然而,Python也有一些缺点: 运行速度相对较慢:与编译型语言相比,Python的运行速度较慢,特别是在处理大规模数据时。 全局解释器锁(GIL):Python的GIL限制了多线程的并行执行,可能影响多线程应用的性能。 Python适合用于: Web开发:使用Django、Flask等框架可以快速构建稳定可靠的Web应用。 数据分析:Python拥有强大的数据处理和分析库,如NumPy、Pandas、Matplotlib等,适用于数据探索和分析。 人工智能:Python成为了深度学习、机器学习、自然语言处理等领域的主流语言,配合人工智能库如TensorFlow、PyTorch等可以进行模型训练与应用开发。 典型的开源软件和框架: Django:一个强大的Python Web框架,用于构建高效的Web应用程序。 NumPy:一个高性能科学计算库,提供了强大的多维数组对象和相关函数。 TensorFlow:一个流行的深度学习框架,用于构建和训练神经网络模型。 Python拥有一个活跃的社区,有大量的在线资源、各种教程和社区论坛,开发者可以方便地获取帮助和交流经验。 2. Java Java是一种高级、面向对象的编程语言。 它具有以下特点: 平台无关性:Java使用Java虚拟机(JVM)作为中间层,在不同的平台上都可以运行,这使得Java具备了平台无关性的特点。 强类型语言:Java是一种静态类型的语言,变量需提前声明并指定类型。 强大的生态系统:Java拥有庞大、稳定且成熟的生态系统,包括丰富的开发工具、框架和库。 Java的主要优点有: 可靠性和稳定性:Java的设计注重可靠性和稳定性,具备异常处理机制、垃圾回收等特性,提供了更高的代码健壮性和稳定性。 多线程支持:Java提供了多线程支持,开发者可以轻松实现多线程并发编程。 大型应用开发:Java适用于开发大型应用和企业级应用,如JavaEE,可以构建高可用、高性能的分布式系统。 然而,Java也有一些缺点: 冗长的语法:相比其他语言,Java的语法相对冗长,需要更多的代码量来完成相同的功能。 相对较慢的运行速度:与一些编译型语言相比,Java的运行速度较慢。 Java适合用于: 企业级应用开发:Java的稳定性、可靠性和强大的生态系统使其成为开发大型企业级应用的首选语言。 Android应用开发:Java是Android平台的主要开发语言,可以用于开发各种类型的Android应用。 大数据处理:Java拥有大量的开源框架,如Hadoop、Spark等,适合处理大规模数据和分布式计算。 典型的开源软件和框架: Spring Framework:一个全功能的Java开发框架,用于构建企业级应用程序。 Hibernate:一个强大的对象关系映射(ORM)框架,用于简化Java应用程序与数据库之间的交互。 Apache Hadoop:一个可扩展的大数据处理框架,对于大规模数据的分布式处理非常有效。 Java拥有广泛的社区支持和活跃的开发者社区,在线教程、文档和社区论坛等资源丰富,对于学习和解决问题都非常有帮助。 3. JavaScript JavaScript是一种脚本语言,主要用于在网页上实现交互功能。它具有以下特点: 动态性:JavaScript是一种动态类型的语言,变量的类型在运行时可以自动推断。 客户端脚本语言:JavaScript主要在浏览器中执行,用于增强用户界面的交互性。 事件驱动:JavaScript通过事件机制响应用户的操作,并进行相应处理。 JavaScript的主要优点有: 前端开发:JavaScript是前端开发的核心语言,用于构建交互性的网页应用,丰富用户体验。 灵活性:JavaScript具有灵活性,可以方便地修改和调试,适合快速迭代开发。 强大的库支持:JavaScript拥有众多的开源库和框架,如React、Vue.js等,可以提高开发效率。 然而,JavaScript也有一些缺点: 兼容性问题:不同浏览器对JavaScript的支持并不完全一致,需要注意兼容性问题。 安全性:由于JavaScript运行在浏览器端,存在一些安全性的考虑,需要注意防止恶意代码注入。 JavaScript适合用于: 网页交互:JavaScript用于网页中的表单验证、用户行为追踪等交互功能的实现。 前端框架:JavaScript的框架和库如React、Angular、Vue.js等用于构建现代化的前端应用。 后端开发:通过Node.js,JavaScript也可用于后端开发,构建高性能、可扩展的服务器应用。 典型的开源软件和框架: React:一个流行的JavaScript库,用于构建用户界面。 Vue.js:一个轻量级、易用的JavaScript框架,适用于构建交互式Web界面。 Node.js:一个基于Chrome V8引擎的JavaScript运行环境,用于构建高性能的服务器端应用。 JavaScript拥有一个非常活跃的社区,开发者可以在GitHub上找到许多优秀的开源项目,也可以通过在线文档和社区论坛获取帮助和交流经验。 4. C++ C++是一种通用的、编译型的、静态类型的编程语言。它具有以下特点: 高效性:C++是一种性能卓越的语言,可以直接操作硬件,提供了更高的运行效率。 面向对象:C++支持面向对象编程,具有封装、继承、多态等特性。 强大的库支持:C++有丰富的标准库和第三方库,利于程序员开发高效的应用。 C++的主要优点有: 高效性:C++具备高效的运行速度和低内存消耗,适用于开发对性能要求高的应用,如游戏、图形、嵌入式系统等。 与C语言兼容:C++源代码可以与C语言混合编译,方便现有C代码的重用。 强大的控制能力:C++提供了底层的内存控制和强大的指针操作能力,使得程序员可以更精细地控制程序的执行。 然而,C++也有一些缺点: 语法复杂:C++的语法相对复杂,对初学者来说学习难度较大。 内存管理:C++需要手动管理内存,容易出现内存泄漏和指针悬挂等问题。 C++适合用于: 系统和游戏开发:C++的高效性使得它成为系统级程序和游戏开发的首选语言。 性能关键的应用:C++适用于需要高性能和低延迟的领域,如金融、科学计算等。 底层开发:C++的底层控制能力使其适合开发驱动程序和嵌入式系统。 典型的开源软件和框架: Boost:一个功能强大且广泛使用的C++库集合,提供了许多工具和组件,可帮助开发者提高开发效率。 Qt:一个跨平台的C++应用程序开发框架,用于构建图形用户界面和嵌入式应用。 C++拥有庞大的开发者社区和活跃的社区资源,不仅有众多的在线文档、教程和论坛,还有许多优秀的开源项目可以供开发者参考和学习。 5. C# C#(读作C-Sharp)是一种通用的、编译型的、面向对象的编程语言。它具有以下特点: 与.NET紧密集成:C#是.NET平台的核心语言,与.NET框架紧密集成,使得开发过程更加高效。 简单易学:C#的语法类似于Java和C++,易于理解和上手。 跨平台:C#不仅可以在Windows上运行,还支持跨平台开发,如使用.NET Core可在Linux、macOS等上运行。 C#的主要优点有: 简单易学:C#的语法简洁,类似于其他主流语言,使得开发人员能够快速上手。 强大的.NET生态系统:C#在.NET平台上拥有丰富的类库和框架,提供了大量的功能和工具,方便开发人员进行应用开发。 面向对象:C#支持面向对象编程,提供了封装、继承、多态等特性,可以更好地组织和管理代码。 然而,C#也有一些缺点: Windows依赖:C#最初是为Windows开发的,虽然现在也支持跨平台开发,但在一些特定领域内的使用可能存在限制。 生态系统相对局限:与一些其他编程语言相比,C#的开源库和框架相对较少,选择范围相对较小。 C#适合用于: Windows应用开发:C#具有与Windows紧密集成的特点,适合用于开发Windows应用程序和游戏。 Web开发:通过ASP.NET,C#也可以用于Web开发,构建可靠且高性能的Web应用。 Unity游戏开发:C#是Unity游戏引擎的主要脚本语言,用于开发跨平台的游戏。 典型的开源软件和框架: ASP.NET:一个用于构建Web应用的框架,具有强大的性能和安全性。 Entity Framework:一个面向对象的数据库访问框架,简化了与数据库的交互。 C#拥有活跃的社区和大量的学习资源,开发者可以通过微软官方文档、在线教程和社区论坛等途径获取帮助和交流经验。 6. PHP PHP(Hypertext Preprocessor)是一种通用的脚本语言,主要用于服务器端编程。它具有以下特点: 强大的Web开发能力:PHP最初设计用于处理动态网页,因此在Web开发方面具备强大的能力。 面向对象:PHP支持面向对象编程,具有类、继承、封装等特性。 容易入门:PHP的语法类似于C语言,相对易于学习和上手。 PHP的主要优点有: 广泛应用:PHP被广泛用于Web开发,特别是动态网页的开发,如CMS、电子商务网站等。 快速开发:PHP提供了许多内置函数和扩展,使开发人员能够快速构建功能丰富的网站和应用。 跨平台:PHP可以运行在主流的操作系统上,如Windows、macOS、Linux等。 然而,PHP也有一些缺点: 性能相对较低:相比一些编译型语言,PHP的性能较低,尤其对于大规模并发和高负载的场景。 代码可维护性差:PHP在语法灵活性上强调了开发速度,但也容易导致代码可读性和可维护性的问题。 PHP适合用于: Web开发:PHP是一种强大的Web开发语言,用于构建各种类型的网站、应用和系统。 动态网页:通过与HTML混编,PHP可以实现动态网页的生成和内容交互。 数据库操作:PHP提供了丰富的数据库操作支持,如MySQL、SQLite等。 典型的开源软件和框架: WordPress:一个流行的开源CMS(内容管理系统),采用PHP开发。 Laravel:一个功能强大且易于使用的PHP框架,用于构建高效的Web应用程序。 Symfony:一个用于构建复杂Web应用的PHP框架,提供了大量的组件和工具。 PHP有一个庞大的开发者社区,有许多在线文档、教程和社区论坛可以供开发者学习和交流。 7. Swift 特点 高性能:Swift在编译时进行优化,生成高效的本机代码,因此具有出色的性能。 安全性:Swift引入了许多安全机制,如类型检查、内存安全和错误处理,可以帮助开发者避免一些常见的编程错误和安全漏洞。 现代化语言特性:Swift支持诸如类型推断、闭包、泛型等现代化语言特性,使开发者能够更加高效地编写代码。 优点 易学易用:Swift的语法简洁易懂,类似于英语,使得入门门槛较低。 强大的开发工具:Xcode是一款功能强大的集成开发环境,提供了许多有用的工具和调试功能,可以极大地提高开发效率。 多平台支持:Swift可以编写 iOS、macOS、watchOS和tvOS等平台上的应用程序,方便开发者进行跨平台开发。 缺点: 相对较新:Swift相比其他语言来说相对较新,因此社区和生态系统相对较小。 代码兼容性:由于Swift语言不断演进,代码迁移可能会带来一些兼容性问题。 适用场景: iOS开发:Swift是开发iOS应用程序的首选语言,具有强大的开发工具和丰富的iOS生态系统。 macOS开发:Swift也可以用于开发macOS应用程序,享受到其语法简洁和高效性能的优势。 典型的开源软件或框架: Alamofire:一款非常受欢迎的Swift网络请求框架,提供了简单易用的API,方便进行网络数据交互。 SwiftUI:一个现代化的用户界面框架,用于构建iOS和macOS应用程序,提供了声明式语法和直观的可视化工具。 Swift具有一个活跃的社区,有许多在线论坛、博客和代码库,为开发者提供了丰富的资源和交流机会。开发者可以从中获取帮助、分享经验和学习最新的Swift技术。除此之外,苹果公司也在不断推动Swift的发展,发布了大量的教程和文档,致力于提供最佳的开发体验和支持。 8. Go 特点: 并发性:Go语言具有原生支持并发的特性,通过goroutine和通道机制,可以更轻松地实现并发编程。 高效性:Go语言的编译速度非常快,同时也具有高效的执行性能,适合用于构建高性能的分布式系统。 简洁性:Go语言的语法简洁明了,强调可读性和简单性,对于快速开发和维护代码非常便捷。 优点: 并发编程:通过goroutine和通道机制,Go语言可以轻松实现高并发的并行任务,处理大规模的并发问题非常高效。 内置工具支持:Go语言带有丰富的标准库和内置工具,例如测试框架、性能分析工具等,方便开发者进行开发、测试和性能优化。 跨平台:Go语言可以在多个平台上进行编译,适用于开发跨平台的应用程序。 缺点: 代码冗长:相比起其他语言,Go语言的代码可能会显得冗长,一些简单的功能可能需要较多的代码行数来实现。 生态系统相对较小:虽然Go的生态系统正在不断发展壮大,但与其他一些编程语言相比,它的生态系统相对较小一些。 适用场景: 分布式系统:Go的高效性和并发性特点使其非常适合用于构建分布式系统,如微服务架构。 网络编程:Go语言设计用于处理网络通信,通过其原生的并发和协程机制,可以轻松实现高性能的网络应用程序。 典型的开源软件或框架: Gin:一款轻量级且高性能的Web框架,用于构建RESTful API。 Docker:一个开源的容器化平台,使用Go语言开发,广泛用于部署和管理容器。 Kubernetes:一种用于自动化部署、扩展和管理容器化应用程序的开源平台,也是用Go语言开发。 Go语言拥有一个活跃的社区,吸引了许多开发者和公司的关注,提供了丰富的资源和交流机会。开发者可以从社区获得教程、文档、示例代码等,同时也可以积极参与社区的讨论和贡献。 在选择编程语言时,关键是要考虑你的目标和项目需求。 不同的语言在不同的应用场景下有其优势和限制。 因此,建议你根据自己的兴趣和需求进行选择,并相应地学习和提升。 无论你选择哪种编程语言,持续学习和实践都是成为一名优秀开发者的关键。 ...

    2023-11-03 149
  • 如何使用Python制作脚本巡检设备,并将结果输出到excel

    本脚本使用了 pexpect 库来自动化 Telnet 登录到交换机并执行命令,然后将输出保存到文件中。 如果你想要将输出存储到 Excel 文件中,你可以使用 openpyxl 库来实现。 下面是一个将你提供的脚本与 Excel 输出结合的示例: import pexpect import sys import datetime import openpyxl # 定义交换机信息和命令 switch_info = { "ip": "x.x.x.x", "passwd": "xxxx", "name": "<F5-Core-S12508>", "name1": "---- More ----" } # 创建 Excel 工作簿和工作表 workbook = openpyxl.Workbook() worksheet = workbook.active worksheet.title = "Switch Inspection" child = pexpect.spawn('telnet %s' % switch_info["ip"]) child.expect('login:') child.sendline("admin") child.expect('(?i)ssword:') child.sendline(switch_info["passwd"]) child.expect(switch_info["name"]) # 执行命令并将输出写入 Excel def execute_command(command): child.sendline(command) child.expect(switch_info["name1"]) result = child.before.decode("utf-8") return result # 执行各个命令并写入 Excel commands = [ "display power", "display version", "display environment", "display fan", "display cpu-usage", "display memory", "display interface brief", "dis logbuffer", "display ip routing-table", "display irf link", ] for command in commands: output = execute_command(command) worksheet.append([command, output]) child.sendline("quit") child.expect(pexpect.EOF) # 保存 Excel 文件 excel_filename = f"switch_inspection_{datetime.date.today().strftime('%Y%m%d')}.xlsx" workbook.save(excel_filename) print(f"Inspection results saved to {excel_filename}") 在这个示例中,我使用了 openpyxl 库来创建 Excel 工作簿和工作表,并在每次执行命令后将输出写入 Excel 表格中。 你可以根据实际需要进一步调整和优化这个脚本,确保交换机命令的执行和输出的写入都能符合你的要求。 同时,记得确保在运行脚本之前安装了所需的库: pip install pexpect openpyxl 自动化与 Telnet 进行交互时,稳定性和错误处理非常重要,因为网络环境可能会导致意外情况。 ...

    2023-08-10 184
  • Python 将杂乱文件自动归类整理

    目录格式 默认的文件路径格式 \ 而 Python 里需要修改成 \\,或者在目录前面加上 r字母。 # 方法一 path = r'F:\test\文件自动归类整理' # 文件目录 # 方法二 path = 'F:\\test\\文件自动归类整理' # 文件目录 这里我使用的是方法二,来进行以下操作。 改变操作目录 首先导入 os模块,使用 os.chdir()函数,打开目录,再使用 os.getchd()函数,查看当前目录,进行确认。 import os # 导入os模块 path = r'F:\test\文件自动归类整理' # 文件目录 os.chdir(path) # 打开目录 print(os.getcwd()) # 输出:F:\test\文件自动归类整理 改变操作目录 当目录确认好后,再使用 os.listdir()函数,获取目录下所有的文件 import os # 导入 os 模块 path = r'F:\test\文件自动归类整理' # 文件目录 os.chdir(path) # 打开目录 # 获取目录下所有文件 contents = os.listdir() for content in contents: print(content) # 输出: # 备忘 # 开心 2.jpg # 开心.jpg # 心情日记.docx # 现场留言.mp3 还没写完... ...

    2022-02-14 540
  • 别去送死了!爬虫使用 Selenium 与 Puppeteer 能被网站探测的几十个特征

    很多人喜欢使用 Selenium 或 Puppeteer(Pyppeteer) 通过模拟浏览器来编写爬虫,自以为这样可以不被网站检测到,想爬什么数据就爬什么数据 但实际上,Selenium 启动的浏览器,有几十个特征可以被网站通过 JavaScript 探测到;Puppeteer 启动的浏览器,也有很多特征能够被网站探测 如果你不相信,那么我们来做一个实验。首先你使用正常的浏览器打开如下网址:https://bot.sannysoft.com/ 可以看到,页面的内容如下: 这个页面很长,你得滚动鼠标往下看,大部分都是绿色的 接下来,使用 Selenium启动一个 Chrome 的有头模式,再打开这个页面看看效果: 一开始 WebDriver这一项就标红了,说明网站成功检测到你使用模拟浏览器了 你再往下翻,标红的都是可以被检测出的特征 左边是普通浏览器,右边是模拟浏览器 左边是普通浏览器,右边是模拟浏览器 如果你一项一项对比,就会发现很多地方都不一样 这还是有头模式的效果。我们来看看无头模式: from selenium.webdriver import Chrome from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument("--headless") driver = Chrome('./chromedriver', options=chrome_options) driver.get('https://bot.sannysoft.com/') driver.save_screenshot('screenshot.png') 截图打开以后是下面这样的。不要吓到: 万里河山一片红 这么多特征都直接暴露了,你还隐藏个屁。网站只要想发现你,非常容易。 既然 Selenium 不行,那 Puppeteer 或者 Pyppeteer怎么样呢? 我们使用 Pyppeteer 来做个实验,直接启动无头模式并截图 运行效果是下面这样的: 跟 Selenium 没什么区别 所以,你还好意思继续用这两个东西来写爬虫? 爬点没有安全意识的小网站可以,爬那些有强大安全团队和法务团队的公司,你就是在找死! ...

    2021-02-19 814
  • 如何正确设置 Python 项目的入口文件?

    今天在Kirin博客粉丝交流群里面,有一位爱好者提到了 Python 找不到模块的问题:问题涉及到的代码结构和代码截图如下: 这个问题的解决方法非常简单,就是把start.py文件从bin文件夹移出来就好了。 但如果对这个问题进一步分析,可以看到更多问题。 在我以前的文章:为什么Python代码能运行但是PyCharm给我画红线?中,我讲到了工作区(Workdir)对代码的影响。PyCharm、VSCode 识别的工作区,可能并不等于你直接在终端窗口运行.py文件时候的工作区。 今天这个问题本质上也是工作区导致的问题。这个同学的项目根目录是MY_API,所以他使用的编辑器VSCode 就会默认把MY_API当做工作区。所以,当他在start.py文件中写上from lib.interface import server时,VScode 并不会给他标记红色波浪线。因为从 VSCode 的视角看,lib文件夹确实就是在工作区下面的。 但是,当他在 VSCode 里面运行这个start.py文件时,Python 是从bin文件夹下面运行的。此时,Python 会把bin文件夹当做工作区。在工作区里面就只有这一个start.py文件,所以当然找不到lib文件夹。 如果仅仅从技术上来说,你非要导入 bin 文件夹的父文件夹下面的其他模块,也并不困难,我在一日一技:导入父文件夹中的模块并读取当前文件夹内的资源一文中讲到了具体的做法。 但问题在于,你不应该这样做。你不应该把项目的入口文件,放到项目内部很深的文件夹中。 所谓入口文件,就是要首先经过它,才能到达其他的文件。当你拿到一个 Python 项目,你只需要首先从入口文件开始阅读代码,根据入口文件调用的模块,一路看下去,你就能读到它的所有实现逻辑。 但如果大家经常逛 Github,就会发现,有些人可能是被其他垃圾语言污染了思想,他的 Python 项目,根目录有五六个文件夹和七八个.py文件。你拿到这个项目的时候,你甚至不知道,当你想运行这个代码的时候,python3 xxx.py应该运行哪个文件。你多方打听,或者看了半天文档,才知道,哦,原来入口文件在com/xx/yy/zz/script/run.py。 当你打开这个run.py文件,你发现它的顶部,文件导入的代码写的是from ../../../../aaa import bbb。 简直是神经病写法。我知道有些垃圾语言流行这样写。但现在你用的是 Python,学聪明一点,别那样写。 对于一个 Python 项目来说,入口文件应该始终在最外层。例如: 当你要启动这个项目的时候,直接在最外层python3 main.py,就能把它启动起来。在main.py里面,你可以导入其他模块,然后调用其他模块里面的类或者函数。 这样做的好处是什么?这样做,你是在项目的根目录启动的这个项目,所以你的工作区就是项目的根目录。那么你在任何一个.py文件里面都可以很容易地基于工作区导入任意其他文件。例如,你现在在models/mongo-util/mongob_helper.py文件中,你想导入utils/abc.py中的time_format()函数,那么,你只需要这样写就可以了。 from utils.abc import time_format 你根本不可能出现需要导入父文件夹中的某个模块的情况。 只有工具脚本,才需要单独使用一个文件夹来存放,然后调用父文件夹中的其他文件。例如,我现在有一个工具脚本,它每天晚上0点会读写 MongoDB,清理无效数据,那么此时,我可以在根目录单独创建一个script或tools或者bin文件夹,然后把工具脚本放进去,例如: 在这个工具脚本里面,你可能会调用models/mongo-util/mongob_helper.py文件中的某个函数。这种情况下,你调用父文件夹中的内容是可以接受的。但这毕竟只是工具脚本。 可能还有同学要问,那如果我的项目是一个 Python 的包,它本身没有入口文件怎么办呢?这个时候,你可以把这个包的__init__.py当做它的入口文件。大家可以参考我在 GitHub - kingname/GeneralNewsExtractor: 新闻网页正文通用抽取器 Beta 版.[1]的代码组织结构。在项目根目录留下一个example.py文件,用来演示如何调用这个包。而这个包本身的代码,是在一个叫做gne的文件夹中的。这个gne文件夹是一个包,它的入口文件在__init__.py中。 ...

    2021-02-19 782
  • Python 中为什么不建议使用 time.sleep 实现定时功能?

    有时候,我们想实现一个非常简单的定时功能,例如:让一个程序每天早上 8 点调用某个函数 但我们又不想安装任何第三方库,也不会使用 crontab 或者任务计划功能,就想使用纯 Python 来实现 可能有同学会这样写代码: import time import datetime def run():     print('我是需要被每天调用的函数') def schedule():     target_time = datetime.time(8, 0, 0)     today = datetime.date.today()     target_date = today + datetime.timedelta(days=1)     target_datetime = datetime.datetime.combine(target_date, target_time)     now = datetime.datetime.now()     delta = (target_datetime - now).total_seconds()     time.sleep(delta)     run()     while True:         time.sleep(24 * 3600)         run() if __name__ == '__main__':     schedule() 这段程序,首先计算出现在距离明天早上 8 点相差的秒数;睡眠这么多秒以后,第一次运行目标函数,然后进入一个死循环,每隔 86400 秒,程序调用一次 run 函数 这个程序初看起来,似乎没有什么问题 但如果你每天观察它的运行时间,你会发现随着时间的推移,时间会越来越不准确 这是因为,run 函数不是一瞬间就运行完成的。它运行也会消耗时间 假设程序第一次运行 run 函数的时候,确实刚刚好是 8:00,run 函数运行了 2秒;那么,程序睡眠 86400 秒以后,时间实际上是 8:00:02.从第二天开始,每天晚 2 秒钟。一个月就会晚一分钟 但实际上,我们如果付出一点点微不足道的代价,我们就可以防止这种误差的发生,并且程序代码会变得更简单: import time import datetime def run():     print('我是需要被每天调用的函数') def schedule():     last_run = None     while True:         now = datetime.datetime.now()         if now.strftime('%H:%M') == '08:00' and last_run != now.date():             run()             last_run = now.date()         time.sleep(1) if __name__ == '__main__':     schedule() 程序在一个死循环中,每秒做一次检查,如果当前的时分正好是 08:00,并且上一次运行不是今天,那么就调用 run 函数,并把上一次运行的时间设置为今天。否则,就睡眠 1 秒钟 这样做,相当于每秒都会校对时间,从而避免了长时间运行导致的时间误差。虽然看起来这个死循环会非常消耗 CPU,但只要你算一下,实际上它只不过每天循环 86400 次而已。这个次数并不多 但无论如何,专业的事情应该交由专业的工具来做;time.sleep 用来设置周期性的时间间隔可以,但它实际上不适合用来做定时任务 因为一个支持定时任务的库,例如:Python 的schedule或者APScheduler,他们在确保定时时间准确上,做了很多工作。还有一些库甚至用到了时间轮这样的数据结构来确保时间的准确性。这不是我们简单用两三行 Python 代码就能完成的。 总结 如果能用 crontab 或者任务计划,那么这是最优选择;其次,使用 Python 专用的定时模块;最次,才是使用 time.sleep 来实现 如果不得不用 time.sleep,那么应该尽量缩短检查的间隔,避免长时间睡眠 ...

    2020-12-23 958
  • 如何提高 Python 的运行速度?

    Python 目前得到了众多程序员的喜爱,但是还是遭到一些人的诟病,原由之一就是认为它运行缓慢。 其实某个特定程序(无论使用何种编程语言)的运行速度是快还是慢,在很大程度上取决于编写该程序的开发人员自身素质,以及他们编写优化而高效代码的能力。 Medium 上一位小哥就详细讲了讲如何让 Python 提速 30%,以此证明代码跑得慢不是 Python的问题,而是代码本身的问题。 01时序分析 在开始进行任何优化之前,我们首先需要找出代码的哪些部分使整个程序变慢。有时程序的问题很明显,但是如果你一时不知道问题出在哪里,那么这里有一些可能的选项: 注意:这是我将用于演示的程序,它将进行指数计算 # slow_program.py from decimal import * def exp(x):     getcontext().prec += 2     i, lasts, s, fact, num = 0, 0, 1, 1, 1     while s != lasts:         lasts = s         i += 1         fact *= i         num *= x         s += num / fact     getcontext().prec -= 2     return +s exp(Decimal(150)) exp(Decimal(400)) exp(Decimal(3000)) 最简约的“配置文件” 首先,最简单最偷懒的方法——Unix时间命令。 ~ $ time python3.8 slow_program.py real  0m11,058s user 0m11,050s sys 0m0,008s 如果你只能知道整个程序的运行时间,这样就够了,但通常这还远远不够。 最详细的分析 另外一个指令是cProfile,但是它提供的信息过于详细了。 ~ $ python3.8 -m cProfile -s time slow_program.py          1297 function calls (1272 primitive calls) in 11.081 seconds    Ordered by: internal time    ncalls tottime percall cumtime percall filename:lineno(function)         3   11.079    3.693   11.079    3.693 slow_program.py:4(exp)         1    0.000    0.000    0.002    0.002 {built-in method _imp.create_dynamic}       4/1    0.000    0.000   11.081   11.081 {built-in method builtins.exec}         6    0.000    0.000    0.000    0.000 {built-in method __new__ of type object at 0x9d12c0}         6    0.000    0.000    0.000    0.000 abc.py:132(__new__)        23    0.000    0.000    0.000    0.000 _weakrefset.py:36(__init__)       245    0.000    0.000    0.000    0.000 {built-in method builtins.getattr}         2    0.000    0.000    0.000    0.000 {built-in method marshal.loads}        10    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:1233(find_spec)       8/4    0.000    0.000    0.000    0.000 abc.py:196(__subclasscheck__)        15    0.000    0.000    0.000    0.000 {built-in method posix.stat}         6    0.000    0.000    0.000    0.000 {built-in method builtins.__build_class__}         1    0.000    0.000    0.000    0.000 __init__.py:357(namedtuple)        48    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:57(_path_join)        48    0.000    0.000    0.000    0.000 <frozen importlib._bootstrap_external>:59(<listcomp>)         1    0.000    0.000   11.081   11.081 slow_program.py:1(<module>) 在这里,我们使用cProfile模块和time参数运行测试脚本,以便按内部时间(cumtime)对行进行排序。这给了我们很多信息,你在上面看到的行大约是实际输出的10%。由此可见,exp函数是罪魁祸首,现在我们可以更详细地了解时序和性能分析。 时序特定功能 现在我们知道了应当主要关注哪里,我们可能想对运行速度缓慢的函数计时,而不用测量其余的代码。为此,我们可以使用一个简单的装饰器: def timeit_wrapper(func):     @wraps(func)     def wrapper(*args, **kwargs):         start = time.perf_counter() # Alternatively, you can use time.process_time()         func_return_val = func(*args, **kwargs)         end = time.perf_counter()         print('{0:<10}.{1:<8} : {2:<8}'.format(func.__module__, func.__name__, end - start))         return func_return_val     return wrapper 然后可以将此装饰器应用于待测功能,如下所示: @timeit_wrapper def exp(x):     ... print('{0:<10} {1:<8} {2:^8}'.format('module', 'function', 'time')) exp(Decimal(150)) exp(Decimal(400)) exp(Decimal(3000)) 这给出我们如下输出: ~ $ python3.8 slow_program.py module function   time   __main__ .exp      : 0.003267502994276583 __main__ .exp      : 0.038535295985639095 __main__ .exp      : 11.728486061969306 需要考虑的一件事是我们实际想要测量的时间。时间包提供time.perf_counter和time.process_time两个函数。他们的区别在于perf_counter返回的绝对值,包括你的Python程序进程未运行时的时间,因此它可能会受到计算机负载的影响。另一方面,process_time仅返回用户时间(不包括系统时间),这仅是你的过程时间。 02加速吧! 让Python程序运行得更快,这部分会很有趣!我不会展示可以解决你的性能问题的技巧和代码,更多地是关于构想和策略的,这些构想和策略在使用时可能会对性能产生巨大影响,在某些情况下,可以将速度提高30%。 使用内置数据类型 这一点很明显。内置数据类型非常快,尤其是与我们的自定义类型(例如树或链接列表)相比。这主要是因为内置程序是用C实现的,因此在使用Python进行编码时我们的速度实在无法与之匹敌。 使用lru_cache缓存/记忆 我已经在上一篇博客中展示了此内容,但我认为值得用简单的示例来重复它: import functools import time # caching up to 12 different results @functools.lru_cache(maxsize=12) def slow_func(x):     time.sleep(2) # Simulate long computation     return x slow_func(1) # ... waiting for 2 sec before getting result slow_func(1) # already cached - result returned instantaneously! slow_func(3) # ... waiting for 2 sec before getting result 上面的函数使用time.sleep模拟大量计算。第一次使用参数1调用时,它将等待2秒钟,然后才返回结果。再次调用时,结果已经被缓存,因此它将跳过函数的主体并立即返回结果。有关更多实际示例,请参见以前的博客文章。 使用局部变量 这与在每个作用域中查找变量的速度有关,因为它不只是使用局部变量还是全局变量。实际上,即使在函数的局部变量(最快),类级属性(例如self.name——较慢)和全局(例如,导入的函数)如time.time(最慢)之间,查找速度实际上也有所不同。 你可以通过使用看似不必要的分配来提高性能,如下所示: # Example #1 class FastClass:     def do_stuff(self):         temp = self.value # this speeds up lookup in loop         for i in range(10000):             ... # Do something with `temp` here # Example #2 import random def fast_function():     r = random.random     for i in range(10000):         print(r()) # calling `r()` here, is faster than global random.random() 使用函数 这似乎违反直觉,因为调用函数会将更多的东西放到堆栈上,并从函数返回中产生开销,但这与上一点有关。如果仅将整个代码放在一个文件中而不将其放入函数中,则由于全局变量,它的运行速度会慢得多。因此,你可以通过将整个代码包装在main函数中并调用一次来加速代码,如下所示: def main():     ... # All your previously global code main() 不访问属性 可能会使你的程序变慢的另一件事是点运算符(.),它在获得对象属性时被使用。此运算符使用__getattribute__触发字典查找,这会在代码中产生额外的开销。那么,我们如何才能真正避免(限制)使用它呢? # Slow: import re def slow_func():     for i in range(10000):         re.findall(regex, line) # Slow! # Fast: from re import findall def fast_func():     for i in range(10000):         findall(regex, line) # Faster! 当心字符串 使用模数(%s)或.format()进行循环运行时,字符串操作可能会变得非常慢。我们有什么更好的选择?根据雷蒙德·海廷格(Raymond Hettinger)最近的推特,我们唯一应该使用的是f-string,它是最易读,最简洁且最快的方法。根据该推特,这是你可以使用的方法列表——最快到最慢: f'{s} {t}'  # Fast! s + ' ' + t ' '.join((s, t)) '%s %s' % (s, t) '{} {}'.format(s, t) Template('$s $t').substitute(s=s, t=t) # Slow! 生成器本质上并没有更快,因为它们被允许进行延迟计算,从而节省了内存而不是时间。但是,保存的内存可能会导致你的程序实际运行得更快。这是怎么做到的?如果你有一个很大的数据集,而没有使用生成器(迭代器),那么数据可能会溢出CPU L1缓存,这将大大减慢内存中值的查找速度。 在性能方面,非常重要的一点是CPU可以将正在处理的所有数据尽可能地保存在缓存中。你可以观看Raymond Hettingers的视频,他在其中提到了这些问题。 03结论 优化的首要规则是不要优化。但是,如果确实需要,那么我希望上面这些技巧可以帮助你。但是,在优化代码时要小心,因为它可能最终使你的代码难以阅读,因此难以维护,这可能超过优化的好处。 ...

    2020-12-06 655
  • 最全总结!聊聊 Python 发送邮件的几种方式

    1. 前言 邮件,作为最正式规范的沟通方式,在日常办公过程中经常被用到 我们都知道 Python内置了对 SMTP 的支持,可以发送纯文本、富文本、HTML 等格式的邮件 本文将聊聊利用 Python 发送邮件的 3 种方式 2. 准备 以 126 邮箱为例,在编码之前,我们需要开启 SMTP 服务 然后,手动新增一个授权码 其中,账号、授权码和服务器地址用于连接登录邮箱服务器 3. 方式一:smtplib smtplib是 Python 自带的依赖库,可以直接导入使用首先,通过邮箱账号、授权码、邮箱服务器地址初始化一个 SMTP 实例,然后进行连接 def __init__(self):     # 初始化     self.smtp = smtplib.SMTP()     # 连接邮箱服务器地址     self.smtp.connect('smtp.126.com')     # 加入主题和附件,邮件体     self.email_body = MIMEMultipart('mixed')     # 发件人地址及授权码     self.email_from_username = '**@126.com'     self.email_from_password = '授权码' # 登录 self.smtp.login(self.email_from_username, self.email_from_password) 然后,将收件人列表、邮件标题、邮件正文内容、附件路径及附件文件名加入到上面定义的邮件体中 def generate_email_body(self, email_to_list, email_title, email_content, attchment_path, files):     """     组成邮件体     :param email_to_list:收件人列表     :param email_title:邮件标题     :param email_content:邮件正文内容     :param attchment_path:附件的路径     :param files:附件文件名列表     :return:     """     self.email_body['Subject'] = email_title     self.email_body['From'] = self.email_from_username     self.email_body['To'] = ",".join(email_to_list)     for file in files:         file_path = attchment_path + '/' + file         if os.path.isfile(file_path):             # 构建一个附件对象             att = MIMEText(open(file_path, 'rb').read(), 'base64', 'utf-8')             att["Content-Type"] = 'application/octet-stream'             att.add_header("Content-Disposition", "attachment", filename=("gbk", "", file))             self.email_body.attach(att)     text_plain = MIMEText(email_content, 'plain', 'utf-8')     self.email_body.attach(text_plain) 接着,就可以使用 SMTP 实例对象,将邮件发送出去  # 收件人列表 email_to_list = ['收件人1地址','收件人2地址'] # 发送邮件 # 注意:此处必须同时指定发件人与收件人,否则会当作垃圾邮件处理掉 self.smtp.sendmail(self.email_from_username, email_to_list, self.email_body.as_string()) 邮件发送完毕之后,退出服务即可 def exit(self):     """     退出服务     :return:     """     self.smtp.quit() 4. 方式二:zmail Zmail 项目创建目的是,使邮件处理变得更简单 使用 Zmail 发送接收邮件方便快捷,不需要手动添加服务器地址、端口以及适合的协议,可以轻松创建 MIME 对象和头文件 注意:Zmail 仅支持 Python3,不支持 Python2 首先,安装依赖库 # 安装依赖库 pip3 install zmail 然后,使用邮箱账号、授权码创建一个邮箱服务对象 class ZMailObject(object):     def __init__(self):         # 邮箱账号         self.username = '**@126.com'         # 邮箱授权码         self.authorization_code = '授权码'         # 构建一个邮箱服务对象         self.server = zmail.server(self.username, self.authorization_code) 接着,将邮件主题、邮件内容、包含的附件路径加入到一个字典中,组成邮件主体 # 邮件主体 mail_body = {         'subject': '测试报告',         'content_text': '这是一个测试报告',  # 纯文本或者HTML内容         'attachments': ['./attachments/report.png'], } 最后,将调用send_mail()函数,将邮件发送出去即可 # 收件人 # 可以指定一个人,字符串;也可以是多个人,列表 mail_to = "收件人1" # 发送邮件 self.server.send_mail(mail_to, mail_body) 5. 方式三:yagmail yagmail 只需要几行代码,就能实现发送邮件的功能 相比 zmail,yagmail 实现发送邮件的方式更加简洁优雅 首先,安装依赖库 # 安装依赖库 pip3 install yagmail 然后,通过账号、授权码和服务器地址连接邮箱服务器,返回一个服务对象 import yagmail # 连接服务器 # 用户名、授权码、服务器地址 yag_server = yagmail.SMTP(user='**@126.com', password='授权码', host='smtp.126.com') 接着,通过 send() 函数,将邮件发送出去 # 发送对象列表 email_to = ['**@qq.com', ] email_title = '测试报告' email_content = "这是测试报告的具体内容" # 附件列表 email_attachments = ['./attachments/report.png', ] # 发送邮件 yag_server.send(email_to, email_title, email_content, email_attachments) 邮件发送完毕之后,关闭连接即可 # 关闭连接 yag_server.close() 6. 最后 上面总结了 Python 发送邮件的 3 种方式,实际项目中,更推荐使用后两种方式 我已经将文中全部源码上传到后台,关注公众号后回复「 email 」即可获得全部源码 如果你觉得文章还不错,请大家可以 加入我们的交流群,因为这将是我持续输出更多优质文章的最强动力! ...

    2020-07-14 1338
  • 用python编写自动信息收集脚本(三) -ip收集

    本人只是python初学者,本文只适合初学者观看学习。大佬请绕过(或者指出需要改进的地方)!在日常渗透测试过程中我们都知道,在对目标进行渗透之前都是先要信息收集一波。收集到越多的信息往往渗透过程中越顺利,所以信息收集格外重要。而信息收集往往费时间比较多,所以我们想写一个自动信息收集的脚本,但是代码量太大。本文就先从whois信息开始,代码不好的地方。希望大家提出意见! 本次模块配合之前的用python编写自动信息收集脚本一,二使用 import threading #多线程 import requests import time from lxml import etree import re #正则表达式 import csv import telnetlib #建立tcp链接 实现端口扫描 class xxsj(object):     def __init__(self):         global dk #创建全局变量,后面端口扫描用         self.wz = input("请输入您想查询的网站") #接收网站地址         dk = self.wz         self.a = re.sub(r"www.","",self.wz) #正则表达式,匹配www. 然后删除         self.header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}     def ip(self):         url='https://dns.aizhan.com/' self.wz '/' # url地址         print("----在获取ip地址----")         response = requests.get(url=url, headers=self.header)         selector = etree.HTML(response.content)         title = "IP地址"         global ab #创建全局 ...

    2020-06-20 885
  • 用python编写自动信息收集脚本(二)网站信息搜集

    本人只是python初学者,本文只适合初学者观看学习。大佬请绕过(或者指出需要改进的地方)!在日常渗透测试过程中我们都知道,在对目标进行渗透之前都是先要信息收集一波。收集到越多的信息往往渗透过程中越顺利,所以信息收集格外重要。而信息收集往往费时间比较多,所以我们想写一个自动信息收集的脚本,但是代码量太大。本文就先从whois信息开始,代码不好的地方。希望大家提出意见! 本次模块配合之前的用python编写自动信息收集脚本(一)使用 def xx(self):     url = 'https://www.aizhan.com/seo/' self.wz     response = requests.get(url=url, headers=self.header)     selector = etree.HTML(response.content)     title = selector.xpath('//*[@id="icp"]/li[1]/text()')[0]   #备案号 获取li[1]下的文本     infor = selector.xpath('//*[@id="icp_icp"]/text()')[0]   #备案信息     a = selector.xpath('//*[@id="icp_company"]/text()')[0]   #公司性质     b = selector.xpath('//*[@id="icp_type"]/text()')[0]    #公司名称     c = 1     for i in range(0, 2):     #写两次  将四个变量两次写人csv文件中         if c == 1:             self.write([title, infor])             c = c 1         else:             self.write([b, a]) ...

    2020-06-20 937
  • 用python编写自动信息收集脚本(一)

    本人只是python初学者,本文只适合初学者观看学习。大佬请绕过(或者指出需要改进的地方)! 在日常渗透测试过程中我们都知道,在对目标进行渗透之前都是先要信息收集一波。收集到越多的信息往往渗透过程中越顺利,所以信息收集格外重要。而信息收集往往费时间比较多,所以我们想写一个自动信息收集的脚本,但是代码量太大。本文就先从whois信息开始,代码不好的地方。希望大家提出意见! import requests from lxml import etree import csv class xxsj(object):     def __init__(self):         self.header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}     def whois(self):         wz = input('请输入您想信息收集的网站:')         print("正在whois查询",)         url = 'https://whois.aizhan.com/' wz         response = requests.get(url=url, headers=self.header)         selector = etree.HTML(response.content)         title = selector.xpath('//td[@class="thead"]/text()')         yuming = selector.xpath('//td[2]//text()')         a = len(title)         for i in range(0, a - 1):             title1 = title             yuming1 = yuming             self.write([title1, yuming1])     def write(self,lis):         with open('信息收集.csv', ...

    2020-06-20 1242
  • 不懂代码也能爬取数据?试试这几个工具

    前天,有个同学加我微信来咨询我: “毒蜂,我想抓取近期 5000 条新闻数据,但我是文科生,不会写代码,请问该怎么办?” 有问必答,毒蜂对于这位同学的问题,我给安排上。 先说说获取数据的方式:一是利用现成的工具,我们只需懂得如何使用工具就能获取数据,不需要关心工具是怎么实现。打个比方,假如我们在岸上,要去海上某个小岛,岸边有一艘船,我们第一想法是选择坐船过去,而不会想着自己来造一艘船再过去。 第二种是自己针对场景需求做些定制化工具,这就需要有点编程基础。举个例子,我们还是要到海上某个小岛,同时还要求在 30 分钟内将 1 顿货物送到岛上。 因此,前期只是单纯想获取数据,没有什么其他要求的话,优先选择现有工具。 可能是 Python 近来年很火,加上我们会经常看到别人用 Python 来制作网络爬虫抓取数据。从而有一些同学有这样的误区,想从网络上抓取数据就一定要学 Python,一定要去写代码。 其实不然,毒蜂介绍几个能快速获取网上数据的工具。 1.Microsoft Excel 你没有看错,就是 Office 三剑客之一的 Excel。Excel 是一个强大的工具,能抓取数据就是它的功能之一。我以耳机作为关键字,抓取京东的商品列表。 等待几秒后,Excel 会将页面上所有的文字信息抓取到表格中。这种方式确实能抓取到数据,但也会引入一些我们不需要的数据。如果你有更高的需求,可以选择后面几个工具。 2.火车头采集器 火车头是爬虫界的老品牌了,是目前使用人数最多的互联网数据抓取、处理、分析,挖掘软件。它的优势是采集不限网页,不限内容,同时还是分布式采集,效率会高一些。缺点是对小白用户不是很友好,有一定的知识门槛(了解如网页知识、HTTP 协议等方面知识),还需要花些时间熟悉工具操作。 因为有学习门槛,掌握该工具之后,采集数据上限会很高。有时间和精力的同学可以去折腾折腾。 官网地址:http://www.locoy.com/ 3.八爪鱼采集器 八爪鱼采集器是一款非常适合新手的采集器。它具有简单易用的特点,让你能几分钟中就快手上手。八爪鱼提供一些常见抓取网站的模板,使用模板就能快速抓取数据。如果想抓取没有模板的网站,官网也提供非常详细的图文教程和视频教程。 八爪鱼是基于浏览器内核实现可视化抓取数据,所以存在卡顿、采集数据慢的特点。但这瑕不掩瑜,能基本满足新手在短时间抓取数据的场景,比如翻页查询,Ajax 动态加载数据等。 网站:https://www.bazhuayu.com/ 4.GooSeeker 集搜客 集搜客也是一款容易上手的可视化采集数据工具。同样能抓取动态网页,也支持可以抓取手机网站上的数据,还支持抓取在指数图表上悬浮显示的数据。集搜客是以浏览器插件形式抓取数据。虽然具有前面所述的有点,但缺点也有,无法多线程采集数据,出现浏览器卡顿也在所难免。 网站:https://www.gooseeker.com/ 5.Scrapinghub 如果你想抓取国外的网站数据,可以考虑 Scrapinghub。Scrapinghub 是一个基于Python 的 Scrapy 框架的云爬虫平台。Scrapehub 算是市场上非常复杂和强大的网络抓取平台,提供数据抓取的解决方案商。 地址:https://scrapinghub.com/ 6.WebScraper WebScraper 是一款优秀国外的浏览器插件。同样也是一款适合新手抓取数据的可视化工具。我们通过简单设置一些抓取规则,剩下的就交给浏览器去工作。 地址:https://webscraper.io/ 如果你觉得文章不错的话,分享、收藏、在看是对猴哥的最大支持,是毒蜂持续创作的动力。 ...

    2020-04-12 891
  • 我用Python找到了隔壁蹭网妹子的QQ号

    最近发现晚上有人老是在蹭网,而且严重怀疑是我的美女单身邻居,这可是千载难逢的好机会。于是我用Python轻松找到了它的QQ号,开始了我的桃花之旅......下面给大家介绍一下我是怎么做到的。 1、登入路由器进行分析 蹭网的信息全部都在路由器上,所以我们首先要登录路由器,去查探一下线索。果然登入路由器之后,发现有1台陌生的设备华为P30Pro在线,哈哈女神都是用高端手机,我等屌丝还在苦苦坚守16年的华为mate9。 那么如何才能知道女神的QQ号呢,别急别急啊,且听我慢慢给大家分析。 2、抓流量包进行分析 想办法抓取女神的流量包,路由器定向太麻烦,干脆直接把路由器wifi关了,在电脑上插个外置usb网卡,重新开个同名同密码的wifi,到时候女神的手机就可以自动连上了,我只要抓电脑网卡的流量就OK了。 如下图所示,不一会,这台华为P30pro就不知不觉自动连上我新建的wifi了。 3、神库Scapy抓包分析 用Python的scapy库抓包分析,有同学可能不知道这个库,这个库其实非常有用,尤其在网络分析方面,小编简单介绍一下。 1).scapy库简介 scapy是一个可以让用户发送、侦听和解析并伪装网络报文的Python程序。这些功能可以用于制作侦测、扫描网络的工具。 2).用scapy抓usb网卡上的流量: packets=scapy.sniff(iface=iface_name,prn=pktTCP) 一行代码就搞定了,其中iface_name是网卡的名称,在网卡的属性中可以找到,pktTCP是返回的数据包,它长下图这样: 包含数据链路层、网络层、传输层数据。 3).分析数据包,找到有用信息: 这是最重要的一步,过程不难,但比较繁琐,我就不详细说了,直接把结果说出来吧: 经过多次试验,QQ号(一般是5到10位)一般在这2类字符串中后面,通过正则表达式匹配!另外这2类字符串后面跟的也可能是全0数字,要进行简单的筛选。 部分源码如下: 4).运行程序,等待结果,果然没几分钟就搜索到了。 上面那个是我自己的,下面那个是女神的,果断加了过去。 哈哈哈,果然是她。 ...

    2020-01-20 1008
  • Python 帮你批量生成手机号码

    阅读文本大概需要 8 分钟。 1 目 标 场 景 平时在工作过程中,偶尔会需要大量的 手机号码,去测试一些具体的业务功能,为了保证测试的有效性,手机号码的 真实性 尤为的重要。 那如何按要求 批量生成 一些真实的手机号码呢? 本篇文章的目的是带大家利用 Python 批量生成手机号码。 2 编 写 代 码 要批量生成手机号码,首先需要了解 11 位手机号码的组成规律,即: 手机号码一共有 11 位,以 1 开头 第 2 位的数值是 3、4、5、7、8 中的一个 第 3 位根据第 2 位的数字,对应运营商的生成规律 后 8 位是随机生成的 8 个数字 知道手机号码的组成规律后,接着把数字拼接起来,即可以生成一个手机号码。 def create_a_phone():     # 第二位数字     second = [3, 4, 5, 7, 8][random.randint(0, 4)]     # 第三位数字     third = {3: random.randint(0, 9),              4: [5, 7, 9][random.randint(0, 2)],              5: [i for i in range(10) if i != 4][random.randint(0, 8)],              7: [i for i in range(10) if i not in [4, 9]][random.randint(0, 7)],              8: random.randint(0, 9), }[second]     # 最后八位数字     suffix = random.randint(9999999, 100000000)     # 拼接手机号     return "1{}{}{}".format(second, third, suffix) 由于三大运营商的号段一直在更新变化,上面组成的手机号码也有可能不是一个有效的号码。 为了保证号码的真实性,利用号码去获取 手机号码归属地,如果能获取到归属地,即代表为一个真实有效的号码。 淘宝和百度都提供了查询归属地的 API,可以非常方便的查询号码的归属地。 def judge_phone_ava(phone):     """     判断手机号码是否合理     :param phone:手机号码     :return:     """     resp_content = requests.get('http://mobsec-dianhua.baidu.com/dianhua_api/open/location?tel=%s' % phone).content     txt = json.loads(resp_content)     result = txt.get('response').get(phone)     return result 循环上面的操作,可以生成一些随机的手机号码,正因为生成号码的随机性,使得数据的价值性大打折扣。 如果我需要批量生成指定城市的手机号码,上面的这种方法没法做到。幸运地是,有一个网站(阅读原文)已经实现了这个功能,我们只需要用 Python 模拟请求即可。 选择手机号码归属地、包含号段、数量,就能快速生成我们想要的手机号码,按 F12 可以查看网络请求方式及参数。 请求参数中的区域代码对应选择的省+市区,这部分数据利用 JS 加载到页面中了。 我们只需要解析网页源代码,利用正则表达式查找对应的字符串,解析出 区域 ID 和城市名称。 def get_all_citys():     """     获取所有的城市数据     :return:     """     headers = {         'authority': 'uutool.cn',         'pragma': 'no-cache',         'cache-control': 'no-cache',         'upgrade-insecure-requests': '1',         'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36',         'sec-fetch-user': '?1',         'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',         'sec-fetch-site': 'none',         'sec-fetch-mode': 'navigate',         'accept-encoding': 'gzip, deflate, br',         'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',         'cookie': 'UM_distinctid=16f759fe6bd24b-0322efd0d180d8-1d376b5b-1aeaa0-16f759fe6beb69; CNZZDATA1275106188=191793625-1578225029-https%253A%252F%252Fwww.google.com%252F%7C1578316721',     }     resp = requests.get('https://uutool.cn/phone-generate/', headers=headers).text     re_rule = r'areaArr:(.+?)segmentArr:'     # 匹配换行符     result_data = re.findall(re_rule, resp, re.S)[0].strip()[:-1]     result = json.loads(result_data)     # 获取所有的省份     provices = result.keys()     # 所有的城市     citys = {}     for provice in provices:         current_citys = result.get(provice)         # citys.extend(current_citys)         for item in current_citys:             citys[item.get('name')] = item.get('id')     return citys 拿到城市名称和区域 ID 的关系数据后,模拟网络请求,即可以批量生成目标城市的手机号码。 citys = get_all_citys() city_name = input('请输入手机归属地:') if city_name not in citys.keys():      city_name = '北京' # 获取城市id city_id = citys.get(city_name) phones = generate_phones(num, city_id) # pass 3 结 果 结 论 通过上面的操作,就能按照自己的需求,批量生成一些真实有效的手机号码。 接下来,可以结合自动化操作,可以使得我们生成的数据价值最大化。 如果你觉得文章还不错,请大家分享下。你的肯定是我最大的鼓励和支持。 ...

    2020-01-18 1247
  • 我背着女朋友,用 Python 偷偷抓取了她的行踪

    阅读文本大概需要 5 分钟。 1 目 标 场 景 有时候女朋友一个人在外面玩耍,问她在哪个地方,就是不告诉我。但是,你又很想知道女朋友的「位置」,这该如何是好? 其实你可以这样套路女朋友,假装自己在家很无聊,可以帮她修图,让她微信发原图给你,拿到「微信原图」后,你就可以利用 Python 快速获取到女友的具体位置了。 2 准 备 工 作 首先,在虚拟环境中安装识别图片元数据的库。 pip3 install exifread 然后,进入高德开放平台,申请一个 Web 服务的应用,获取到一个 「Key」用于逆地理编码 API。 3 编  写  脚  本 整个操作分为 3 步骤,分别是获取图片的经度和纬度、对经度和纬度进行数据矫正、调用高德逆地理编码 API 获取具体位置。 第 1 步,获取图片的「经度和纬度」。 使用 exifread 库可以直接读取图片文件,获取到图片的元数据,包含经度、纬度、南北纬方向、东西经方向和拍摄时间。 # 使用 exifread 获取图片的元数据 img_exif = exifread.process_file(open(self.img_path, 'rb')) # 能够读取到属性 if img_exif:      # 纬度数      latitude_gps = img_exif['GPS GPSLatitude']      # N,S 南北纬方向      latitude_direction = img_exif['GPS GPSLatitudeRef']      # 经度数      longitude_gps = img_exif['GPS GPSLongitude']      # E,W 东西经方向      longitude_direction = img_exif['GPS GPSLongitudeRef']      # 拍摄时间      take_time = img_exif['EXIF DateTimeOriginal'] 如果元数据存在,然后判断拍摄时间是否合理。如果拍摄时间不在今天,那只能很遗憾地通知你,你的女朋友在向你撒谎「撒谎」。 def judge_time_met(self, take_time):     """     判断拍摄时间是否是在今天     :param take_time:     :return:     """     # 拍摄时间     format_time = str(take_time).split(" ")[0].replace(":", "-")     # 当天日期     today = str(datetime.date.today())     if format_time == today:         return True     else:         return False if is_lie:         print('很遗憾的通知你,你的女朋友在撒谎!!!')         return 如果女友没有撒谎,那么可以进行第 2 步的操作。 因为通过 GPS 获取的经度、纬度和高德地图的坐标存在一定的误差,这里需要把坐标转换为「火星坐标系」。 x_pi = 3.14159265358979324 * 3000.0 / 180.0 pi = 3.1415926535897932384626  # π a = 6378245.0  # 长半轴 ee = 0.00669342162296594323  # 扁率 def wgs84togcj02(lng, lat):     """     WGS84转GCJ02(火星坐标系)     :param lng:WGS84坐标系的经度     :param lat:WGS84坐标系的纬度     :return:     """     if out_of_china(lng, lat):  # 判断是否在国内         return lng, lat     dlat = transformlat(lng - 105.0, lat - 35.0)     dlng = transformlng(lng - 105.0, lat - 35.0)     radlat = lat / 180.0 * pi     magic = math.sin(radlat)     magic = 1 - ee * magic * magic     sqrtmagic = math.sqrt(magic)     dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)     dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)     mglat = lat + dlat     mglng = lng + dlng     return [mglng, mglat] 另外需要注意的是,接口中经度、纬度参数只能识别小数点后 6 位,需要对经纬度中的度、分、秒做一定的数据处理,然后再进行四舍五入。 def __format_lati_long_data(self, data):     """     对经度和纬度数据做处理,保留6位小数     :param data: 原始经度和纬度值     :return:     """     # 删除左右括号和空格     data_list_tmp = str(data).replace('[', '').replace(']', '').split(',')     data_list = [data.strip() for data in data_list_tmp]     # 替换秒的值     data_tmp = data_list[-1].split('/')     # 秒的值     data_sec = int(data_tmp[0]) / int(data_tmp[1]) / 3600     # 替换分的值     data_tmp = data_list[-2]     # 分的值     data_minute = int(data_tmp) / 60     # 度的值     data_degree = int(data_list[0])     # 由于高德API只能识别到小数点后的6位     # 需要转换为浮点数,并保留为6位小数     result = "%.6f" % (data_degree + data_minute + data_sec)     return float(result) 第 3 步,调用高德的反地理编码 API,传入申请的应用 Key,就能拿到女朋友的详细地址。 def __get_address(self, location):     """     根据坐标得到详细地址     :param location: 经纬度值     :return:     """     resp = requests.get(self.url_get_position.format(self.api_key, location))     location_data = json.loads(resp.text)     address = location_data.get('regeocode').get('formatted_address')     return address 4 结 果 结 论 确保图片是原图的基础上,可以快速帮你判断女朋友是否在撒谎;如果女朋友没有撒谎,就返回女朋友具体的位置。 如果你觉得文章还不错,请大家分享下。你的肯定是我最大的鼓励和支持。 ...

    2020-01-18 1044
  • Python爬虫之-爬取妹子图片

    #coding=utf-8 import requests from bs4 import BeautifulSoup import os all_url = ‘http://www.mzitu.com’ #http请求头 Hostreferer = { ‘User-Agent’:’Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)’, ‘Referer’:’http://www.mzitu.com’ } Picreferer = { ‘User-Agent’:’Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)’, ‘Referer’:’http://i.meizitu.net’ } #此请求头破解盗链 start_html = requests.get(all_url,headers = Hostreferer) #保存地址 path = ‘G:\python\妹子\liang’ #找寻最大页数 soup = BeautifulSoup(start_html.text,”html.parser”) page = soup.find_all(‘a’,class_=’page-numbers’) max_page = page[-2].text same_url = ‘http://www.mzitu.com/page/’ for n in range(1,int(max_page)+1): ul = same_url+str(n) start_html = requests.get(ul, headers = Hostreferer) soup = BeautifulSoup(start_html.text,”html.parser”) all_a = soup.find(‘div’,class_=’postlist’).find_all(‘a’,target=’_blank’) for a in all_a: title = a.get_text() #提取文本 if(title != ”): print(“准备扒取:”+title) #win不能创建带?的目录 if(os.path.exists(path+title.strip().replace(‘?’,”))): #print(‘目录已存在’) flag=1 else: os.makedirs(path+title.strip().replace(‘?’,”)) flag=0 os.chdir(path + title.strip().replace(‘?’,”)) href = a[‘href’] html = requests.get(href,headers = Hostreferer) mess = BeautifulSoup(html.text,”html.parser”) pic_max = mess.find_all(‘span’) pic_max = pic_max[10].text #最大页数 if(flag == 1 and len(os.listdir(path+title.strip().replace(‘?’,”))) >= int(pic_max)): print(‘已经保存完毕,跳过’) continue for num in range(1,int(pic_max)+1): pic = href+’/’+str(num) html = requests.get(pic,headers = Hostreferer) mess = BeautifulSoup(html.text,”html.parser”) pic_url = mess.find(‘img’,alt = title) print(pic_url[‘src’]) #exit(0) html = requests.get(pic_url[‘src’],headers = Picreferer) file_name = pic_url[‘src’].split(r’/’)[-1] f = open(file_name,’wb’) f.write(html.content) f.close() print(‘完成’) print(‘第’,n,’页完成’) ...

    2019-06-30 1590

联系我们

在线咨询:点击这里给我发消息

QQ交流群:KirinBlog

工作日:8:00-23:00,节假日休息

扫码关注