日期: 2021 年 5 月 10 日

python实现2048——1、界面&逻辑

python实现2048——1、界面&逻辑

前言
这次,我们来尝试一下2048这款游戏,不了解的可以自行玩一下,这里不展开了。
还是使用pygame,因为我们之前已经有过了好几个pygame项目了,这次我准备快一点,主要讲其中的逻辑部分。

界面搭建
这部分的pygame调用会一笔掠过,如果不知道原理的看一下这个:
之前的部分

2048的效果是这样的:

%title插图%num

4*4的格子,每一个格子上都有一个数字,并且下面有我们的得分。

这次我们没有再使用创建类的方式来存储rect对象和数字,而是分开成两个。
num二维数组:存储数据;
rectangle数组:存储rect对象。
然后将数字和一个个的方块对应上。

整个界面我们是渲染了背景颜色,然后对每一种可能出现的数字都赋予一种和背景颜色不同的颜色,并且我们的方块稍微窄一些,这样就能够显示出一个漂亮的分割线。
随后,在数字非零的方块上,我们显示出数字,就实现了功能。

“””2048小游戏”””
import pygame
from fuc import *
from time import sleep
# 游戏状态
“””当变量为0时,结束循环,退出游戏”””
game_stats = 1

# 颜色
“””背景颜色,深灰色”””
bg_color = (105, 105, 105)
“””每一种数字对应的rgb颜色,用字典封装方便查找”””
color = {
0 :(211, 211, 211),
2 :(255, 255, 255),
4 :(253, 245, 230),
8 :(255, 228, 196),
16 :(255, 222, 173),
32 :(255, 193, 193),
64 :(255, 106, 106),
128:(255, 255, 0 ),
256:(218, 165, 32),
512:(184, 134, 11)
}

# 格子的宽度、高度
lattice = 99

# 得分
score = 0

# 参数封装
“””参数封装成列表,方便我们进行变量的修改”””
game = [game_stats, score]

# 创建矩阵
“””问题1″””
num = [ [0]*4 for i in range(4)]
# rect对象数组,这个是一维数组!,而且这个xy顺序很烦的
“””问题2″””
rectangle = [pygame.Rect(x*lattice+x+1,y*lattice+y+1,lattice,lattice) for y in range(4) for x in range(4)]

# 创建screen对象
pygame.init()
screen = pygame.display.set_mode((400,430))
pygame.display.set_caption(‘2048’)

# 开始游戏
“””先生成一个,不然玩个鬼”””
new(num,game)
while game[0]:
“”刷新””””
update(screen,bg_color,color,num,rectangle,game)
“””事件检测”””
check_events(num,game)
update(screen,bg_color,color,num,rectangle,game)
sleep(3)

问题:

我们如果是使用[[0] *4] *4,你看着会生成一个4 * 4的矩阵,但是当你进行元素的修改,呵呵,原地爆炸。
首先,我们是使用[0]4生成了一个[0,0,0,0]的列表,每一个内容都是不可变类型,进行修改确实没什么,但是第二层,[列表]*4,实际上是将一个二维数组的每一行都指向同一个一维列表。而列表是可变类型,当你进行修改的时候,是在之前的基础上改变的,这样就会导致指向四个列表的位置全部改变。

%title插图%num
这里我采用了一个列表解析,外部的for循环只有一个计数的功能。
这里注意了,我们的rect对象是用一个一维列表存储的,别跟我一样用二维列表的方式调用然后崩了。
Rect函数参数:x、y坐标(左上角),以及矩形的宽度、高度
这里主要是逻辑比较烦,我想要的是0123 \n 4567这样的,所以需要先遍历y然后是x,这样我们第i行第j列的元素就可以使用4*i+j来调用了。
这里,我将处理函数添加在事件检测中了,在确定事件之后,我们就调用对应的函数。

在游戏的*后,我们刷新了一下屏幕,这是因为当判断游戏结束时,我们是没机会再次刷新的,所以会导致看到的结果是不完善的。(其实也可以将update放在check之后,反正玩家没有电脑快)

函数部分
接下来是逻辑部分。
这个游戏就上下左右的检测,然后是一个 关闭界面的退出。
在检测了事件之后,我们就需要判断移动是否有效,因为有效的移动就需要生成一个新的方块;
同时在每一次新生成方块之后,就可能会结束游戏,所以在生成之后我们还需要一个检测。

事件检测
def check_events(num,game):
for event in pygame.event.get():
“””退出事件的检测”””
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
“””按键事件”””
pass

然后我们用event.key == pygame.K_UP来判断按键的方向,类似的还有K_DOWN、K_LEFT、K_RIGHT这些。

就拿向上为例吧。
向上事件中,我们是将数字向上移动和合并,因为每一个方向都是不一样的,所以我进行了一个整合:

for j in range(4):
s = [num[i][j] for i in range(4)]
s_ret = my_sort(s,game)
for i in range(4):
num[i][j] = s_ret[i]

my_sort函数实现了将一个列表向0下标整理的操作,在向上的操作中,我们需要向上整理,所以传入列表推导式s,调用函数实现一列的移动和整合。
还有一个问题就是在我们成功的移动之后,就需要生成一个新的方块。这里的函数叫做new(),实现在0位置生成一个2或者4。那么问题就是如何判断是否成功移动。

ret = 0
for j in range(4):
s = [num[i][j] for i in range(4)]
s_ret = my_sort(s,game)
if s_ret == s:
ret += 1
else:
for i in range(4):
num[i][j] = s_ret[i]
if ret != 4:
new(num,game)

对于每一列,我们保存生成的列表和返回的列表,如果相同则说明该列没有移动成功,如果不同则说明有变化,移动成功。

整体:
(还是没法将四个方向进行一个综合,没想到太好的办法,希望dl指点)

def check_events(num,game):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
ret = 0
for j in range(4):
s = [num[i][j] for i in range(4)]
s_ret = my_sort(s,game)
if s_ret == s:
ret += 1
else:
for i in range(4):
num[i][j] = s_ret[i]
if ret != 4:
new(num,game)
elif event.key == pygame.K_DOWN:
ret = 0
for j in range(4):
s = [num[i][j] for i in range(3,-1,-1)]
s_ret = my_sort(s,game)
if s_ret == s:
ret += 1
else:
for i in range(4):
num[3-i][j] = s_ret[i]
if ret != 4:
new(num,game)
elif event.key == pygame.K_LEFT:
ret = 0
for i in range(4):
s = num[i]
s_ret = my_sort(s,game)
if s_ret == s:
ret += 1
else:
num[i] = s_ret
if ret != 4:
new(num,game)
elif event.key == pygame.K_RIGHT:
ret = 0
for i in range(4):
s = num[i][::-1]
s_ret = my_sort(s,game)
if s_ret == s:
ret += 1
else:
num[i] = s_ret[::-1]
if ret != 4:
new(num,game)

接下来只需要实现检查、排序和new即可。

生成
这个还算简单

def new(num,game):
“””生成新的方块”””
success = 1
x = y = 0
“””先检测一下是否能生成,一般来说用不上”””
for i in range(4):
for j in range(4):
if not num[i][j]:
success = 0
if success:
game[0] = 0
return
# 随机数判断生成啥
while not success:
x = randint(0,3)
y = randint(0,3)
if not num[x][y]:
if (x+y)%2:
num[x][y] = 2
else:
num[x][y] = 4
break
check(num,game)

检查函数
这部分,我也是想了好久,但是只能给出一个比较i复杂的,那就是四个方向都模拟一遍,然后判断是否为都失败了。

def check(num,game):
stats = 0
ret = 0
for i in range(4):
s = num[i]
s_ret = my_sort(s,game)
# 有一列没有移动成功
if s == s_ret:
ret += 1
# 四列都没有移动成功
if ret == 4:
stats += 1
ret = 0
for i in range(4):
s = num[i][::-1]
s_ret = my_sort(s,game)
if s == s_ret:
ret += 1
if ret ==4:
stats += 1
ret = 0
for j in range(4):
s = [num[i][j] for i in range(4)]
s_ret = my_sort(s,game)
if s == s_ret:
ret += 1
if ret == 4:
stats += 1
ret = 0
for j in range(4):
s = [num[3-i][j] for i in range(4)]
s_ret = my_sort(s,game)
if s == s_ret:
ret += 1
if ret == 4:
stats += 1
# 四个方向都废了,说明死掉了
if stats == 4:
game[0] = 0

全程计数,和我们的事件检测基本上相同,只是没有将数据赋值回去罢了。

排序
好了么,还是到这部分了,卡了我好几天的部分(其实是放假摸鱼太狠了)。
我整理了一下我们对于四个数字要实现的:

向下标0移动,中间不能有空着的
相邻的或者是中间只有0的两个元素,可以合并
合并时,下标小的*2,大的为0
合并*骚的一点是比如422这种,我们只能合并到44,而不是一个8,也就是参与合并之后的点不能接着合并了
我试过快慢指针来寻找两个元素,也试过while循环直到中间没有空格(复杂而且不满足第四点)

*后我得到了这样一个算法:
先将所有的非零元素拿出来,进行合并之后再处理一次0。
随后我们按照4个元素个数进行补0操作(因为是向0下标移动,所以是在后面补0)

def my_sort(s,game):
“””将需要处理的一行/一列拿出来,四个元素的列表
我们要把s[0]作为顶端”””
# 先处理,再合并
s = [i for i in s if i]
for i in range(1,len(s)):
if s[i-1] == s[i]:
s[i-1] *= 2
s[i] = 0
# game[1]是我们的得分,合并时可以一起加上
game[1] += s[i-1]
s = [i for i in s if i]
s += [0]*(4-len(s))
return s

*步去除0元素,我们只需要判断相邻的两个即可。

合并之后难面出现0,我们再去除一次,然后在后面补上即可。

刷新
补上这一部分,我们的游戏就能跑起来了。

def update(screen,bg_color,color,num,rectangle,game):
screen.fill(bg_color)
font = pygame.font.SysFont(None,48)
for i in range(4):
for j in range(4):
# 确定数字和rect对象
number = num[i][j]
the_rect = rectangle[i*4+j]
# 绘制底色
col = color[number]
pygame.draw.rect(screen,col,the_rect)
if number:
# 绘制数字
msg_image = font.render(str(number),True,(0, 0, 0),col)
msg_rect = msg_image.get_rect()
msg_rect.center = the_rect.center
screen.blit(msg_image,msg_rect)
# 绘制得分
string = “score:”
string += str(game[1])
msg_image = font.render(string,True,(255, 255, 255),bg_color)
screen.blit(msg_image,(0,400))
pygame.display.flip()

都是调用现成的pygame函数,不清楚的可以看一下往期的几个小游戏。
贪吃蛇
井字棋

结语
这样我们的整个游戏就完事了,不过我想到了几个优化点,我可能会在后续的博客中推出。

不过有一些我已经写过了,所以不准备再来一次了。

保存得分
如果是简单的,可以看这个:
txt读入、写入*高分
如果是高端一点的,想玩玩json文件的,看这个(主要是针对多个变量的,这里一个有一说一其实用不上)

如果是想多一点元素,比如在开始界面我们添加一个开始游戏按钮或者是在死亡之后添加一个弹窗显示得分和*高分:
看这个

NumPy之:使用genfromtxt导入数据

NumPy之:使用genfromtxt导入数据

 

看动画学算法
以动画的方式,图文并茂讲解常用的算法和数据结构,包括各种排序算法、hash、栈、队列、链表、树、散列表、堆、图等,*对物有所值!
flydean程序那些事
¥39.90
订阅专栏
文章目录
简介
genfromtxt介绍
多维数组
autostrip
comments
跳过行和选择列
简介
在做科学计算的时候,我们需要从外部加载数据,今天给大家介绍一下NumPy中非常有用的一个方法genfromtxt。genfromtxt可以分解成两步,*步是从文件读取数据,并转化成为字符串。第二步就是将字符串转化成为指定的数据类型。

genfromtxt介绍
先看下genfromtxt的定义:

numpy.genfromtxt(fname, dtype=<class ‘float’>, comments=’#’, delimiter=None, skip_header=0, skip_footer=0, converters=None, missing_values=None, filling_values=None, usecols=None, names=None, excludelist=None, deletechars=” !#$%&'()*+, -./:;<=>?@[\]^{|}~”, replace_space=’_’, autostrip=False, case_sensitive=True, defaultfmt=’f%i’, unpack=None, usemask=False, loose=True, invalid_raise=True, max_rows=None, encoding=’bytes’)
1
genfromtxt可以接受多个参数,这么多参数中只有fname是必须的参数,其他的都是可选的。

fname可以有多种形式,可以是file, str, pathlib.Path, list of str, 或者generator。

如果是单独的str,那么默认是本地或者远程文件的名字。如果是list of str,那么每个str都被当做文件中的一行数据。如果传入的是远程的文件,这个文件会被自动下载到本地目录中。

genfromtxt还可以自动识别文件是否是压缩类型,目前支持两种压缩类型:gzip 和 bz2。

接下来我们看下genfromtxt的常见应用:

使用之前,通常需要导入两个库:

from io import StringIO
import numpy as np

StringIO会生成一个String对象,可以作为genfromtxt的输入。

我们先定义一个包含不同类型的StringIO:

s = StringIO(u”1,1.3,abcde”)
1
这个StringIO包含一个int,一个float和一个str。并且分割符是 ,。

我们看下genfromtxt*简单的使用:

In [65]: data = np.genfromtxt(s)

In [66]: data
Out[66]: array(nan)

因为默认的分隔符是delimiter=None,所以StringIO中的数据会被作为一个整体转换成数组,结果就是nan。

下面我们添加一个逗号分割符:

In [67]: _ = s.seek(0)

In [68]: data = np.genfromtxt(s,delimiter=”,”)

In [69]: data
Out[69]: array([1. , 1.3, nan])

这次有输出了,但是*后一个字符串因为不能被转换成为float,所以得到了nan。

注意,我们*行需要重置StringIO的指针到文件的开头。这里我们使用 s.seek(0)。

那么怎么把*后一个str也进行转换呢?我们需要手动指定dtype:

In [74]: _ = s.seek(0)

In [75]: data = np.genfromtxt(s,dtype=float,delimiter=”,”)

In [76]: data
Out[76]: array([1. , 1.3, nan])

上面我们指定了所有的数组类型都是float,我们还可以分别为数组的每个元素指定类型:

In [77]: _ = s.seek(0)

In [78]: data = np.genfromtxt(s,dtype=[int,float,’S5′],delimiter=”,”)

In [79]: data
Out[79]: array((1, 1.3, b’abcde’), dtype=[(‘f0’, ‘<i8’), (‘f1’, ‘<f8’), (‘f2’, ‘<U’)])

我们分别使用int,float和str来对文件中的类型进行转换,可以看到得到了正确的结果。

除了指定类型,我们还可以指定名字,上面的例子中,我们没有指定名字,所以使用的是默认的f0,f1,f2。看一个指定名字的例子:

In [214]: data = np.genfromtxt(s, dtype=”i8,f8,S5″,names=[‘myint’,’myfloat’,’mystring’], delimiter=”,”)

In [215]: data
Out[215]:
array((1, 1.3, b’abcde’),
dtype=[(‘myint’, ‘<i8’), (‘myfloat’, ‘<f8’), (‘mystring’, ‘S5’)])

分隔符除了使用字符之外,还可以使用index:

In [216]: s = StringIO(u”11.3abcde”)
In [217]: data = np.genfromtxt(s, dtype=None, names=[‘intvar’,’fltvar’,’strvar’],
…: delimiter=[1,3,5])

In [218]: data
Out[218]:
array((1, 1.3, b’abcde’),
dtype=[(‘intvar’, ‘<i8’), (‘fltvar’, ‘<f8’), (‘strvar’, ‘S5’)])

上面我们使用index作为s的分割。

多维数组
如果数据中有换行符,那么可以使用genfromtxt来生成多维数组:

>>> data = u”1, 2, 3\n4, 5, 6″
>>> np.genfromtxt(StringIO(data), delimiter=”,”)
array([[ 1., 2., 3.],
[ 4., 5., 6.]])

autostrip
使用autostrip 可以删除数据两边的空格:

>>> data = u”1, abc , 2\n 3, xxx, 4″
>>> # Without autostrip
>>> np.genfromtxt(StringIO(data), delimiter=”,”, dtype=”|U5″)
array([[‘1’, ‘ abc ‘, ‘ 2’],
[‘3’, ‘ xxx’, ‘ 4′]], dtype='<U5’)
>>> # With autostrip
>>> np.genfromtxt(StringIO(data), delimiter=”,”, dtype=”|U5″, autostrip=True)
array([[‘1’, ‘abc’, ‘2’],
[‘3’, ‘xxx’, ‘4’]], dtype='<U5′)

comments
默认的comments 是 # ,数据中所有以# 开头的都被看做是注释。

>>> data = u”””#
… # Skip me !
… # Skip me too !
… 1, 2
… 3, 4
… 5, 6 #This is the third line of the data
… 7, 8
… # And here comes the last line
… 9, 0
… “””
>>> np.genfromtxt(StringIO(data), comments=”#”, delimiter=”,”)
array([[1., 2.],
[3., 4.],
[5., 6.],
[7., 8.],
[9., 0.]])

跳过行和选择列
可以使用skip_header 和 skip_footer 来跳过返回的数组特定的行:

>>> data = u”\n”.join(str(i) for i in range(10))
>>> np.genfromtxt(StringIO(data),)
array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
>>> np.genfromtxt(StringIO(data),
… skip_header=3, skip_footer=5)
array([ 3., 4.])

可以使用usecols 来选择特定的行数:

>>> data = u”1 2 3\n4 5 6″
>>> np.genfromtxt(StringIO(data), usecols=(0, -1))
array([[ 1., 3.],
[ 4., 6.]])

如果列还有名字的话,可以用usecols 来选择列的名字:

>>> data = u”1 2 3\n4 5 6″
>>> np.genfromtxt(StringIO(data),
… names=”a, b, c”, usecols=(“a”, “c”))
array([(1.0, 3.0), (4.0, 6.0)],
dtype=[(‘a’, ‘<f8’), (‘c’, ‘<f8’)])
>>> np.genfromtxt(StringIO(data),
… names=”a, b, c”, usecols=(“a, c”))
array([(1.0, 3.0), (4.0, 6.0)],
dtype=[(‘a’, ‘<f8’), (‘c’, ‘<f8’)])

云计算与开源有什么关系 如何学好云计算技术

云计算与开源有什么关系?如何学好云计算技术?作为一种“一切皆服务”的全新IT提供模式,云计算已经与开源变得密不可分,开源日渐成为云计算技术的主流。有很多同学对云计算与开源之间的关系似懂非懂,接下来就给大家分享云计算与开源是如何相互影响的。

%title插图%num

开源技术给云计算带来的影响

1、云原生技术闭环初见雏形。

容器技术应用持续深化,Docker技术热度不减,Kubernetes已成为被企业选用*多的容器编排技术,微服务技术应用逐步落地。云原生应用开发框架SpringCloud已经成为分布式微服务框架中的领导者之一,开源服务网格Istio进一步简化了服务间的通信。Devops助力敏捷开发持续交付。开源IT运维自动化平台Ansible、Salt-stack、持续集成工具Jenkins等的受关注度持续提升。

2、OpenStack成为应用*广泛的开源云管理平台。

目前OpenStack几乎成为云计算开源技术的事实标准,广泛覆盖了网络、虚拟化、操作系统、服务器等方面。预计到2020年,来自OpenStack业务模式的收入将突破50亿美元,年复合增长率达到35%。

3、开源分布式存储技术Redis、Ceph应用广泛。

Redis作为在微服务和容器开发者中*受欢迎的高性能开源键值(Key-Value)存储数据库,目前已被9亿个容器使用。开源分布式存储系统Ceph,凭借其高可靠、高性能、易扩容三大特性,抢占了大部分云平台存储市场。目前,市场上70%~80%的Open-Stack云平台都在采用Ceph作为底层的存储平台。

云计算给开源的影响

1、云计算巨头借收购布局。

近年来,多家国际云计算巨头收购开源公司,以借助开源开拓更为广阔的市场,整体提升本公司在云计算领域的市场竞争力。

2、云计算有望改变传统开源模式。

开源许可证一般都规定只有在“分发”时才需要遵守相关许可证的要求对外公开源代码,云计算的产生创造了以SaaS形式提供服务的全新模式,对传统的开源模式造成了巨大影响。

近年来,在开源技术的支持和推动下,云原生理念在不断丰富的同时实现了落地,云计算人才需求不断增多。很多人想要加入云计算行列,参加专业学习是一个不错的选择。

python 字符编码

python 字符编码

1.Python Unicode字符串
字符串还有一个编码问题。
由于计算机只能处理数字,若是要处理文本,就必须先把文本转换为数字才能处理。*先的计算机在设计时采用8个比特(bit)做为一个字节(byte),因此,一个字节能表示的*大的整数就是255(二进制11111111=十进制255),0 – 255被用来表示大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,好比大写字母 A 的编码是65,小写字母 z 的编码是122。
若是要表示中文,显然一个字节是不够的,至少须要两个字节,并且还不能和ASCII编码冲突,因此,中国制定了GB2312编码,用来把中文编进去。
相似的,日文和韩文等其余语言也有这个问题。为了统一全部文字的编码,Unicode应运而生。Unicode把全部语言都统一到一套编码里,这样就不会再有乱码问题了。
Unicode一般用两个字节表示一个字符,原有的英文编码从单字节变成双字节,只须要把高字节所有填为0就能够。
由于Python的诞生比Unicode标准发布的时间还要早,因此*先的Python只支持ASCII编码,普通的字符串’ABC’在Python内部都是ASCII编码的。
Python在后来添加了对Unicode的支持,以Unicode表示的字符串用u’…’表示,好比:
print u’中文’
中文
注意: 不加 u ,中文就不能正常显示。
Unicode字符串除了多了一个 u 以外,与普通字符串没啥区别,转义字符和多行表示法仍然有效:
转义:
u’中文\n日文\n韩文’
多行:
u”’*行
第二行”’
raw+多行:
ur”’Python的Unicode字符串支持”中文”,
“日文”,
“韩文”等多种语言”’
若是中文字符串在Python环境下遇到 UnicodeDecodeError,这是由于.py文件保存的格式有问题。能够在*行添加注释
# -*- coding: utf-8 -*-
目的是告诉Python解释器,用UTF-8编码读取源代码。而后用Notepad++ 另存为… 并选择UTF-8格式保存。

2.解析unicode编码的字符串
使用python抓取页面或者web端的json时候很容易抓到一些unicode编码的字符串流。在python里边对Unicode编码的处理成了一件头疼的事。

对于string里边不含”引号的处理比较简单,使用eval注明引入str是unicode编码:

str1 = eval(“u”+”\””+str + “\””)

str1.decode(‘utf8’)
对于包含引号的明文,须要先把引号转化为 \”,而后能够进行eval函数处理。 web

str=str.replace(“\\\””,”\\\\\””) #先转化字符串中的\”
str=str.replace(“\””,”\\\””) #再转化 ”

print eval(“u”+”\””+str+”\””)
对于json格式unicode的有个很奇怪的处理:

python 的json 库在使用 json.loads()函数时候会默认把输入中unicode编码解析好,而不是保留原输入。 函数

代码: 编码

str1=”{\”html\”:\”\u003c\u003e\”}”
s=json.loads(str1)
print s[“html”]
输出:<>
输出<>而不是 \u003c 这也引出了一个问题:python的json库解析json不彻底保留原格式,使用时候要注意。

若是想要json解析保持unicode编码比较麻烦,需要将unicode码的\改成\\,转译代码以下:

str=”{\”html\”:\”\u003c\”}”
s=str.replace(“\\u”,”\\\\u”)
s2=json.loads(s)
print s2[“html”]
输出: \u003c
3.str字符串和unicode字符串
字符编码
咱们在编辑器中输入的文字,对用户来讲是可读的。可是机器只能读懂01串,那怎么把咱们方便阅读的符号转换成机器能读懂的01串呢?程序员

这就需要给出符号-二进制之间的映射关系,并且必须是一一映射:即给定一个符号,机器有并且有惟一的二进制对应。根据字符获得二进制表示是编码过程(encode);根据二进制表示获得字符是解码过程(decode)。web

ASCII字符集与字符编码
刚开始的时候,给出了ASCII标准,用一个8bits字节来表示字符。并且这个字节实际上只用了7位,*高位是不用的,这样总共能表示128个字符。意味着ASCII字符集只有128个。数据库

随着计算机的普及,愈来愈多的国家开始使用计算机。128个字符难以知足各个国家的语言需求,这促使包含更多字符的字符集诞生,而且须要采用新的编码方案。网络

Latin-1
充分利用8bits字节的高位,扩展到256个字符。编辑器

Unicode字符集与字符编码
Unicode字符集包含了全部种语言的全部字符。一般用U+后接4位的16进制数字表示一个Unicode字符,好比U+FFFF。svg

UTF-8编码
UTF-8是针对Unicode字符集的一种编码方案。编码

用变长字节来表示字符:有的字符用一个字节表示(好比ASCII中规定的字符),有的字符用2个字节表示。*大长度为4字节。spa

%title插图%num

上面这张图是从Wikipedia中截取的。Number of Bytes列表示字节数;Bits for code point列表示多少个bit位是真正有用的;First code point列表示该字节数能表示的*个Unicode字符;Last code point列表示对应字节数能表示的*后一个Unicode字符;Byte i(i=1,2,3,4)列表示第i字节上的bit值。
以第二行为例,这一行的编码需要两个字节,其中真正有用的bit位只有11个,另5位是占位符,能表示从U+0080~U+07FF的Unicode字符。code

至于具体的编码方式,咱们以欧元符号€为例。€在Unicode字符集中对应U+20AC:

U+20AC位于U+0800~U+FFFF之间,因此须要三个字节来表示;
十六进制20AC能够写成二进制:0010 0000 1010 1100;
前4个bit放在*字节的低4位:11100010;
中间6个bit放在第二字节的低6位:10000010;
后6个bit放在第三字节的低6位:10101100;
因而€的UTF-8编码为:11100010 10000010 10101100。
Unicode字符集还有其余的编码方式,这里就介绍到这里。

要记住:全部的编码方式都是向后兼容ASCII的。ASCII字符对应什么二进制,那么在其余编码方式中也对应一样的二进制。

3.Python的字符串类型
Python包含两种字符串类型:str(其实就是二进制)和unicode。当只会用到ASCII字符集时,一切相安无事。一旦出现其余字符集,问题也就接踵而来。因此下面咱们着重介绍非ASCII字符串。

str类型
咱们平时写的用引号括起来的字符串都是str类型的。
<span style=”color:#000000″>>>> x = <span style=”color:#219161″><span style=”color:#219161″>’哈哈'</span></span>
>>> x
<span style=”color:#219161″><span style=”color:#219161″>’\xb9\xfe\xb9\xfe'</span></span></span>
根据上面的打印结果,能够知道str类型的x存的实际上是二进制序列,而非字符串。为何会出现这种状况呢?咱们赋给x的明明是字符串。

其实很简单,x通过了一次隐形的编码过程encode()。应该采用的是系统默认编码方案。
– unicode类型
若是在引号的前面加上字符u,那么咱们就获得一个unicode字符串:

<span style=”color:#000000″>>>> x = <span style=”color:#219161″><span style=”color:#219161″>u’哈哈'</span></span>
>>> x
<span style=”color:#219161″><span style=”color:#219161″>u’\u54c8\u54c8′</span></span></span>
unicode对象保存的是字符串自己,而非二进制序列。好比程序中的unicode字符串中包含两个U+54c8字符。

unicode编码为str
可是有的时候,咱们须要二进制序列,好比将数据写入文件、发送到网络或者写入数据库中时。若是不进行任何处理,会出现错误:

<span style=”color:#000000″>>>> x = <span style=”color:#219161″><span style=”color:#219161″>u’哈哈'</span></span>
>>> x
<span style=”color:#219161″><span style=”color:#219161″>u’\u54c8\u54c8′</span></span>
>>> f = open(<span style=”color:#219161″><span style=”color:#219161″>’test.txt'</span></span>, <span style=”color:#219161″><span style=”color:#219161″>’w'</span></span>);
>>> f.write(x)
Traceback (most recent call last):
File <span style=”color:#219161″><span style=”color:#219161″>”<stdin>”</span></span>, line <span style=”color:#40a070″><span style=”color:#40a070″>1</span></span>, <span style=”color:#954121″><span style=”color:#954121″>in</span></span> <module>
UnicodeEncodeError: <span style=”color:#219161″><span style=”color:#219161″>’ascii'</span></span> codec can<span style=”color:#219161″><span style=”color:#219161″>’t encode characters in position 0-1: ordinal not in range(128)</span></span></span>
这是由于在把字符串写入文件时,会首先检查字符串的类型,若是是str类型的字符串,那么一切OK;若是是unicode类型的字符串,那么会隐式地对其编码,即x.encode()。而系统默认的编码方案是ASCII(能够经过sys.getdefaultencoding()查看),对非ASCII字符进行编码的时候,确定会出现错误。

为了不错误,在写入文件以前,应该用utf-8或者gbk编码方案对unicode字符串编码:

<span style=”color:#000000″>>>> x = <span style=”color:#219161″><span style=”color:#219161″>u’哈哈'</span></span>
>>> x
<span style=”color:#219161″><span style=”color:#219161″>u’\u54c8\u54c8′</span></span>
>>> f = open(<span style=”color:#219161″><span style=”color:#219161″>’test.txt'</span></span>, <span style=”color:#219161″><span style=”color:#219161″>’w'</span></span>);
>>> x = x.encode(<span style=”color:#219161″><span style=”color:#219161″>’utf-8′</span></span>) <span style=”color:#408080″><em><span style=”color:#408080″><em>#unicode -> str</em></span></em></span>
>>>x
<span style=”color:#219161″><span style=”color:#219161″>’\xe5\x93\x88\xe5\x93\x88′</span></span>
>>> f.write(x)</span>
str解码为unicode
当从文本中读取数据时,读到的是str字符串,并且咱们已经知道,它保存的是二进制序列。若是其中包含非ASCII文本,咱们应该怎么恢复呢?这时候就要用到解码decode()。

<span style=”color:#000000″>>>> f = open(<span style=”color:#219161″><span style=”color:#219161″>’test.txt'</span></span>, <span style=”color:#219161″><span style=”color:#219161″>’w'</span></span>);
>>> x = f.read()
>>> x
<span style=”color:#219161″><span style=”color:#219161″>’\xe5\x93\x88\xe5\x93\x88′</span></span>
>>> x = x.decode(<span style=”color:#219161″><span style=”color:#219161″>’utf-8′</span></span>) <span style=”color:#408080″><em><span style=”color:#408080″><em>#str -> unicode</em></span></em></span>
>>> x
<span style=”color:#219161″><span style=”color:#219161″>u’\u54c8\u54c8′</span></span></span>
必定要记得,用什么方式编码的就必须用什么方式解码。否则的话,从二进制到字符的对应过程会出现UnicodeDecodeError。

print语句
print语句的参数须要是str类型,并且在执行的时候会用系统的编码方式对str进行隐式解码。

两个遗留问题
#-*-coding:utf-8 -*-
如今暂且认为若是脚本中包含中文,那么必须加上这个声明。

setdefaultencoding() 这个方法貌似如今不能够用了。我以为这个设置与encode()、decode()在不指明参数的状况下的默认参数有关。

python删除相似度高的图片

python删除相似度高的图片

1.参考博客:
python—–删除同一文件夹下相似的图片
Python-列表删除重复元素/图像相似度判断及删除相似图像
python 图像相似 phash和compare_ssim比较
利用Python轻松实现图片相似度对比(一)
利用Python轻松实现图片相似度对比(二)
因为输入是视频,切完帧之后都是连续图片,所以主要参考*篇博客的*种方法。我的目录结构如下:

%title插图%num

其中frame_output是视频切帧后的保存路径,1和2文件夹分别对应两个是视频切帧后的图片。

2.切帧的代码如下:
#encoding:utf-8
import os
import sys
import cv2

video_path = ‘/home/pythonfile/video/’ # *对路径,video下有两段视频
out_frame_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), ‘frame_output’) #frame_output是视频切帧后的保存路径
if not os.path.exists(out_frame_path):
os.makedirs(out_frame_path)
print(‘out_frame_path’, out_frame_path)
files = []
list1 = os.listdir(video_path)
print(‘list’, list1)
for i in range(len(list1)):
item = os.path.join(video_path, list1[i])
files.append(item)
print(‘files’,files)
for k,file in enumerate(files):
frame_dir = os.path.join(out_frame_path, ‘%d’%(k+1))
if not os.path.exists(frame_dir):
os.makedirs(frame_dir)
cap = cv2.VideoCapture(file)
j = 0
print(‘start prossing NO.%d video’ % (k + 1))
while True:
ret, frame = cap.read()
j += 1
if ret:
#每三帧保存一张
if j % 3 == 0:
cv2.imwrite(os.path.join(frame_dir, ‘%d.jpg’%j), frame)
else:
cap.release()
break
print(‘prossed NO.%d video’%(k+1))

3.删除相似度高的图片
根据我的文件结构参考*篇博客的*种方法修改后的代码如下:

# coding: utf-8
import os
import cv2
# from skimage.measure import compare_ssim
# from skimage.metrics import _structural_similarity
from skimage.metrics import structural_similarity as ssim

def delete(filename1):
os.remove(filename1)

def list_all_files(root):
files = []
list = os.listdir(root)
# os.listdir()方法:返回指定文件夹包含的文件或子文件夹名字的列表。该列表顺序以字母排序
for i in range(len(list)):
element = os.path.join(root, list[i])
# 需要先使用python路径拼接os.path.join()函数,将os.listdir()返回的名称拼接成文件或目录的*对路径再传入os.path.isdir()和os.path.isfile().
if os.path.isdir(element): # os.path.isdir()用于判断某一对象(需提供*对路径)是否为目录
# temp_dir = os.path.split(element)[-1]
# os.path.split分割文件名与路径,分割为data_dir和此路径下的文件名,[-1]表示只取data_dir下的文件名
files.append(list_all_files(element))

elif os.path.isfile(element):
files.append(element)
# print(‘2’,files)
return files

def ssim_compare(img_files):
count = 0
for currIndex, filename in enumerate(img_files):
if not os.path.exists(img_files[currIndex]):
print(‘not exist’, img_files[currIndex])
break
img = cv2.imread(img_files[currIndex])
img1 = cv2.imread(img_files[currIndex + 1])
#进行结构性相似度判断
# ssim_value = _structural_similarity.structural_similarity(img,img1,multichannel=True)
ssim_value = ssim(img,img1,multichannel=True)
if ssim_value > 0.9:
#基数
count += 1
imgs_n.append(img_files[currIndex + 1])
print(‘big_ssim:’,img_files[currIndex], img_files[currIndex + 1], ssim_value)
# 避免数组越界
if currIndex+1 >= len(img_files)-1:
break
return count

if __name__ == ‘__main__’:
path = ‘/home/dj/pythonfile/frame_output/’

img_path = path
imgs_n = []

all_files = list_all_files(path) #返回包含完整路径的所有图片名的列表
print(‘1’,len(all_files))

for files in all_files:
# 根据文件名排序,x.rfind(‘/’)是从右边寻找*个‘/’出现的位置,也就是*后出现的位置
# 注意sort和sorted的区别,sort作用于原列表,sorted生成新的列表,且sorted可以作用于所有可迭代对象
files.sort(key = lambda x: int(x[x.rfind(‘/’)+1:-4]))#路径中包含“/”
# print(files)
img_files = []
for img in files:
if img.endswith(‘.jpg’):
# 将所有图片名都放入列表中
img_files.append(img)
count = ssim_compare(img_files)
print(img[:img.rfind(‘/’)],”路径下删除的图片数量为:”,count)
for image in imgs_n:
delete(image)

4.关于导入skimage.measure import compare_ssim出错的解决方法:
from skimage.measure import compare_ssim as sk_cpt_ssim error,从skimage导入compare_ssim出错。

from skimage.measure import compare_ssim
1
改为

from skimage.metrics import _structural_similarity
1
参考官网:https://scikit-image.org/docs/stable/auto_examples/transform/plot_ssim.html#sphx-glr-auto-examples-transform-plot-ssim-py

SSIM(structural similarity)算法原理

5.查看python安装路径及依赖包路径
ubuntu查看python及安装包的位置

6.*后贴上_structural_similarity.py的源码,以后学习
from warnings import warn
import numpy as np
from scipy.ndimage import uniform_filter, gaussian_filter

from ..util.dtype import dtype_range
from ..util.arraycrop import crop
from .._shared.utils import warn, check_shape_equality

__all__ = [‘structural_similarity’]

def structural_similarity(im1, im2,
*,
win_size=None, gradient=False, data_range=None,
multichannel=False, gaussian_weights=False,
full=False, **kwargs):
“””
Compute the mean structural similarity index between two images.

Parameters
———-
im1, im2 : ndarray
Images. Any dimensionality with same shape.
win_size : int or None, optional
The side-length of the sliding window used in comparison. Must be an
odd value. If `gaussian_weights` is True, this is ignored and the
window size will depend on `sigma`.
gradient : bool, optional
If True, also return the gradient with respect to im2.
data_range : float, optional
The data range of the input image (distance between minimum and
maximum possible values). By default, this is estimated from the image
data-type.
multichannel : bool, optional
If True, treat the last dimension of the array as channels. Similarity
calculations are done independently for each channel then averaged.
gaussian_weights : bool, optional
If True, each patch has its mean and variance spatially weighted by a
normalized Gaussian kernel of width sigma=1.5.
full : bool, optional
If True, also return the full structural similarity image.

Other Parameters
—————-
use_sample_covariance : bool
If True, normalize covariances by N-1 rather than, N where N is the
number of pixels within the sliding window.
K1 : float
Algorithm parameter, K1 (small constant, see [1]_).
K2 : float
Algorithm parameter, K2 (small constant, see [1]_).
sigma : float
Standard deviation for the Gaussian when `gaussian_weights` is True.

Returns
——-
mssim : float
The mean structural similarity index over the image.
grad : ndarray
The gradient of the structural similarity between im1 and im2 [2]_.
This is only returned if `gradient` is set to True.
S : ndarray
The full SSIM image. This is only returned if `full` is set to True.

Notes
—–
To match the implementation of Wang et. al. [1]_, set `gaussian_weights`
to True, `sigma` to 1.5, and `use_sample_covariance` to False.

.. versionchanged:: 0.16
This function was renamed from “skimage.measure.compare_ssim“ to
“skimage.metrics.structural_similarity“.

References
———-
.. [1] Wang, Z., Bovik, A. C., Sheikh, H. R., & Simoncelli, E. P.
(2004). Image quality assessment: From error visibility to
structural similarity. IEEE Transactions on Image Processing,
13, 600-612.
https://ece.uwaterloo.ca/~z70wang/publications/ssim.pdf,
:DOI:`10.1109/TIP.2003.819861`

.. [2] Avanaki, A. N. (2009). Exact global histogram specification
optimized for structural similarity. Optical Review, 16, 613-621.
:arxiv:`0901.0065`
:DOI:`10.1007/s10043-009-0119-z`

“””
check_shape_equality(im1, im2)

if multichannel:
# loop over channels
args = dict(win_size=win_size,
gradient=gradient,
data_range=data_range,
multichannel=False,
gaussian_weights=gaussian_weights,
full=full)
args.update(kwargs)
nch = im1.shape[-1]
mssim = np.empty(nch)
if gradient:
G = np.empty(im1.shape)
if full:
S = np.empty(im1.shape)
for ch in range(nch):
ch_result = structural_similarity(im1[…, ch],
im2[…, ch], **args)
if gradient and full:
mssim[…, ch], G[…, ch], S[…, ch] = ch_result
elif gradient:
mssim[…, ch], G[…, ch] = ch_result
elif full:
mssim[…, ch], S[…, ch] = ch_result
else:
mssim[…, ch] = ch_result
mssim = mssim.mean()
if gradient and full:
return mssim, G, S
elif gradient:
return mssim, G
elif full:
return mssim, S
else:
return mssim

K1 = kwargs.pop(‘K1’, 0.01)
K2 = kwargs.pop(‘K2’, 0.03)
sigma = kwargs.pop(‘sigma’, 1.5)
if K1 < 0:
raise ValueError(“K1 must be positive”)
if K2 < 0:
raise ValueError(“K2 must be positive”)
if sigma < 0:
raise ValueError(“sigma must be positive”)
use_sample_covariance = kwargs.pop(‘use_sample_covariance’, True)

if gaussian_weights:
# Set to give an 11-tap filter with the default sigma of 1.5 to match
# Wang et. al. 2004.
truncate = 3.5

if win_size is None:
if gaussian_weights:
# set win_size used by crop to match the filter size
r = int(truncate * sigma + 0.5) # radius as in ndimage
win_size = 2 * r + 1
else:
win_size = 7 # backwards compatibility

if np.any((np.asarray(im1.shape) – win_size) < 0):
raise ValueError(
“win_size exceeds image extent. If the input is a multichannel ”
“(color) image, set multichannel=True.”)

if not (win_size % 2 == 1):
raise ValueError(‘Window size must be odd.’)

if data_range is None:
if im1.dtype != im2.dtype:
warn(“Inputs have mismatched dtype. Setting data_range based on ”
“im1.dtype.”, stacklevel=2)
dmin, dmax = dtype_range[im1.dtype.type]
data_range = dmax – dmin

ndim = im1.ndim

if gaussian_weights:
filter_func = gaussian_filter
filter_args = {‘sigma’: sigma, ‘truncate’: truncate}
else:
filter_func = uniform_filter
filter_args = {‘size’: win_size}

# ndimage filters need floating point data
im1 = im1.astype(np.float64)
im2 = im2.astype(np.float64)

NP = win_size ** ndim

# filter has already normalized by NP
if use_sample_covariance:
cov_norm = NP / (NP – 1) # sample covariance
else:
cov_norm = 1.0 # population covariance to match Wang et. al. 2004

# compute (weighted) means
ux = filter_func(im1, **filter_args)
uy = filter_func(im2, **filter_args)

# compute (weighted) variances and covariances
uxx = filter_func(im1 * im1, **filter_args)
uyy = filter_func(im2 * im2, **filter_args)
uxy = filter_func(im1 * im2, **filter_args)
vx = cov_norm * (uxx – ux * ux)
vy = cov_norm * (uyy – uy * uy)
vxy = cov_norm * (uxy – ux * uy)

R = data_range
C1 = (K1 * R) ** 2
C2 = (K2 * R) ** 2

A1, A2, B1, B2 = ((2 * ux * uy + C1,
2 * vxy + C2,
ux ** 2 + uy ** 2 + C1,
vx + vy + C2))
D = B1 * B2
S = (A1 * A2) / D

# to avoid edge effects will ignore filter radius strip around edges
pad = (win_size – 1) // 2

# compute (weighted) mean of ssim
mssim = crop(S, pad).mean()

if gradient:
# The following is Eqs. 7-8 of Avanaki 2009.
grad = filter_func(A1 / D, **filter_args) * im1
grad += filter_func(-S / B2, **filter_args) * im2
grad += filter_func((ux * (A2 – A1) – uy * (B2 – B1) * S) / D,
**filter_args)
grad *= (2 / im1.size)

if full:
return mssim, grad, S
else:
return mssim, grad
else:
if full:
return mssim, S
else:
return mssim

moviepy的神奇操作竟然让我完成了对B站的爬取

moviepy的神奇操作竟然让我完成了对B站的爬取

 

文章目录
前言
目标分析
遇到问题
发现神器
下载安装
查文档
使用
结语
前言
*个人主张自学,但是也不能忘记了讨论的重要性,但是由于平时不z怎么看CSDN,所以呢我这边搞了一个小圈子,欢迎大家来哦~可以畅所欲言呀——java小圈子

貌似在Python爬虫这边打Java群广告不太好,不过管他呢,哦哈哈哈
*

目标分析
爬取B站某一视频

遇到问题
在爬取B站的时候我们发现:
B站的视频和音频是分开储存的
那么我们需要将音频视频分别爬取
(具体怎么爬,我也不介绍了,无非就是抓包分析)
然后将视频音频分别储存
而后利用Python将视频音频合在一起
但是怎么利用Python才能将视频音频合在一起?(不会怎么办,没事,搜索引擎会用吧)

发现神器
经过我的不(利)懈(用)努(百)力(度),我找到了一个强劲的第三方库:

moviepy

他可以对视频做出许许多多的操作如:
剪切、拼接、插入标题、视频合成(即非线性编辑)、视频处理和创建高级特效(我的天?pr?)

具体更多操作可以参考官方中文文档——moviepy官方中文文档

下载安装
因为是Python的第三方库嘛,因此就需要请出我们的pip选手将其拿下
打开我们的终端(cmd)输入:
pip install moviepy -i https://pypi.douban.com/simple
然后如果没啥大问题的话,应该都是会成功的

查文档
然后就是找到我们需要的功能(将视频和音频合并),然后去阅读官方文档查看用法

仔细阅读了一遍后,发现还是挺有趣的

具体用法太多,我就不一一列举了,强烈推荐去看看文档然后学习一下,很有用

使用
# 导包
from moviepy.editor import *

# 读取视频文件
videoclip = VideoFileClip(“视频文件名”)
# 读取音频文件
Audioclip = AudioFileClip(“音频文件名”)

# 给 视频 添加 音频
video_data = videoclip.set_audio(Audioclip)

# 保存为另一个视频
video_data.write_videofile(“视频文件名”)

将视频音频合二为一就成功了!

这样我们的爬取B站视频就成功了

完结撒花~

结语
学习本就是一个从无到有的过程,我们要学会如何使用别人的轮子达到我们的效果。

如果我们连用轮子都不会,何谈造轮子。

今天就到这里了,再见

云计算运维工程师怎么样 和传统运维有区别吗

云计算运维工程师怎么样?和传统运维有区别吗?学习云计算就业方向多,运维是其中比较重要地岗位之一。有人好奇云计算运维工程师和传统运维有什么区别?接下来小编就给大家介绍一下。

%title插图%num

传统层面的运维人员,接触的都是硬件,如服务器、设备和风火水电,但是在云时代,运维人员已经无法见到物理的任何设备。

云计算运维岗位涉及到云计算平台能否顺利、平稳地运行,因此运维工程师需要掌握的知识结构也相对比较丰富,既涉及到传统的网络运维知识,还涉及到虚拟化、管控、存储、安全等相关知识。另外,运维工程师还需要具备一定的程序设计能力,以便于完成大规模的自动化服务部署,这对于运维工程师也提出了较高的要求。

云计算运维工程师需要考虑两个问题:

1、应用如何在云平台上实现应用的快速部署,快速更新,实时监控。云计算时代要求运维人员能够自动化地部署应用程序和所有支持的软件和软件包,然后通过生命周期阶段操作维护和管理应用程序,如自动扩展事件和进行软件更新等一系列的操作。

2、如何在云端更加轻松的部署、配置和管理应用。如何利用工具轻松地在云中快速部署和管理应用程序,同时可以自动处理容量预配置、负载均衡、Auto Scaling和应用程序状况监控,这是对运维人员的新要求。

想要快速蜕变成为云计算运维工程师,专业学习一下是非常明智的选择。如果你想快速掌握云计算一系列的技术,专业的学习让你高效、快速掌握企业所需的高薪技术!

如何从事云计算拿高薪 该怎么避免云迁移失败

如何从事云计算拿高薪?该怎么避免云迁移失败?随着云计算在企业中的应用不断增多,越来越多的企业将业务迁移到云上。然而并不是所有云计算部署都能带来好处,一旦云迁移失败企业将面临巨大的损失。接下来就给大家分享避免云迁移失败的几种方法。

%title插图%num

为什么会迁移失败?

许多IT领导者都面临着云迁移的失败,因为他们将应用程序迁移到云中,却发现它们在云中的工作不如在内部部署运行的那样好,这就迫使他们进行反向迁移。

权威调查结果显示,有52%的受访者表示将工作负载从云平台中迁移回内部部署数据中心,其中性能或安全问题是他们做出决定的主要原因,另有21%的受访者将监管问题作为驱动因素。

此外还有一些企业认为成本高于预期;另一些企业发现他们没有从云计算供应商那里得到他们期望的正常运行时间;还有一些企业遇到了复杂的问题,从而降低了他们的系统速度。

如何避免迁移失败?

1、组建团队。

很多企业对云计算服务的需求超过了供应,而完成工作却缺乏高素质的人才。项目之所以取得成功,是因为客户将他们技术团队带到了网络中,并要求他们的系统集成商也将其技术团队带到网络中。如果企业不聘请优秀的人才,那么可能会面临糟糕的结果。

2、谨慎对待云计算

很多企业仍然犯的一个常见错误是将很多东西都转移到云平台上,但并不是很多东西都适用于云计算。如果企业的一些业务与众不同,需要考虑将其转移,例如电子邮件和日历、ERP、HCM,而核心后台功能至关重要,而且难以或缺,但这是企业业务与众不同的地方吗?如果不是,这些都可以迁移到云平台。

3、制定成功的策略

功的迁移包括做出有意识的投资组合决策,以决定要保留哪些内容和要迁移哪些应用程序和工作负载,要保留或放弃哪些平台,以及如何重构应用程序以利用云计算的优势。通过在通用计算、存储和数据库平台上进行标准化,可以降低复杂性,并降低管理成本和运营成本。

4、创新与差异化

成功的企业已经利用云计算的不同性质进行了创新,而不仅仅是复制,这提供了他们从未有过的新原型,将服务提高到了客户几乎从未期望的水平,并采用了新的方式为新市场开发新的应用程序。

为了能够更好的经营云上业务,企业开始高薪竞聘云计算人才,如果你想从事云计算拿高薪,现在正是好时机。

云计算安全措施怎么回事 如何避免云配置错误

云计算安全措施怎么回事?如何避免云配置错误?随着云计算应用加速落地,越来越多的企业将业务迁移到云上。云计算安全措施是云计算客户必须采取的措施,当客户没有在云计算环境中正确配置和保护自己的工作负载和存储桶时,就会发生重大事故。接下来就给大家分享几个常见的云配置错误。

%title插图%num

1、存储访问

在存储桶方面,许多云计算用户认为“经过身份验证的用户”仅涵盖那些在其组织或相关应用程序中已通过身份验证的用户。而情况并非如此。“经过身份验证的用户”是指具有AWS身份验证的任何人,实际上是任何AWS客户。由于这种误解以及由此导致的控件设置错误配置,存储对象*终可能完全暴露给公共访问。

解决方法是设置存储对象访问权限时需要特别小心,确保只有组织内需要访问权限的人员才能访问它。

2、禁用日志记录和监视

有很多企业没有启用、配置甚至检查公共云提供的日志和遥测数据,而在实际应用中,企业云团队中的某个人应该负责定期查看此数据并标记与安全相关的事件。存储即服务供应商通常提供类似的信息,这同样需要定期审查。更新公告或维护警报可能会对企业产生严重的安全影响,但如果没有人注意,则对企业没有任何好处。

3、“秘密”管理

确保诸如密码、API密钥、管理凭据和加密密钥之类的机密至关重要,它们在配置错误的云存储桶、受感染的服务器、开放的GitHub存储库甚至HTML代码中公开可用,这相当于将家门的钥匙放在门前。解决方案是维护企业在云中使用的所有机密的清单,并定期检查以查看每个机密如何得到保护,另外你要使用秘密管理系统。

4、缺乏验证

无论是内部资源还是外部审核员,都必须负责定期验证服务和权限是否已正确配置和应用。设置时间表以确保这种情况像发条一样发生,因为随着环境的变化,错误是不可避免的。企业还需要建立严格的流程来定期审核云配置,否则恶意行为者可以利用这些漏洞。

除了以上内容,常见的云配置错误还包括对主机、容器和虚拟机的访问权限过大等。为了更好的运行云应用,企业纷纷加大对云计算人才的招聘力度,想要入行云计算选择正是好时机。

一次完整的HTTP通信中,web浏览器和web服务器之间完成的七个步骤

1、建立TCP连接:

在HTTP工作开始之前,web浏览器首先要通过网络与web服务器建立连接,该连接是通过TCP来完成的。

为什么要先建立TCP呢?

因为HTTP是比TCP更高层次的应用层协议,根据规则,只有低层协议建立之后才能进行更高层次协议的连接,因此要先建立TCP连接,一般TCP连接的端口号是80

2、web浏览器向web服务器发送请求指令

一旦建立了TCP连接,web浏览器就会向web服务器发送请求指令

其中一部分是请求行,内容包括:请求方法/请求url资源/http协议版本信息;如:(Request-Line)  GET /a.html HTTP/1.1

3、web浏览器发送请求头信息

浏览器发送其请求命令之后,还要以头信息的形式向web服务器发送一些别的信息;如:

Host    127.0.0.1

User-Agent  Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.0.15) Gecko/2009102815 Ubuntu/9.04 (jaunty) Firefox/3.0.15

Accept              text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language     zh-cn,zh;q=0.5

Accept-Encoding     gzip,deflate

Accept-Charset      gb2312,utf-8;q=0.7,;q=0.7

Keep-Alive          300

Connection          keep-alive

之后浏览器还会发送一空行来通知服务器,它已经结束了该头信息的发送

4、web服务器做出应答

web服务器收到客户端的请求后,服务器会向客户端回应

其中一部分是响应头信息;内容包括:http版本信息/状态码 状态文字(状态短语),如:(Status-Line)       HTTP/1.1 200 OK

5、web服务器发送应答头信息

和客户端一样,服务器也会随同发送关于自己的数据以及被请求的文档等信息给客户端;如:

Date                Thu, 26 Nov 2009 13:50:54 GMT

Server              Apache/2.2.11 (Unix) PHP/5.2.9

Last-Modified       Thu, 26 Nov 2009 13:50:19 GMT

Etag                “8fb8b-14-4794674acdcc0″

Accept-Ranges       bytes

Content-Length      20

Keep-Alive          timeout=5, max=100

Connection          Keep-Alive

Content-Type        text/html

这里面比较重要的属性有:Etag(指示资源的状态唯一标识)、Last-Modified(指示*后修改的时间)、Expires(指示资源在浏览器缓存中的过期时间)

这些属性关系到http的缓存机制(前面的文章有说到HTTP请求中的缓存(cache)机制),同时也与HTTP的断点续传原理有关系(后面有相关文章HTTP 1.1 版本新特性描述);

6、Web服务器想浏览器发送数据

web服务器发送完头信息后,它也会发送一个空白行来表示头信息的发送到此为止,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据

7、web服务器关闭TCP连接

一般情况下,一旦web服务器向浏览器发送了请求数据后,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入这行代码:

connection:keep-alive

这样TCP连接将依然保持打开状态,浏览器可以继续通过相同的连接发送请求,保持连接,节省了为每个请求建立新连接所需要的的事件,同时节省了宽带

实际上,在HTTP 1.1 版本的新特性中有一点是:默认持久连接节省通信量,只要客户端、服务端任意一端没有明确断开TCP连接,可以发送多次HTTP请求

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速