XieJava's blog

记录最好的自己


  • 首页

  • 分类

  • 标签

  • 归档

  • 关于

pandas数据加载(csv、excel、json、mysql、webAPI)

发表于 2022-01-22 | 更新于: 2025-08-10 | 分类于 技术 , 开发 | | 阅读次数:
字数统计: 1.4k | 阅读时长 ≈ 5

pandas
pandas 是基于NumPy 的一种工具,该工具是为解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。Pandas的名称来自于面板数据(panel data)和python数据分析(data analysis)。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。它是使Python成为强大而高效的数据分析环境的重要因素之一。

数据的输入是数据分析的第一步,如果不能将数据快速方便的导入导出python,那么pandas不可能成为强大而高效的数据分析环境,本文重点介绍pandas的数据输入加载。pandas的数据输入可以划分为几个大类:读取文本文件和其他更高效的磁盘存储格式,加载数据库中的数据,利用Web API获取网络资源。
pandas数据处理
pandas的IO工具支持非常多的数据输入输出方式。包括csv、json、Excel、数据库等。

Format Type Data Description Reader Writer
text CSV read_csv to_csv
text JSON read_json to_json
text HTML read_html to_html
text Local clipboard read_clipboard to_clipboard
binary MS Excel read_excel to_excel
binary OpenDocument read_excel
binary HDF5 Format read_hdf to_hdf
binary Feather Format read_feather to_feather
binary Parquet Format read_parquet to_parquet
binary Msgpack read_msgpack to_msgpack
binary Stata read_stata to_stata
binary SAS read_sas
binary Python Pickle Format read_pickle to_pickle
SQL SQL read_sql to_sql
SQL Google Big Query read_gbq to_gbq

本文通过几个实例,介绍几种常用的数据加载方式,包括从csv文件、excel文件、关系型数据库如mysql、API接口加载json数据,来初步体验一下pandas加载数据的便捷性。

见上表pandas 提供了多种数据源读取数据的方法:
read_csv() 用于读取文本文件
read_json() 用于读取 json 文件
read_sql_query() 读取 sql 语句查询的表记录

一、读取CSV文件

CSV 又称逗号分隔值文件,是一种简单的文件格式,以特定的结构来排列表格数据。 CSV 文件能够以纯文本形式存储表格数据,比如电子表格、数据库文件,并具有数据交换的通用格式。CSV 文件会在 Excel 文件中被打开,其行和列都定义了标准的数据格式。
将 CSV 中的数据转换为 DataFrame 对象是非常便捷的。和一般文件读写不一样,它不需要你做打开文件、读取文件、关闭文件等操作。相反,只需要一行代码就可以完成上述所有步骤,并将数据存储在 DataFrame 中。
pandas通过read_csv()从 CSV 文件中读取数据,并创建 DataFrame 对象。
下面通过一个实例来说明。一个用于测试的员工数据集csv的数据如下,文件为staff.csv。

1
2
3
4
5
6
7
8
9
10
11
"staff_id","staff_name","staff_age","staff_gender","staff_salary","staff_depatment_id"
"1","陈一","30","男","7000","1"
"2","周二","31","男","12000","2"
"3","张三","30","女","13000","3"
"4","李四","29","女","15000","1"
"5","王五","29","男","9000","2"
"6","赵六","35","男","8600","1"
"7","钱七","36","女","9700","3"
"8","孙八","40","女","10000","3"
"9","何九","40","男","11000","1"
"10","顾十","37","女","15000","2"

代码如下:

1
2
3
import pandas as pd
df = pd.read_csv('C:\\Users\\xiejava\\Desktop\\staff.csv')
df

输出:
通过csv加载

二、读取EXCEL文件

Excel 是由微软公司开发的办公软件之一,它在日常工作中得到了广泛的应用。在数据量较少的情况下,Excel 对于数据的处理、分析、可视化有其独特的优势,因此可以显著提升您的工作效率。但是,当数据量非常大时,Excel 的劣势就暴露出来了,比如,操作重复、数据分析难等问题。Pandas 提供了操作 Excel 文件的函数,可以很方便地处理 Excel 表格。
pandas提供了 read_excel() 方法,从 Excel文件中读取数据,并创建 DataFrame 对象。
staff数据集excel文件staff.xlsx如下图:
staff.xlsx
代码如下:

1
2
3
import pandas as pd
df = pd.read_excel('C:\\Users\\xiejava\\Desktop\\staff.xlsx')
df

输出:
通过Excel加载数据

三、读取MySQL数据库表

在许多应用中,数据很少取自文本文件,因为这种方式存储数据量有限且比较低效。最常见的是基于SQL的关系型数据库如MySQL、MS-SQL、PostgreSQL等。pandas将关系型数据库加载到DataFrame的过程很简单,通过read_sql_query()方法就可以快速的将数据加载。
同样是staff的数据集,在mysql中的表结构如下:

1
2
3
4
5
6
7
8
CREATE TABLE `staff` (
`staff_id` int(11) DEFAULT NULL,
`staff_name` varchar(64) DEFAULT NULL,
`staff_age` int(2) DEFAULT NULL COMMENT '年龄',
`staff_gender` varchar(2) DEFAULT NULL COMMENT '性别',
`staff_salary` double DEFAULT NULL COMMENT '薪水',
`staff_depatment_id` int(2) DEFAULT NULL COMMENT '部门ID'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

数据如下:
staff数据集MySQL记录
代码如下:

1
2
3
4
5
6
import pandas as pd
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://root:yourpassword@localhost:3306/pandastest')
sql_query_staff = 'select * from staff;'
df_staff = pd.read_sql_query(sql_query_staff, engine)
df_staff

输出:
加载mysql数据

四、读取Web API的数据

除了本地文件和数据库外,许多网站和web应用都有一些通过JSON或其他格式提供数据的公共API。可以通过Python的requests包来访问这些API获得相应的数据,经过解析处理后加载到pandas的DataFrame中。
为了演示方便,本文通过Flask做了一个staff数据集的API,效果如下:
staff数据集API
通过requests包来访问API,通过json包来解析json,然后加载到pandas的DataFrame中。
代码如下:

1
2
3
4
5
6
7
8
import requests
import json
import pandas as pd
url='http://127.0.0.1:5000/getstaff'
resp=requests.get(url)
data=json.loads(resp.text)
staff=pd.DataFrame(data)
staff

输出:
加载WEBAPI数据

至此,通过staff测试数据集介绍了pandas的常用多种类型数据源的加载,包括csv、excel、mysql、web API。可以看出pandas对于数据加载非常的方便高效。

全部数据集及源代码:https://github.com/xiejava1018/pandastest.git


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


“fullbug”微信公众号

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

Python实现读取Word表格计算汇总写入Excel

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

快过年了,又到了公司年底评级的时候了。今年的评级和往常一下,每个人都要填写公司的民主评议表,给各个同事进行评价打分,然后部门收集起来根据收集上来的评价表进行汇总统计。想想要收集几十号人的评价表,并根据每个人的评价表又要填到Excel中进行汇总计算统计给出每个人的评价,就头大。虽然不是个什么难事,但是是个无脑的细致活。几十个人的评价也得要花大半天的时间来弄,而且搞多了还容易搞错。如是就想起干脆用Python写个小程序自动来处理这些脏活累活,评级年年都要评,每年都可以用。

要做的事情就是读放到某个文件夹中的word文档中的评价表格,根据表格内容进行处理,然后汇总所有的表格数据,根据计算规则,算出每个人的评分,在根据评分计算每个人的评价。汇总后写入Excel中。
处理Word解析、汇总、统计写入Excel

不可否认用Python来实现这样的事情真的是太方便了,人生苦短我用Python。
我是用的python的docx包来处理word,用pandas来处理数据并写入excel

一、首先导入包

1
2
pip install docx
pip install pandas

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

1
pip install openpyxl

二、读评价表所在的目录文件

通过python的os包,列出文件夹里面的文件,识别出.docx的文件

1
2
3
4
files=os.listdir(filepah)
for file in files:
if file.find('.docx')>0:
docfilepah=filepah+file

三、读word文件,处理word中的表格数据

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
data=[]
#读word的docx评议表文件,并读取word中的表格数据
def procdoc(docfilepath):
document=Document(docfilepath)
tables=document.tables
table=tables[0]
for i in range(1,len(table.rows)):
id=int(table.cell(i,0).text)
name=table.cell(i,1).text
excellent=0
if table.cell(i,2).text!='' and table.cell(i,2).text is not None:
excellent=1
competent = 0
if table.cell(i, 3).text!='' and table.cell(i, 3).text is not None:
competent=1
basicacompetent=0
if table.cell(i, 4).text!='' and table.cell(i, 4).text is not None:
basicacompetent=1
notcompetent = 0
if table.cell(i, 5).text!='' and table.cell(i, 5).text is not None:
notcompetent=1
dontunderstand =0
if table.cell(i, 6).text!='' and table.cell(i, 6).text is not None:
dontunderstand=1
appraisedata=[id,name,excellent,competent,basicacompetent,notcompetent,dontunderstand]
data.append(appraisedata)

四、统计计算

通过pandas直接对数据进行统计计算,避免了传统的循环计算。

1
2
3
4
5
df = pd.DataFrame(data,columns=['序号','姓名','优秀','称职','基本称职','不称职','不了解'])
df=df.groupby(['序号','姓名']).sum() #汇总每个人每一项的评分
df['票数'] = df.apply(lambda x: x.sum(), axis=1) #统计票数
df['计分'] = (df['优秀']*95+df['称职']*85+df['基本称职']*75+df['不称职']*65+df['不了解']*0)/len(df)#根据规则计分
df['评价']=df['计分'].map(getscore) #根据规则评价评级

计分方法:民主评议得分=Σ各等级票数*等级计分分数/总票数,其中“优秀”计95分,“称职”计85分,“基本称职”计75分,“不称职”计65分,“不了解”不计分。

1
2
3
4
5
6
7
8
9
10
11
#根据评分规则计算评级
def getscore(x):
if x>=95:
score='优秀'
elif x>=80 and x<95:
score='称职'
elif x>=75 and x<80:
score='基本称职'
elif x<75:
score='不称职'
return score

五、将统计计算结果写入汇总Excel

通过pandas直接可以将dataframe写入到Excel文件

1
2
3
4
5
6
#将汇总计算好的数据写入Excel
def write2excle(exclefile,dataframe):
writer = pd.ExcelWriter(exclefile)
dataframe.to_excel(writer)
writer.save()
print('输出成功')

完整代码

Python不到八十行代码,实现读Word->处理表格数据->汇总计算数据->写Excel。
完整的代码如下:

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
import os
import pandas as pd
from docx import Document

data=[]
#读word的docx评议表文件,并读取word中的表格数据
def procdoc(docfilepath):
document=Document(docfilepath)
tables=document.tables
table=tables[0]
for i in range(1,len(table.rows)):
id=int(table.cell(i,0).text)
name=table.cell(i,1).text
excellent=0
if table.cell(i,2).text!='' and table.cell(i,2).text is not None:
excellent=1
competent = 0
if table.cell(i, 3).text!='' and table.cell(i, 3).text is not None:
competent=1
basicacompetent=0
if table.cell(i, 4).text!='' and table.cell(i, 4).text is not None:
basicacompetent=1
notcompetent = 0
if table.cell(i, 5).text!='' and table.cell(i, 5).text is not None:
notcompetent=1
dontunderstand =0
if table.cell(i, 6).text!='' and table.cell(i, 6).text is not None:
dontunderstand=1
appraisedata=[id,name,excellent,competent,basicacompetent,notcompetent,dontunderstand]
data.append(appraisedata)

#读取评议表的目录,并处理目录中的docx文件,根据评议表计算评分,写入汇总表。
def readfile(filepah):
files=os.listdir(filepah)
for file in files:
if file.find('.docx')>0:
docfilepah=filepah+file
procdoc(docfilepah)
df = pd.DataFrame(data,columns=['序号','姓名','优秀','称职','基本称职','不称职','不了解'])
print(df)
df=df.groupby(['序号','姓名']).sum()
df['票数'] = df.apply(lambda x: x.sum(), axis=1)
df['计分'] = (df['优秀']*95+df['称职']*85+df['基本称职']*75+df['不称职']*65+df['不了解']*0)/len(df)
df['评价']=df['计分'].map(getscore)
print(df)
write2excle('民主评议\\民主评议表汇总.xlsx',df)

#根据评分规则计算评级
def getscore(x):
if x>=95:
score='优秀'
elif x>=80 and x<95:
score='称职'
elif x>=75 and x<80:
score='基本称职'
elif x<75:
score='不称职'
return score

#将汇总计算好的数据写入Excel
def write2excle(exclefile,dataframe):
writer = pd.ExcelWriter(exclefile)
dataframe.to_excel(writer)
writer.save()
print('输出成功')

if __name__ == '__main__':
readfile('民主评议\\')

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

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


“fullbug”微信公众号

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

网络安全之恶意代码

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

恶意代码是一种有害的计算机代码或 web 脚本,其设计目的是创建系统漏洞,并借以造成后门、安全隐患、信息和数据盗窃、以及其他对文件和计算机系统的潜在破坏。恶意代码不仅使企业和用户蒙受了巨大的经济损失,而且使国家的安全面临着严重威胁。1991年的海湾战争是美国第一次公开在实战中使用恶意代码攻击技术取得重大军事利益,从此恶意代码攻击成为信息战、网络战最重要的入侵手段之一。恶意代码问题无论从政治上、经济上、还是军事上,都成为信息安全面临的首要问题。让我们一起来认识一下恶意代码。

一、什么是恶意代码

恶意代码(Unwanted Code)是指故意编制或设置的、对网络或系统会产生威胁或潜在威胁的计算机代码。最常见的恶意代码有计算机病毒(简称病毒)、特洛伊木马(简称木马)、计算机蠕虫(简称蠕虫)、后门、逻辑炸弹等。

二、恶意代码的分类

1、恶意代码分类

恶意代码的分类标准主要是代码的独立性和自我复制性,独立的恶意代码是指具备一个完整程序所应该具有的全部功能功能,能够独立传播、运行的恶意代码,这样的恶意代码不需要寄宿在另一个程序中。非独立恶意代码只是一段代码,必须嵌入某个完整的程序中,作为该程序的一个组成部分进行传播和运行。对于非独立恶意代码,自我复制过程就是将自身嵌入宿主程序的过程,这个过程也称为感染宿主程序的过程。对于独立恶意代码,自我复制过程就是将自身传播给其他系统的过程。不具有自我复制能力的恶意代码必须借助其他媒介进行传播。

分类:

类别 实例
具有自我复制能力的依附性恶意代码 主要代表是病毒
具有自我复制能力的独立性恶意代码 主要代表是蠕虫
不具有自我复制能力的依附性恶意代码 主要代表是后门
不具有自我复制能力的独立性恶意代码 主要代表是木马

2、不同恶意代码的区别

病毒侧重于破坏系统和程序的能力

木马侧重于窃取敏感信息的能力

蠕虫侧重于网络中的自我复制能力和自我传染能力

病毒 木马 蠕虫
存在形式 寄生 独立文件 独立文件
传染途径 通过宿主程序运行 植入目标主机 系统漏洞
传染速度 慢 最慢 快
攻击目标 本地文件 文件、网络主机 存在漏洞的网络程序
触发机制 攻击者指定条件 自启动 自动攻击有漏洞的程序
防范方法 从宿主文件中清除 清除启动项和木马服务程序 更新安全补丁
对抗主体 用户,反病毒软件 用户、管理员、反病毒软件 应用程序供应商、用户和管理员

三、恶意代码基本技术

1、隐蔽技术

(1)本地隐藏

防止本地系统管理人员觉察而采取的隐蔽手段。

  • 文件隐蔽:将恶意代码的文件命名为与系统的合法程序文件名相似的名称,或者干脆取而代之,或者将恶意代码文件附加到合法程序文件中。
  • 进程隐蔽:附着或替换系统进程,使恶意代码以合法服务的身份运行,从而隐蔽恶意代码。还可以通过修改进程列表程序,修改命令行参数使恶意代码进程的信息无法查询。也可以借助RootKit 技术实现进程隐蔽。
  • 网络连接隐蔽:借用现有服务的端口实现网络连接隐蔽,如使用80端口,攻击者在自己的数据包设置特殊标识,通过标识识别连接信息,未标识的WWW 服务网络包仍转交给原服务程序处理。
  • 编译器隐蔽:由编译器在对程序代码进行编译时植入恶意代码,从而实现恶意代码在用户程序中的隐藏和原始分发攻击。恶意代码的植入者是编译器开发人员。
  • RootKit隐蔽:利用适当的Rootkit工具,可以很好的隐蔽自身或指定的文件、进程和网络连接等,很难被管理员发现。

    (2)网络隐藏

    网络隐藏主要是指通信内容和传输通道的隐藏。
  • 通信内容隐蔽:使用加密算法对所传输的内容进行加密能够隐蔽通信内容。
  • 传输通道隐藏:利用隐蔽通道技术,实现对传输通道的隐蔽。(隐蔽通道(Covert Channel)是一个不受安全机制控制的、利用共享资源作为通信通路的信息流。包括有:存储隐蔽通道和时间隐蔽通道。)

2、生存技术

恶意代码的生存技术主要包括四种类型:

  • 反跟踪技术:通过提高恶意代码分析难度,减少被发现的可能性
  • 加密技术:利用加密技术,提高恶意代码自身保护能力
    模糊变换技术:利用模糊变换技术,恶意代码可以躲避基于特征码的恶意代码检测系统,提高生存能力
  • 自动生产技术:利用自动生成技术,在已有的恶意代码的基础上自动生成特征码不断变化的新的恶意代码,从而躲避基于特征码的恶意代码检测。

3、攻击技术

  • 进程注入技术:恶意代码程序将自身嵌入到操作系统和网络系统的服务程序中,不但实现了自身的隐藏,而且还能随着服务的加载而启动。
  • 三线程技术:恶意代码进程同时开启三个线程,其中一个为主线程,负责远程控制的工作。另外两个辅助线程分别是监视和守护线程。一旦发现主线程被删除,则立即设法恢复。
  • 端口复用技术:重复利用系统或网络服务打开的端口(如80端口),可以欺骗防火墙,具有很强的欺骗性。
  • 超级管理技术:恶意代码采用超级管理技术对反恶意代码软件系统进行攻击,使其无法正常运行。
  • 端口反向连接技术:指使恶意代码的服务端(被控制端)主动连接客户端(控制端)的技术。
  • 缓冲区溢出技术:恶意代码利用系统和网络服务的安全漏洞植入并且执行攻击代码,造成缓冲区溢出,从而获得被攻击主机的控制权。

三、恶意代码传播方式及防范手段

1、传播方式

传播途径

  • 利用操作系统和应用软件的漏洞进行传播
  • 通过网站传播
    在网页上挂载恶意代码
    如:主机流览该网页时,恶意代码会自动下载到主机执行。
    将恶意代码与正常应用软件捆绑
    如:主机下载正常软件运行时,恶意代码也随之自动运行。
  • 利用移动媒介传播
    如:主机访问U盘和硬盘时,恶意代码可以自动执行。
  • 利用用户之间的信任关系传播
    如:冒充用户发送虚假链接、图片、邮件等。

总的来说,恶意代码的传播是因为用户的软件出现了漏洞、操作不慎或者是两者的结合造成。

(1)病毒。病毒具备有自我复制能力,一般嵌入主机的程序中。当被感染文件执行操作,如,用户打开一个可执行文件时,病毒就会自我繁殖。病毒一般都具有破坏性。
(2)木马。这种程序从表面上看没有危害,但实际上却隐含着恶意的意图和破坏的作用。一些木马程序会通过覆盖系统中已经存在的文件的方式存在于系统之中;另外有的还会以软件的形式出现,因为它一般是以一个正常的应用程序身份在系统中运行的,所以这种程序通常不容易被发现。
(3)蠕虫。蠕虫是一种可以自我复制的完全独立的程序,它的传播不需要借助被感染主机中的程序和用户的操作,而是通过系统存在的漏洞和设置的不安全性来进行入侵,如通过共享的设置来侵入。蠕虫可以自动创建与它的功能完全相同的副本,并能在无人干涉的情况下自动运行,大量地复制占用计算机的空间,使计算机的运行缓慢甚至瘫痪。

2、攻击机制

恶意代码的行为表现各异,破坏程度千差万别,但基本作用机制大体相同,其整个作用过程分为6个部分。
(1)侵入系统。侵入系统是而已代码实现其恶意目的的必要条件。恶意代码入侵的途径很多,包括前面传播方式的各种途径。如:从互联网下载的程序本身就可能含有而已代码;接收已感染恶意代码的电子邮件;从光盘或U盘往系统上安装软件;黑客或者攻击者故意将恶意代码植入系统等。
(2)维持或提升权限。恶意代码的传播与破坏必须盗用用户或者进程的合法权限才能完成。
(3)隐蔽策略。为了不让系统发现恶意代码已经侵入系统,恶意代码可能会改名、删除源文件或者修改系统的安全策略来隐藏自己。
(4)潜伏。恶意代码侵入系统后,等待一定的条件,并具有足够的权限时,就发作并进行破坏活动。
(5)破坏。恶意代码本质具有破坏性,其目的是造成信息丢失,泄密,破坏系统完整性等。
(6)重复(1)至(5)对新的目标实施攻击过程。
恶意代码的攻击模型

3、防范手段

通用恶意代码检测技术包括静态和动态检测技术:

  • 基于特征的扫描技术
    建立恶意代码的特征文件,在扫描时根据特征进行匹配查找

  • 校验和法
    对需要监控的文件生成校验,周期性的生成新校验和并与原始值比较

  • 沙箱技术
    根据程序需要的资源和拥有的权限建立运行沙箱,可以安全地检测和分析程序行为

  • 基于蜜罐的检测技术
    将主机伪装为运行着脆弱的服务或系统,同时安装强大的监测系统。

其中基于特征的扫描技术和校验和法是静态检测技术,沙箱技术和基于蜜罐的检测技术属于动态检测技术。

四、常见恶意代码

常见的恶意代码

参考文献:
《网络攻防技术与实战 深入理解信息安全防护体系》 郭帆
《恶意代码及其防御》知乎 Drifter
《恶意代码》MBA智库百科


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


“fullbug”微信公众号

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

网络安全之暴露面、攻击面、脆弱性

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

暴露面
暴露在攻击者视线范围内,可以被利用进行入侵的系统、设备、信息等,都属于暴露面。虽然大多数企业都认识到暴露面的风险所在,并想方设法来减少暴露面;但不幸的是,并非所有暴露面都是显而易见的,大量的暴露面都潜藏在不容易被发现的暗处,很容易因为资产排查不彻底、人员疏漏等问题被忽略。互联网暴露面资产直接面向外部攻击者的威胁。相对于企业内部资产,所面临的安全风险更高。

攻击面
攻击面:是一个给定的计算机或网络系统,可以被黑客访问和利用的漏洞总和。
攻击面包含:
操作系统、中间件、应用程序、承载网络中存在的软件漏洞;
系统和软件中的错误配置与安全控制缺失;
违反安全制度和合规要求的网络配置;
过度宽松的访问控制规则;

减少攻击面的基本策略是减少运行中的软件总量,减少非信任用户可使用的入口点,以及消除用户很少使用的服务。改进信息安全的方法之一就是减少系统与软件的攻击表面。因为关闭不必要的功能,可以避免它们带来的安全风险。减少未授权操作者可调用的代码有助避免安全事故。虽然减少攻击表面有助于防止安全事故,但它不能减少一旦攻击者发现漏洞后可能造成的损害程度。

攻击面从外部攻击视角来审视企业网络资产可能存在的攻击面及脆弱性,如开放端口是否做映射、网络边界是否做隔离、人员行为是否被明确约束等。

脆弱性
脆弱性也可称为弱点或漏洞,是资产或资产组中存在的可能被威胁利用造成损害的薄弱环节。脆弱性一旦被威胁成功利用就可能对资产造成损害。脆弱性可能存在于物理环境、组织、过程、人员、管理、配置、硬件、软件和信息等各个方面。脆弱性是网络系统中可能被利用并造成危害的弱点。

三无七边系统
三无:指具有系统特征且存在”无人管理、无人使用、无人防护”情况的业务/网站/系统/平台。
七边:指测试系统、试验平台、退网未离网系统、工程已上线加载业务但未正式交维系统、与合作伙伴共同运营的业务或系统、责任交接不清的系统、处于衰退期的系统。
三无七边系统是往往是最容易被外部攻破和利用的,所以需要加以重视。但是”三无七边”往往是最不容易发现和忽视的。
“三无七边”系统网络安全管控工作应贯穿规划、设计、建设、入网运行、维护及下线退网整个生命周期。

暴露面不一定存在漏洞也不一定是攻击面,但是因为暴露在攻击者视线范围内,直面外部攻击者的威胁,安全风险高。
攻击面我的理解是既可以被黑客访问又存在漏洞,也就是既是暴露面又有脆弱性,安全风险非常高。
攻击面是从外部攻击的视角来审视可能存在的风险,暴露面和脆弱性从内部管理的视角来审视安全风险。
三无七边系统往往是安全管理人员所忽视的有可能存在暴露面和攻击面而又没有在安全管控范围内的系统,安全风险非常非常高。


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


“fullbug”微信公众号

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

不想学鼓的产品经理不是一个好的程序员

发表于 2021-12-29 | 更新于: 2025-08-10 | 分类于 人生 | | 阅读次数:
字数统计: 697 | 阅读时长 ≈ 2

架子鼓

架子鼓

一直以来都想学一门乐器。苦于没有任何才艺,不管是学校搞活动还是公司的团拜活动都是躲得远远的。从小就很羡慕那种多才多艺的人,不管什么时候都能成为众人的焦点,在要表演的时候可以自信的拿得出手表现一番。也非常羡慕那种自娱自乐的享受自我放松的自由演奏,感觉会乐器的人总是那么的快乐和陶醉。

公司搬到岳麓山大学科技城就在中南大学后湖国际艺术园。一天晚上和同事散步经过一家现代音乐体验店,里面传来乐队演奏的声音,于是驻足前往。里面一群快乐的人,正在激情洋溢的排练着享受着。我们都被触动了,这种自由、快乐、充满激情的感觉真好!想着一天到晚围绕着产品、项目、代码、缺陷,被工作和生活的压力摧残着的我们什么时候才会有这样的状态啊?所以合计了一下,我们也来报个班来学乐器。我一直想学架子鼓,所以决定报个学架子鼓的班。

试听课,老师是一位胖胖的90后小女孩,问了我一个灵魂拷问的问题。你这年纪不小了为什么想起要来学架子鼓?我想了半天,说我就是喜欢敲鼓啊,一直一来就喜欢节奏感比较强的声音,听音乐也是喜欢听节奏感强的歌曲,听到重低音的鼓声敲在心里“咚”、“咚”、“咚”的感觉很踏实。而且敲鼓沉浸在音乐里敲起来帅气。不管怎么样,虽然不会,但是从心里还是喜欢。

喜欢是喜欢,但是没有目标的学习始终都是在耍流氓,浪费自己的时间、精力还学不好。既然是喜欢,既然开始学了,就一定要学好。我们现在是报的一个课程12节课的班,我的目标是通过这一个课程的学习,了解架子鼓的基本演奏技巧,学会一首歌曲的演奏。就《大风吹》吧,谁叫这歌这段时间这么火呢。计划是每周二、四上课,每天拿出1个小时用来练习。学鼓,虽然我不是天赋最好的,但我争取做那个最认真的!

今天根据老师的建议在网上买了练习用的哑鼓垫、军鼓架、鼓棒、节拍器。后面动次打次练起来!

以后我的标签又多了一个–鼓手!



“fullbug”微信公众号

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

穷忙与假努力

发表于 2021-12-28 | 更新于: 2025-08-10 | 分类于 人生 | | 阅读次数:
字数统计: 1.4k | 阅读时长 ≈ 4

穷忙与假努力

穷忙与假努力

时间过得真快,只有几天2021年即将过去。每次到了年底回想起来总是感觉时间过得真快,忙忙碌碌又过了一年,可自己各方面取得的成绩乏善可陈。自己并不是很懒惰的人,看上去每天都很忙,却没有忙出效果,反而是随着年龄的增大越来越焦虑。越焦虑就暗自下决心以后要更加努力,当努力没有达到效果时就更加的焦虑。陷入了越努力->越失望->越焦虑的怪圈。

没有目标、没有效果的忙就是穷忙,看上去努力却实际没有效果的努力是假努力,穷忙和假努力往往是一同出现的,假努力造成了穷忙,穷忙成就了假努力。相对于不努力,有时候“假努力”会更加可怕!因为它像安慰剂一样,让你感觉是在努力而不自知,会让你陷入深深的自我怀疑,对自己失望,最后越来越糟,失去对学习、工作、生活的兴趣。

到底什么样的表现是“假努力”呢?有老师针对孩子们在学习上的表现列举了一些“假努力”表现,给了我很大的启发。

“假努力”表现一:上课只顾抄笔记,老师讲的都不听。
有很多同学在上课的时候表现得特别忙,看上去特别努力的在学习,老师黑板上写的,还是口头上说的,他们都会事无巨细地写下来。然而,对于老师们讲的是什么?本节课的重难点又是什么?他们全然无所谓,只顾着把这堂课发生的所有一切都记录下来。这样的“假努力”注定会让课堂的效率低下,让自己的努力完全沦为无用的“假努力”。

“假努力”表现二:花很多时间做笔记,课后却从来不去理解。
有第一种“假努力”的同学,往往都存在着“假努力”的第二种表现,那就是笔记写得非常非常多,但是至于笔者写的内容和知识点,他们都从来不看,更不会花时间去理解和搞懂笔记上的内容。这样花大力气写下的笔记,当然最终沦为无用功。

“假努力”表现三:只顾刷题,从来都不花时间总结。
还有一部分“假努力”的同学,每天花大量的时间刷题,而且他们往往还有一个显著的特征,那就是只管做题多少,从来不过问题目对错!那些错题,反复出现问题的题目,他们从来都是不管不顾,只觉得刷了足够的题目,自己的成绩自然而然会上升!然而,殊不知他们把大量的时间花在了已经会的题目上,那些不会、易错的题目还是永远会错。

“假努力”表现四:每天熬夜学习,白天学习效率低下。
不知道各位老师和同学有没有发现,几乎每一个中学班级里,总会出现这么一两个“夜晚学习狂魔”,他么总喜欢晚上搞学习,并且熬非常的时间,导致第二天整个人的精神状态都不好,白天的学习效率极其低下!最后陷入一个“白天该学的时候状态差,晚上不该学的时候拼命学”的死循环当中。

“假努力”表现五:没有目标和计划的去学习。
这种“假努力”的表现有一个典型的例子,比如某个同学们英语很差,想通过自己的努力学好英语,然后就从英语单词开始入手,每天背课本上的单词,而且无论什么时候都是从单词表的第一个单词去背起!这样无计划、无目标的努力,只会耗费巨大的时间和精力在重复学习之上!进而导致学习成绩的速度异常的缓慢!

从这些表现上来看,其实我们成年人在平时学习、工作中同样存在这些类似的问题。个人认为造成穷忙和假努力最大的问题是没有目标和计划。东一榔头、西一棒子,不知道自己到底要学什么,要学到一个什么样的程度。就像小时候课本里的小猴子去掰玉米,看什么捡什么,最后捡了芝麻丢了西瓜。另外一个就是要有系统化、体系化的思维去学习。只有系统化、体系化的去学习某个东西,建立该领域的知识体系结构体系才能在有体系结构的基础上进行积累,才能学得好,学得牢。现在公众号、抖音、知乎上碎片化的知识很多,哪怕你是天天上知乎去关注学习这些碎片化的知识而没有建立一个知识体系去有意识的去理解吸收的话,那就类似于花了很多时间去做笔记,去关注去了解,课后从来不去理解。给人感觉是看上去在很努力的学习,其实啥也没有学到。


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


“fullbug”微信公众号

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

新场地,新征程!

发表于 2021-12-10 | 更新于: 2025-08-10 | 分类于 人生 | | 阅读次数:
字数统计: 144 | 阅读时长 ≈ 1

服务数字经济,护航美好生活!

2021年12月09日通服网安研发团队强势入驻岳麓上大学科技城国家网络安全产业园。

新场地,新征程,数网络安全研发,还看通服网安!

通服网安揭牌

通服网安

通服网安研发团队

通服网安研发团队

通服网安研发大楼

通服网安研发大楼

通服网安研发大楼外景

通服网安研发大楼外景

通服网安前台

通服网安前台

展厅入口

通服网安展厅入口

通服网安展厅

通服网安展厅

通服网安研发楼展厅安全运营中心展示

通服网安研发楼展厅安全运营中心展示

没有网络安全就没有国家安全

没有网络安全就没有国家安全

机器学习实现恶意URL检测实战一

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

恶意URL检测的方法很多,这里介绍通过机器学习分析URL文本分词词频来检测恶意URL。训练的数据集为开源数据集,通过机器学习训练检测模型,然后做了部分工程化的应用,将模型持久化,在应用的时候加载进来直接应用,不用重新进行训练。通过接口调用实现恶意URL检测预测判断。

恶意URL检测,对应与机器学习是个分类问题,这里分别用逻辑回归和SVM支持向量机分类模型进行模型实现。

具体实现过程包括数据载入–>数据处理(分词、向量化处理)–>模型训练–>模型保存–>模型应用

项目组织结构如下:
项目组织结构

一、数据载入

从数据集中载入数据,读取数据,将URL和标签进行识别和区分。

1
2
3
4
5
6
7
8
9
10
#从文件中获取数据集
def getDataFromFile(filename='data/data.csv'):
input_url = filename
data_csv = pd.read_csv(input_url, ',', error_bad_lines=False)
data_df = pd.DataFrame(data_csv)
url_df = np.array(data_df)
random.shuffle(url_df)
y = [d[1] for d in url_df]
inputurls = [d[0] for d in url_df]
return inputurls,y

二、数据处理(分词、向量化处理)

数据处理实现对URL的分词及向量化处理
分词:分析URL根据,.-进行分词,由于com、cn等常用域名不是关键影响因素,所以分词的时候去掉了

分词

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#分词
def getTokens(input):
web_url = input.lower()
urltoken = []
dot_slash = []
slash = str(web_url).split('/')
for i in slash:
r1 = str(i).split('-')
token_slash = []
for j in range(0, len(r1)):
r2 = str(r1[j]).split('.')
token_slash = token_slash + r2
dot_slash = dot_slash + r1 + token_slash
urltoken = list(set(dot_slash))
if 'com' in urltoken:
urltoken.remove('com')
if 'cn' in urltoken:
urltoken.remove('cn')
return urltoken

向量化处理

将分词以后的结果进行词频的向量化处理,形成可以用于模型训练的稀疏矩阵向量

1
2
3
all_urls,y=getDataFromFile(datapath)
url_vectorizer = TfidfVectorizer(tokenizer=getTokens)
x = url_vectorizer.fit_transform(all_urls)

三、模型训练

将经过处理后的训练数据用模型进行训练,将数据集分为两部分一部分用于训练,一部分用于测试评估。

1
2
3
4
5
6
7
8
9
10
11
#训练,通过逻辑回归模型训练
def trainLR(datapath):
all_urls,y=getDataFromFile(datapath)
url_vectorizer = TfidfVectorizer(tokenizer=getTokens)
x = url_vectorizer.fit_transform(all_urls)
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
l_regress = LogisticRegression() # Logistic regression
l_regress.fit(x_train, y_train)
l_score = l_regress.score(x_test, y_test)
print("score: {0:.2f} %".format(100 * l_score))
return l_regress,url_vectorizer

用逻辑回归模型训练的结果是 score: 98.50 %

1
2
3
4
5
6
7
8
9
10
11
#训练,通过SVM支持向量机模型训练
def trainSVM(datapath):
all_urls, y = getDataFromFile(datapath)
url_vectorizer = TfidfVectorizer(tokenizer=getTokens)
x = url_vectorizer.fit_transform(all_urls)
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
svmModel=svm.LinearSVC()
svmModel.fit(x_train, y_train)
svm_score=svmModel.score(x_test, y_test)
print("score: {0:.2f} %".format(100 * svm_score))
return svmModel,url_vectorizer

用SVM模型训练的结果是 score: 99.64 %

可以看出SVM模型训练的结果比逻辑回归模型训练的效果要稍好。

四、保存模型

将训练好的模型进行持久化保存,通过pickle.dump()的方式把训练好的模型参数及特征保存至模型文件,以便于应用的时候不要再进行训练,直接应用训练好的模型。

1
2
3
4
5
6
7
8
9
10
11
12
#保存模型及特征
def saveModel(model,vector):
#保存模型
file1 = modelfile_path
with open(file1, 'wb') as f:
pickle.dump(model, f)
f.close()
#保存特征
file2 = vectorfile_path
with open(file2, 'wb') as f2:
pickle.dump(vector, f2)
f2.close()

通过main方法执行训练模型及保存模型

1
2
3
4
if __name__ == '__main__':
#model,vector=trainLR('data/data.csv')
model, vector = trainSVM('data/data.csv')
saveModel(model,vector)

四、模型应用

通过pickle.load载入已经训练好的模型和特征,并用Flask暴露一个接口调用模型的预测方法进行预测。

载入已经训练好的模型

1
2
3
4
5
6
7
8
9
10
11
12
#载入已经训练好的模型
def loadModel():
file1 = modelfile_path
with open(file1, 'rb') as f1:
model = pickle.load(f1)
f1.close()

file2 = vectorfile_path
with open(file2, 'rb') as f2:
vector = pickle.load(f2)
f2.close()
return model,vector

通过接口进行调用

1
2
3
4
5
6
7
8
9
10
#通过接口进行调用
@app.route('/<path:path>')
def show_predict(path):
X_predict = []
X_predict.append(path)
model, vector = loadModel()
x = vector.transform(X_predict)
y_predict = model.predict(x)
print(y_predict[0])
return "url predict: "+str(y_predict[0])

五、应用效果

将需要检测的URL,输入到http://127.0.0.1:5000/后面,就可以根据输入的URL进行检测给出模型预测的结果。
http://127.0.0.1:5000/sohu.com/a/338823532_354899
检测效果1
http://127.0.0.1:5000/sohu.com/a/%3Cscript%3E/test
检测效果2

完整代码及数据集见:https://github.com/xiejava1018/urldetection.git


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


“fullbug”微信公众号

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

解决Anaconda报The channel is not accessible源通道不可用问题

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

最近在通过pycharm开发python程序,引用anaconda环境建立虚拟环境时报错,报UnavailableInvalidChannel: The channel is not accessible or is invalid.应该是镜像源访问通道无法访问或无效。现将解决办法记录如下:

环境说明:

操作系统:win10
安装有anaconda 4.10.3
pycharm2021.2

报错现象:

在pycharm中新建python项目,引用anaconda建立虚拟环境时报错
报“UnavailableInvalidChannel: The channel is not accessible or is invalid.”
建立虚拟环境报错

解决办法:

1、找到anaconda的源配置文件

根据报错的建议提示:

You will need to ajust your conda configuration to proceed.
Use ‘cona config –show channels’ to view your configuration’s current state,
and use ‘conda config –show-sources’ to view config file location.

意思是建议你需要调整conda的配置来处理,可以通过cona config --show channels命令来查看你当前的配置状态,可以用conda config --show-sources看查看本地的配置文件。
根据这个建议,打开anaconda的命令行控制台。
Anaconda Powershell

敲入“conda config –show-sources”命令,显示当前的通道为https://pypi.tuna.tsinghua.edu.cn/simple 报错就是说这个通道无法访问或无效。

1
2
3
(base) PS C:\Users\xiejava> conda config --show channels
channels:
- https://pypi.tuna.tsinghua.edu.cn/simple

通过“conda config –show-sources” 查看配置文件的路径。配置文件为用户目录下的.condarc文件

1
2
3
4
5
(base) PS C:\Users\xiejava> conda config --show-sources
==> C:\Users\xiejava\.condarc <==
channels:
- https://pypi.tuna.tsinghua.edu.cn/simple
show_channel_urls: True

在这里插入图片描述

2、修改为清华的镜像源

将找到的.condarc文件打开。
拷贝以下清华的镜像源到该文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
channels:
- defaults
custom_channels:
conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
default_channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2
show_channel_urls: True

然后再次运行conda config --show-sources,确认配置文件内容已经修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(base) PS C:\Users\xiejava> conda config --show-sources
==> C:\Users\xiejava\.condarc <==
channels:
- defaults
custom_channels:
conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
default_channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2
show_channel_urls: True

3、验证

再打开pycharm引用Conda Enviroment新建新的虚拟环境。
新建新的虚拟环境
这时不报错可以正常创建Conda虚拟环境了。
创建Conda Environment

至此,修改成清华镜像源解决了Anaconda报The channel is not accessible源通道不可用的问题。


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


“fullbug”微信公众号

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

Python快速实现一个域名、IP信息聚合网站

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

域名和IP地址信息是非常基础的情报信息,目前网上有很多网站都提供了域名信息的查询、IP地址及归属地的查询。本文通过Python Flask实现域名及IP情报信息的聚合网站。

因为域名和IP地址信息会有变化,为了减少接口压力,做了本地数据库的存储,新鲜度保存一周,每次查询先从本地数据库获取信息,如果本地库信息有并且没有超过一个星期就从本地库取,没有就从其他网站获取,并更新到本地库。

一、获取域名WHOIS信息

网上提供域名WHOIS信息查询的网站有很多,这里以http://whois.chinafu.com 为例实现WHOIS信息的查询和解析。

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
import requests
from bs4 import BeautifulSoup
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'
}

def getwhoisinfobychinafu(domain):
ret_result = {}
result=getWhoisInfoFromDB(domain)
if len(result)==0:
whois_service_url = 'http://whois.chinafu.com/whois.php'
post_data={"domain":domain}

try:
post_result=requests.post(whois_service_url,post_data)
if post_result.status_code == 200:
ret_str = post_result.content.decode('utf-8')
soup = BeautifulSoup(ret_str, 'lxml')
items_tr =soup.find(name='table',attrs={'class':'listtable'}).find_all(name='tr')
for item_tr in items_tr:
td_item=item_tr.find(name='td')
if 'colspan' in td_item.attrs:
key_name='详情'
key_value=td_item.find(name='div',id='tab1').text
else:
key_name=item_tr.find(name='th').text
key_value=item_tr.find(name='td').text
ret_result[key_name]=key_value
addchinafuWhoisInfo2DB(ret_result)
except Exception as r:
print('未知错误 %s' % (r))
#ret_result = json.dumps(ret_result, ensure_ascii=False)
else:
ret_result=result[0]
return ret_result

def getWhoisInfoFromDB(domainname):
whoisInfos=db.session.execute('select * from whoisinfo where domain_name="%s" and updated_time > DATE_SUB(CURDATE(), INTERVAL 1 WEEK)' % domainname).fetchall()
whoisInfo_dics=[]
for whoisInfo in whoisInfos:
chinafuwhoisinfo_dic=chinafuwhoisinfo2dic(whoisInfo)
whoisInfo_dics.append(chinafuwhoisinfo_dic)
return whoisInfo_dics

def addchinafuWhoisInfo2DB(chinafuWhoisInfo_dic):
chinafuWhois=WhoisInfo()
chinafuWhois.domain_name=chinafuWhoisInfo_dic.get('域名DomainName')
chinafuWhois.domain_status=chinafuWhoisInfo_dic.get('域名状态Domain Status','')
chinafuWhois.registrar=chinafuWhoisInfo_dic.get('注册商Sponsoring Registrar','')
chinafuWhois.name_server=chinafuWhoisInfo_dic.get('DNS 服务器Name Server','')
chinafuWhois.registrar_creation_date=chinafuWhoisInfo_dic.get('注册日期Registration Date','')
chinafuWhois.registrar_updated_date = chinafuWhoisInfo_dic.get('更新日期Update Date', '')
chinafuWhois.registrar_expiry_date = chinafuWhoisInfo_dic.get('到期日期Expiration Date', '')
chinafuWhois.detail=chinafuWhoisInfo_dic.get('详情', '')[0:10000]
chinafuWhois.source = '中国福网'
db.session.execute('delete from whoisinfo where domain_name="%s" and source="%s"' % (chinafuWhoisInfo_dic.get('域名DomainName'), chinafuWhois.source))
db.session.add(chinafuWhois)
db.session.commit()

这里为了减少直接从其他网站获取WHOIS信息的压力,做了本地数据库的存储,每次先从本地数据库取WHOIS的信息,如果本地库信息有并且没有超过一个星期就从本地库取,没有就从其他网站获取,并更新到本地库。这里getWhoisInfoFromDB实现了取新鲜度为1周的数据,addchinafuWhoisInfo2DB实现将获取的信息保存到本地数据库。

二、根据域名解析出IP

根据域名解析出IP代码:

1
2
3
4
5
6
7
8
def getIPbyDomain(domain):
addr=''
try:
myaddr = socket.getaddrinfo(domain, 'http')
addr=myaddr[0][4][0]
except Exception as e:
print(e)
return addr

三、获取IP信息

获取IP信息的API接口也有很多,有淘宝的 https://ip.taobao.com/outGetIpInfo 、IPINFO http://ipinfo.io/、IPAPI http://ip-api.com/ 以及GeoLite2离线库等。

从淘宝IP获取IP信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def getipinfobytaobao(ip):
taobaoIp_url = 'https://ip.taobao.com/outGetIpInfo'
post_data={"ip":ip,"accessKey":"alibaba-inc"}
ret_ipinfo= {}
try:
return_data=requests.post(taobaoIp_url,post_data)
#其中返回数据中code的值的含义为,0:成功,1:服务器异常,2:请求参数异常,3:服务器繁忙,4:个人qps超出
return_json=json.loads(return_data.text)
if return_json['code']==0:
ret_ipinfo['ip']=return_json['data']['ip']
ret_ipinfo['country']=return_json['data']['country']
ret_ipinfo['region']=return_json['data']['region']
ret_ipinfo['org']=''
ret_ipinfo['city'] = return_json['data']['city']
ret_ipinfo['isp']=return_json['data']['isp']
ret_ipinfo['loc'] = ''
ret_ipinfo['timezone'] = ''
ret_ipinfo['source']='淘宝IP'
addIPInfo2DB(ret_ipinfo)
except Exception as e:
print('未知错误 %s' % (e))
return ret_ipinfo

从ipinfo.io获取IP信息

1
2
3
4
5
6
7
8
9
10
11
12
def getipinfobyipinfo(ip):
api_url='http://ipinfo.io/'+ip
ipinfo = {}
try:
req_return = requests.get(api_url)
if req_return.status_code == 200:
ipinfo = json.loads(req_return.text)
ipinfo['source']='ipinfo.io'
addIPInfo2DB(ipinfo)
except Exception as e:
print('未知错误 %s' % (e))
return ipinfo

从ip-api.com获取IP信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def getipinfobyipapi(ip):
api_url='http://ip-api.com/json/'+ip
ipinfo={}
try:
req_return=requests.get(api_url)
if req_return.status_code==200:
ipinfo=json.loads(req_return.text)
ipinfo['ip'] = ip
ipinfo['source'] = 'ip-api.com'
ipinfo['loc'] = str(ipinfo['lat'])+','+str(ipinfo['lon'])
addIPInfo2DB(ipinfo)
except Exception as e:
print('未知错误 %s' % (e))
return ipinfo

从GeoLite离线库获取IP信息

如何获取GeoLite离线库及如何读取,详见:http://xiejava.ishareread.com/posts/2c5697c0/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def getipinfobygeoip2(ip):
ipinfo={}
dbdir=Config.geoLiteDBdir
with geoip2.database.Reader(dbdir) as reader:
response = reader.city(ip)
ipinfo['ip'] =ip
ipinfo['country'] = response.country.names['zh-CN']
ipinfo['region'] =''
ipinfo['city']=response.city.name
ipinfo['org'] =''
ipinfo['loc'] = str(response.location.latitude)+','+str(response.location.longitude)
ipinfo['timezone'] = response.location.time_zone
ipinfo['source'] = 'GeoIP'
addIPInfo2DB(ipinfo)
return ipinfo

四、搭建一个FLASK Web应用来查询聚合的域名、IP情报信息

1、FLASK Web应用的工程组织

工程组织

2、配置数据及读取配置数据

1)配置数据

配置数据分别放在.env及.flaskenv中,其中.env放的是工程中用到的数据库链接等比较私密的配置信息。.flaskenv放的是Flask运行环境的信息
.env的配置信息参考如下:

1
2
3
4
5
6
DEV_DATABASE_URI = 'mysql+pymysql://dbuser:yourpassword@127.0.0.1:3306/infocol_db_dev?charset=utf8'
TEST_DATABASE_URI = 'mysql+pymysql://dbuser:yourpassword@127.0.0.1:3306/infocol_db_test?charset=utf8'
PROD_DATABASE_URI = 'mysql+pymysql://dbuser:yourpassword@127.0.0.1:3306/infocol_db?charset=utf8'

SQLALCHEMY_TRACK_MODIFICATIONS = True
SECRET_KEY=your secret key

.falskenv配置信息参考如下:

1
FLASK_ENV=development

2)实现读取配置数据

通过config.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
import os
from dotenv import load_dotenv
basedir=os.path.abspath(os.path.dirname(__file__))
flaskenv_path=os.path.join(basedir,'.flaskenv')
env_path=os.path.join(basedir,'.env')
if os.path.exists(flaskenv_path):
load_dotenv(flaskenv_path)
if os.path.exists(env_path):
load_dotenv(env_path)

class Config:
geoLiteDBdir=os.path.join(basedir,'GeoLite2\GeoLite2-City.mmdb')
flaskenv = os.getenv('FLASK_ENV','development')
SECRET_KEY=os.getenv('SECRET_KEY','123!@#')
SQLALCHEMY_TRACK_MODIFICATIONS=os.getenv('SQLALCHEMY_TRACK_MODIFICATIONS')
SQLALCHEMY_DATABASE_URI = os.getenv('DEV_DATABASE_URI')
@staticmethod
def init_app(app):
pass

class DevelopmentConfig(Config):
DEBUG=True
SQLALCHEMY_DATABASE_URI = os.getenv('DEV_DATABASE_URI')

class TestingConfig(Config):
TESTING=True
SQLALCHEMY_DATABASE_URI = os.getenv('TEST_DATABASE_URI')

class ProductionConfig(Config):
SQLALCHEMY_DATABASE_URI = os.getenv('PROD_DATABASE_URI')

config={
'development':DevelopmentConfig,
'testing':TestingConfig,
'production':ProductionConfig,
'default':DevelopmentConfig
}

3、界面及路由

界面很简单就一个域名/IP的输入框,输入域名或IP后去查询相应的域名信息或IP信息显示到界面上。
index界面

界面用jinjia2的模板
index.html代码如下:

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
{% extends "bootstrap/base.html" %}
{% block title %}InfoCol{% endblock %}
{% block head %}
{{ super() }}
<style></style>
{% endblock %}
{% block body %}
{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">InfoCol</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
</ul>
</div>
</div>
</div>
{% endblock %}
{% block content %}
<div class="container">
<div class="page-header " >
<form method="post" class="center-block">
<div class="center-block" style="text-align:center">
{{ form.hidden_tag() }}
{{ form.name.label }}{{ form.name() }}
{{ form.submit() }}
</div>
</form>
</div>
<div>
{% if whois_info %}
<table class="table table-bordered">
<tr><th colspan="2">{{ name }}的Whois信息</th></tr>
{% for item in whois_info %}
{% if item!='详情' %}
<tr><td style="width: 20%">{{ item }}</td><td style="width: 80%">{{ whois_info[item] }}</td></tr>
{% else %}
<tr>
<td style="width: 20%">
<a role="button" data-toggle="collapse" href="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
{{ item }}
</a>
</td>
<td style="width: 80%">
<div class="collapse" id="collapseExample">
<div class="well">
{{ whois_info[item] }}
</div>
</div>
</td>
</tr>
{% endif %}
{% endfor %}
</table>
{% endif %}
{% if ipinfos|length>0 %}
<table class="table table-bordered">
<tr><th>IP</th><th>国家/地区</th><th>省份</th><th>城市</th><th>机构</th><th>ISP</th><th>经纬度</th><th>来源</th></tr>
{% for ipinfo in ipinfos %}
<tr>
<td>{{ ipinfo['ip'] }}</td>
<td>{{ ipinfo['country'] }}</td>
<td>{{ ipinfo['region'] }}</td>
<td>{{ ipinfo['city'] }}</td>
<td>{{ ipinfo['org'] }}</td>
<td>{{ ipinfo['isp'] }}</td>
<td>{{ ipinfo['loc'] }}</td>
<td>
{% if ipinfo['source']=='ipinfo.io' %}
<a href="http://ipinfo.io/{{ ipinfo['ip'] }}" target="_blank">{{ ipinfo['source'] }}</a>
{% elif ipinfo['source']=='ip-api.com'%}
<a href="http://ip-api.com/json/{{ ipinfo['ip'] }}" target="_blank">{{ ipinfo['source'] }}</a>
{% else %}
{{ ipinfo['source'] }}
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% endif %}
</div>
</div>
{% endblock %}
{% endblock %}

路由配置处理中实现了获取表单中的信息,并判断是域名还是IP如果是域名者获取whois信息,并根据域名获取IP信息。如果输入的是IP则获取IP信息,并反馈到页面上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@index_bp.route('/',methods=['GET','POST'])
def index():
name = ''
ipinfos = []
whois_info = ''
form = InputForm()
if form.validate_on_submit():
name = form.name.data
if checkip(name):
ipinfos = getipinfo(name)
else:
whois_info = getwhoisinfo(name)
whois_ip = getIPbyDomain(name)
if checkip(whois_ip):
ipinfos = getipinfo(whois_ip)
form.name.data = ''
return render_template('index.html',form=form, name=name, ipinfos=ipinfos, whois_info=whois_info)

4、最终实现效果

界面查询效果

至此通过Python快速实现了一个简单的域名、IP信息聚合网站


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

演示地址:http://test.ishareread.com/

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


“fullbug”微信公众号

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

<1…161718…21>
XieJava

XieJava

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

主题 — NexT.Muse
0%