首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

#其他

会怎么办?

求关于激光器封装工艺的书籍?

微风导航传送门?

提示验证失败怎么办?

最爱开车啦互联网的敏感者
在克隆代码仓库时需输入服务邮箱与服务密码。你可以前往「个人账户设置」 -> 「个人设置」查看服务凭证。 📷... 展开详请

视频播着播着就卡住了,什么原因造成的呢?

回答来自于问答智囊团成员:bellchen 专栏:https://cloud.tencent.com/developer/article/1734074 猜想 导致视频播放卡顿的原因有千千万万,常见的有如下: 1、网络较差,导致视频下载较慢,需要缓冲,因此卡住了; 可以下载文件到本地,用本地播放器(VLC、QQ播放器等)尝试播放,这个案例应该不是这个原因,本地播放到第1分钟之后也出现了卡住。 📷 2、文件的音频和视频时长不一致,视频只有一分钟,音频有4分30秒; 如果是这种情况,在一分钟之后,视频可能卡住,应该还会继续有声音,不过这个可能性也不是没有,先保持怀疑态度。 📷 视频轨太短,导致画面卡在1分钟处 3、视频格式有问题,播放器播不动,可能原因是单帧过大,单帧时间过长; 这种情况下一个帧率25fps的视频,时长4分30秒的话,应该有270秒*25fps = 6750帧; 如果这个视频的最后一个帧特别大, 这个视频可能只有60秒*25fps=1500帧,而最后一帧时长为3分30秒; 📷 异常的帧长,导致播放卡住 分析 再多的猜测,也只是猜测,还不如剖析下这个视频文件,看问题出在哪里? 我们知道(其实很多人不知道),一个视频文件,其实就是一堆连续的图片快速切换,当画面切换得足够快,人们就以为这玩意动起来了 📷 假装是一个视频,其实我是个GIF 就像一本书一样,每一页就相当于一个画面,既然上述视频在一分钟卡住了,是不是可以直接定位到一分钟处以及之后的视频帧,我们看下到底是怎么了?就像翻书一样,咱们直接翻到那一页; 然而,书比较好翻,视频文件该怎么精准定位呢? 用播放器来播放,会卡住哦,根本看不到细节; 此时,需要借助FFmpeg里的ffprobe工具,进一步分析; 1、查看视频信息: 这一步可以用如下指令获取 ffprobe -show_streams -i 卡住了.mp4 -of json 得到的json数据如下,为了方便观看,我把一些不重要字段删除了 📷 可以看到视频和音频轨道的时长 由此,排除了上述的第二个猜想(视频较短,音频较长,导致画面停留在最后一帧) 当然,上述步骤也可以用MediaInfo工具查看,入口 http://MediaArea.net/MediaInfo 这个工具可以查看文件的视频流、音频流、字幕流、甚至章节Chapters的信息,实在是居家旅行、排忧解难、必备良药! 2、查看每一帧信息 既然音视频流的长度一致,我们试下用ffprobe定位到一分钟之后的那一帧,看有啥异样; 指令如下: ffprobe -select_streams 0 -show_frames -i 卡住了.mp4 -of csv >> 0.csv #查看第一个流的每一帧 ffprobe -select_streams 1 -show_frames -i 卡住了.mp4 -of csv >> 1.csv #查看第一个流的每一帧 #附件的文件中,第一个流是视频,第二个流是音频。 得到的csv文件,用excel打开之后是没有表头的,而且csv文件的第一列固定是"frame"。 如果是视频,剔除第一列之后,表头信息如下 📷 视频帧信息表头 第1个字段media_type表示它是video视频; 第3个字段key_frame表示是否关键帧; 第10个字段pkt_duration表示该帧的时长; 第13个字段pkt_size 表示该帧的大小; 如果是音频,剔除第一列之后,表头信息如下 📷 音频帧表头 音频帧的字段含义类似,只是音频帧的字段数没视频帧那么多。 为了方便大家查看,我把两个csv文件转换为Excel,放在以下附件,并且高亮了pkt_duration和pkt_size两列。 📷 接下来,即可定位到一分钟附近的帧,看是否有异常,为了更加方便看到整个文件的全貌,我把这两个字段做了图表,该视频的帧率是30fps,那么一分钟就有1800帧。 从pkt_duration的图表看是一条直线,说明每一帧的时长都差不多; 但从pkt_size曲线看,在一分钟之前的pkt_size,由于画面不断变动,每一帧的大小不尽相同; 关键帧I帧相对较大,参考帧P帧相对较小,同样是P帧,大小也不大一样。 但一分钟之后,每一个I帧的大小都一样,每一个P帧的大小都一样 📷 这就很奇怪了,而恰好也解释了这个视频的播放异常现象; 结论 说明视频从一分钟之后,不是视频播放卡住了,而是画面静止不动了,由于画面静止不动,所以每一帧的大小是一样的。 卡住了视频每一帧的信息.zip 📷 anyway,结论不重要,用ffprobe分析视频才重要。... 展开详请
回答来自于问答智囊团成员:bellchen 专栏:https://cloud.tencent.com/developer/article/1734074 猜想 导致视频播放卡顿的原因有千千万万,常见的有如下: 1、网络较差,导致视频下载较慢,需要缓冲,因此卡住了; 可以下载文件到本地,用本地播放器(VLC、QQ播放器等)尝试播放,这个案例应该不是这个原因,本地播放到第1分钟之后也出现了卡住。 📷 2、文件的音频和视频时长不一致,视频只有一分钟,音频有4分30秒; 如果是这种情况,在一分钟之后,视频可能卡住,应该还会继续有声音,不过这个可能性也不是没有,先保持怀疑态度。 📷 视频轨太短,导致画面卡在1分钟处 3、视频格式有问题,播放器播不动,可能原因是单帧过大,单帧时间过长; 这种情况下一个帧率25fps的视频,时长4分30秒的话,应该有270秒*25fps = 6750帧; 如果这个视频的最后一个帧特别大, 这个视频可能只有60秒*25fps=1500帧,而最后一帧时长为3分30秒; 📷 异常的帧长,导致播放卡住 分析 再多的猜测,也只是猜测,还不如剖析下这个视频文件,看问题出在哪里? 我们知道(其实很多人不知道),一个视频文件,其实就是一堆连续的图片快速切换,当画面切换得足够快,人们就以为这玩意动起来了 📷 假装是一个视频,其实我是个GIF 就像一本书一样,每一页就相当于一个画面,既然上述视频在一分钟卡住了,是不是可以直接定位到一分钟处以及之后的视频帧,我们看下到底是怎么了?就像翻书一样,咱们直接翻到那一页; 然而,书比较好翻,视频文件该怎么精准定位呢? 用播放器来播放,会卡住哦,根本看不到细节; 此时,需要借助FFmpeg里的ffprobe工具,进一步分析; 1、查看视频信息: 这一步可以用如下指令获取 ffprobe -show_streams -i 卡住了.mp4 -of json 得到的json数据如下,为了方便观看,我把一些不重要字段删除了 📷 可以看到视频和音频轨道的时长 由此,排除了上述的第二个猜想(视频较短,音频较长,导致画面停留在最后一帧) 当然,上述步骤也可以用MediaInfo工具查看,入口 http://MediaArea.net/MediaInfo 这个工具可以查看文件的视频流、音频流、字幕流、甚至章节Chapters的信息,实在是居家旅行、排忧解难、必备良药! 2、查看每一帧信息 既然音视频流的长度一致,我们试下用ffprobe定位到一分钟之后的那一帧,看有啥异样; 指令如下: ffprobe -select_streams 0 -show_frames -i 卡住了.mp4 -of csv >> 0.csv #查看第一个流的每一帧 ffprobe -select_streams 1 -show_frames -i 卡住了.mp4 -of csv >> 1.csv #查看第一个流的每一帧 #附件的文件中,第一个流是视频,第二个流是音频。 得到的csv文件,用excel打开之后是没有表头的,而且csv文件的第一列固定是"frame"。 如果是视频,剔除第一列之后,表头信息如下 📷 视频帧信息表头 第1个字段media_type表示它是video视频; 第3个字段key_frame表示是否关键帧; 第10个字段pkt_duration表示该帧的时长; 第13个字段pkt_size 表示该帧的大小; 如果是音频,剔除第一列之后,表头信息如下 📷 音频帧表头 音频帧的字段含义类似,只是音频帧的字段数没视频帧那么多。 为了方便大家查看,我把两个csv文件转换为Excel,放在以下附件,并且高亮了pkt_duration和pkt_size两列。 📷 接下来,即可定位到一分钟附近的帧,看是否有异常,为了更加方便看到整个文件的全貌,我把这两个字段做了图表,该视频的帧率是30fps,那么一分钟就有1800帧。 从pkt_duration的图表看是一条直线,说明每一帧的时长都差不多; 但从pkt_size曲线看,在一分钟之前的pkt_size,由于画面不断变动,每一帧的大小不尽相同; 关键帧I帧相对较大,参考帧P帧相对较小,同样是P帧,大小也不大一样。 但一分钟之后,每一个I帧的大小都一样,每一个P帧的大小都一样 📷 这就很奇怪了,而恰好也解释了这个视频的播放异常现象; 结论 说明视频从一分钟之后,不是视频播放卡住了,而是画面静止不动了,由于画面静止不动,所以每一帧的大小是一样的。 卡住了视频每一帧的信息.zip 📷 anyway,结论不重要,用ffprobe分析视频才重要。

在各类系统的表格类信息展示的功能中,Limit 分页如何查询优化?

未觉累不许说我笑点低!
回答来自于问答智囊团成员:王文安@DBA 专栏:https://cloud.tencent.com/developer/user/7566357 在 MySQL 支持的 SQL 语法中对此有特殊的支持,开发人员在实现这类功能的时候很方便: select * from xxx limit M,N select * from xxx limit N offset M 这两类语法代表的意思是一样的:返回从第 M 开始(不包括这一行)之后的 N 行数据。虽然使用起来很方便,但是这类语句存在查询性能上的陷阱,需要特别注意一下。 原理简介 在解释原理之前,先看一下实际的效果,看看这个“性能的陷阱”是什么。 📷 性能效果图 两个语句的内容都非常简单,差别只在 limit 的部分,第一个语句跳过的行数很少,第二个语句跳过的行数很多,结果是两个语句的执行时间差了至少 200 倍。PS:limit 配合 order by 使用是一个好习惯,确保结果数据是稳定的。 可以看到跳过的行数大幅度增长时,SQL 语句的执行时间也会快速增长,原因其实比较简单:在处理 limit M,N 的时候,MySQL 会先拿到 M+N 行结果数据,然后再丢弃 M 行数据,展示之后剩下的 N 行数据。所以上图的第二个语句实际上扫描了 800 多万行数据,然后丢弃了 800 万行数据,只展示之后的 1 行结果。 利用慢查询分析三部曲的方法尝试排查一下,explain 和 optimizer_trace 都看不出来差别,但是 profile 里面能看出来两者的差距: 📷 profile 结果 虽然都只输出一行结果,但是在 Sending data 阶段花费的时间差别很大,其实就是花在扫描 800 万行数据上去了。 优化策略 针对这个问题,其实有一个比较通用的优化思路:利用 join,先根据主键搜索到需要的数据,再通过主键关联到原来的表输出结果。SQL 可以改写一下: 📷 SQL 改写的效果 可以看到查询时间降到了 1.5s 左右,提升了约 37%,看起来还可以,那么还有其他的办法么? 显然还是有的,不过这会要求表有自增主键。在分页查询的时候,记录上一次查询结果中的主键,然后在 where 条件中添加主键的范围约束。以上面的查询为例,上次分页查询时的主键是 8000001,那么下次分页的时候,where 条件中添加一个主键约束:id > 8000001,再来看看查询效果: 📷 添加条件之后的效果 可以发现利用主键来筛选掉上一次分页前的所有数据后再用 limit,查询基本是马上返回结果的。不过要特别注意,这种方法是根据主键的顺序先做了一次筛选,不一定会适用于所有的业务场景,理论上 UUID 类的主键也可以用,但是改造 SQL 前务必确保查询结果是符合预期的。 总结一下 MySQL 由于本身查询优化器覆盖到的场景不够全,慢查询的原因也千奇百怪,各类业务 SQL 在上线前尽量多覆盖一些场景,确保业务功能安全发布。... 展开详请
回答来自于问答智囊团成员:王文安@DBA 专栏:https://cloud.tencent.com/developer/user/7566357 在 MySQL 支持的 SQL 语法中对此有特殊的支持,开发人员在实现这类功能的时候很方便: select * from xxx limit M,N select * from xxx limit N offset M 这两类语法代表的意思是一样的:返回从第 M 开始(不包括这一行)之后的 N 行数据。虽然使用起来很方便,但是这类语句存在查询性能上的陷阱,需要特别注意一下。 原理简介 在解释原理之前,先看一下实际的效果,看看这个“性能的陷阱”是什么。 📷 性能效果图 两个语句的内容都非常简单,差别只在 limit 的部分,第一个语句跳过的行数很少,第二个语句跳过的行数很多,结果是两个语句的执行时间差了至少 200 倍。PS:limit 配合 order by 使用是一个好习惯,确保结果数据是稳定的。 可以看到跳过的行数大幅度增长时,SQL 语句的执行时间也会快速增长,原因其实比较简单:在处理 limit M,N 的时候,MySQL 会先拿到 M+N 行结果数据,然后再丢弃 M 行数据,展示之后剩下的 N 行数据。所以上图的第二个语句实际上扫描了 800 多万行数据,然后丢弃了 800 万行数据,只展示之后的 1 行结果。 利用慢查询分析三部曲的方法尝试排查一下,explain 和 optimizer_trace 都看不出来差别,但是 profile 里面能看出来两者的差距: 📷 profile 结果 虽然都只输出一行结果,但是在 Sending data 阶段花费的时间差别很大,其实就是花在扫描 800 万行数据上去了。 优化策略 针对这个问题,其实有一个比较通用的优化思路:利用 join,先根据主键搜索到需要的数据,再通过主键关联到原来的表输出结果。SQL 可以改写一下: 📷 SQL 改写的效果 可以看到查询时间降到了 1.5s 左右,提升了约 37%,看起来还可以,那么还有其他的办法么? 显然还是有的,不过这会要求表有自增主键。在分页查询的时候,记录上一次查询结果中的主键,然后在 where 条件中添加主键的范围约束。以上面的查询为例,上次分页查询时的主键是 8000001,那么下次分页的时候,where 条件中添加一个主键约束:id > 8000001,再来看看查询效果: 📷 添加条件之后的效果 可以发现利用主键来筛选掉上一次分页前的所有数据后再用 limit,查询基本是马上返回结果的。不过要特别注意,这种方法是根据主键的顺序先做了一次筛选,不一定会适用于所有的业务场景,理论上 UUID 类的主键也可以用,但是改造 SQL 前务必确保查询结果是符合预期的。 总结一下 MySQL 由于本身查询优化器覆盖到的场景不够全,慢查询的原因也千奇百怪,各类业务 SQL 在上线前尽量多覆盖一些场景,确保业务功能安全发布。

大兄弟,你之前的GVoice的问题?

如何用Python读写CSV文件?

土子美互联网从业者
读取CSV文件 # importing csv module import csv # csv file name filename = "aapl.csv" # initializing the titles and rows list fields = [] rows = [] # reading csv file with open(filename, 'r') as csvfile: # creating a csv reader object csvreader = csv.reader(csvfile) # extracting field names through first row fields = csvreader.next() # extracting each data row one by one for row in csvreader: rows.append(row) # get total number of rows print("Total no. of rows: %d"%(csvreader.line_num)) # printing the field names print('Field names are:' + ', '.join(field for field in fields)) #  printing first 5 rows print('\nFirst 5 rows are:\n') for row in rows[:5]: # parsing each column of a row for col in row: print("%10s"%col), print('\n') 复制代码在IDE上运行 上述程序的输出如下所示: 📷 以上示例使用CSV文件aapl.csv,可以从此处下载。 使用同一目录中的aapl.csv文件运行此程序。 让我们试着理解这段代码。 使用open(filename,'r')作为csvfile: csvreader = csv.reader(csvfile) 在这里,我们首先在READ模式下打开CSV文件。文件对象名为csvfile。文件对象将转换为csv.reader对象。我们将csv.reader对象保存为csvreader。 fields = csvreader.next() csvreader是一个可迭代的对象。因此,.next()方法返回当前行并将迭代器前进到下一行。由于我们的csv文件的第一行包含标题(或字段名称),因此我们将它们保存在名为fields的列表中。 对于csvreader中的行: rows.append(行) 现在,我们使用for循环遍历剩余的行。每行都附加到名为rows的列表中。如果您尝试打印每一行,可以发现该行只是一个包含所有字段值的列表。 print(“行的总数:%d”%(csvreader.line_num)) csvreader.line_num只是一个计数器,它返回已迭代的行数。 写入CSV文件 # importing the csv module import csv # field names fields = ['Name', 'Branch', 'Year', 'CGPA'] # data rows of csv file rows = [ ['Nikhil', 'COE', '2', '9.0'], ['Sanchit', 'COE', '2', '9.1'], ['Aditya', 'IT', '2', '9.3'], ['Sagar', 'SE', '1', '9.5'], ['Prateek', 'MCE', '3', '7.8'], ['Sahil', 'EP', '2', '9.1']] # name of csv file filename = "university_records.csv" # writing to csv file with open(filename, 'w') as csvfile: # creating a csv writer object csvwriter = csv.writer(csvfile) # writing the fields csvwriter.writerow(fields) # writing the data rows csvwriter.writerows(rows)复制代码在IDE上运行 让我们尝试分解上面的代码。 字段和行已经定义。fields是包含所有字段名称的列表。rows是列表的列表。每行都是包含该行的字段值的列表。 使用open(filename,'w')作为csvfile: csvwriter = csv.writer(csvfile) 在这里,我们首先以WRITE模式打开CSV文件。文件对象名为csvfile。文件对象将转换为csv.writer对象。我们将csv.writer对象保存为csvwriter。 csvwriter.writerow(场) 现在我们使用writerow方法编写第一行,它只是字段名称。 csvwriter.writerows(行) 我们使用writerows方法一次写入多行。 将字典写入CSV文件 # importing the csv module import csv # my data rows as dictionary objects mydict =[{'branch': 'COE', 'cgpa': '9.0', 'name': 'Nikhil', 'year': '2'}, {'branch': 'COE', 'cgpa': '9.1', 'name': 'Sanchit', 'year': '2'}, {'branch': 'IT', 'cgpa': '9.3', 'name': 'Aditya', 'year': '2'}, {'branch': 'SE', 'cgpa': '9.5', 'name': 'Sagar', 'year': '1'}, {'branch': 'MCE', 'cgpa': '7.8', 'name': 'Prateek', 'year': '3'}, {'branch': 'EP', 'cgpa': '9.1', 'name': 'Sahil', 'year': '2'}] # field names fields = ['name', 'branch', 'year', 'cgpa'] # name of csv file filename = "university_records.csv" # writing to csv file with open(filename, 'w') as csvfile: # creating a csv dict writer object writer = csv.DictWriter(csvfile, fieldnames = fields) # writing headers (field names) writer.writeheader() # writing data rows writer.writerows(mydict) 复制代码在IDE上运行 在此示例中,我们将字典mydict写入CSV文件。 使用open(filename,'w')作为csvfile: writer = csv.DictWriter(csvfile,fieldnames = fields) 这里,文件对象(csvfile)被转换为DictWriter对象。 在这里,我们将fieldnames指定为参数。 writer.writeheader() writeheader方法使用预先指定的字段名简单地写入csv文件的第一行。 writer.writerows(mydict) writerows方法只是写入所有行,但在每一行中,它只写入值(而不是键)。 所以,最后,我们的CSV文件如下所示: 📷 重点: 在csv模块中,可以给出可选的dialect参数,该参数用于定义特定于特定CSV格式的一组参数。默认情况下,csv模块使用excel方言,使其与excel电子表格兼容。您可以使用register_dialect方法定义自己的方言。 这是一个例子: csv.register_dialect( 'mydialect', delimiter = ',', quotechar = '"', doublequote = True, skipinitialspace = True, lineterminator = '\r\n', quoting = csv.QUOTE_MINIMAL) 现在,在定义csv.reader或csv.writer对象时,我们可以像 这样指定方言: csvreader = csv.reader(csvfile, dialect='mydialect') 现在,考虑一个CSV文件在纯文本中看起来像这样: 📷 我们注意到分隔符不是逗号而是分号。此外,行由两个换行符而不是一行换行。在这种情况下,我们可以指定分隔符和行终止符,如下所示: csvreader = csv.reader(csvfile, delimiter = ';', lineterminator = '\n\n') 因此,这是关于如何在python程序中加载和解析CSV文件的简短而简洁的讨论。... 展开详请
读取CSV文件 # importing csv module import csv # csv file name filename = "aapl.csv" # initializing the titles and rows list fields = [] rows = [] # reading csv file with open(filename, 'r') as csvfile: # creating a csv reader object csvreader = csv.reader(csvfile) # extracting field names through first row fields = csvreader.next() # extracting each data row one by one for row in csvreader: rows.append(row) # get total number of rows print("Total no. of rows: %d"%(csvreader.line_num)) # printing the field names print('Field names are:' + ', '.join(field for field in fields)) #  printing first 5 rows print('\nFirst 5 rows are:\n') for row in rows[:5]: # parsing each column of a row for col in row: print("%10s"%col), print('\n') 复制代码在IDE上运行 上述程序的输出如下所示: 📷 以上示例使用CSV文件aapl.csv,可以从此处下载。 使用同一目录中的aapl.csv文件运行此程序。 让我们试着理解这段代码。 使用open(filename,'r')作为csvfile: csvreader = csv.reader(csvfile) 在这里,我们首先在READ模式下打开CSV文件。文件对象名为csvfile。文件对象将转换为csv.reader对象。我们将csv.reader对象保存为csvreader。 fields = csvreader.next() csvreader是一个可迭代的对象。因此,.next()方法返回当前行并将迭代器前进到下一行。由于我们的csv文件的第一行包含标题(或字段名称),因此我们将它们保存在名为fields的列表中。 对于csvreader中的行: rows.append(行) 现在,我们使用for循环遍历剩余的行。每行都附加到名为rows的列表中。如果您尝试打印每一行,可以发现该行只是一个包含所有字段值的列表。 print(“行的总数:%d”%(csvreader.line_num)) csvreader.line_num只是一个计数器,它返回已迭代的行数。 写入CSV文件 # importing the csv module import csv # field names fields = ['Name', 'Branch', 'Year', 'CGPA'] # data rows of csv file rows = [ ['Nikhil', 'COE', '2', '9.0'], ['Sanchit', 'COE', '2', '9.1'], ['Aditya', 'IT', '2', '9.3'], ['Sagar', 'SE', '1', '9.5'], ['Prateek', 'MCE', '3', '7.8'], ['Sahil', 'EP', '2', '9.1']] # name of csv file filename = "university_records.csv" # writing to csv file with open(filename, 'w') as csvfile: # creating a csv writer object csvwriter = csv.writer(csvfile) # writing the fields csvwriter.writerow(fields) # writing the data rows csvwriter.writerows(rows)复制代码在IDE上运行 让我们尝试分解上面的代码。 字段和行已经定义。fields是包含所有字段名称的列表。rows是列表的列表。每行都是包含该行的字段值的列表。 使用open(filename,'w')作为csvfile: csvwriter = csv.writer(csvfile) 在这里,我们首先以WRITE模式打开CSV文件。文件对象名为csvfile。文件对象将转换为csv.writer对象。我们将csv.writer对象保存为csvwriter。 csvwriter.writerow(场) 现在我们使用writerow方法编写第一行,它只是字段名称。 csvwriter.writerows(行) 我们使用writerows方法一次写入多行。 将字典写入CSV文件 # importing the csv module import csv # my data rows as dictionary objects mydict =[{'branch': 'COE', 'cgpa': '9.0', 'name': 'Nikhil', 'year': '2'}, {'branch': 'COE', 'cgpa': '9.1', 'name': 'Sanchit', 'year': '2'}, {'branch': 'IT', 'cgpa': '9.3', 'name': 'Aditya', 'year': '2'}, {'branch': 'SE', 'cgpa': '9.5', 'name': 'Sagar', 'year': '1'}, {'branch': 'MCE', 'cgpa': '7.8', 'name': 'Prateek', 'year': '3'}, {'branch': 'EP', 'cgpa': '9.1', 'name': 'Sahil', 'year': '2'}] # field names fields = ['name', 'branch', 'year', 'cgpa'] # name of csv file filename = "university_records.csv" # writing to csv file with open(filename, 'w') as csvfile: # creating a csv dict writer object writer = csv.DictWriter(csvfile, fieldnames = fields) # writing headers (field names) writer.writeheader() # writing data rows writer.writerows(mydict) 复制代码在IDE上运行 在此示例中,我们将字典mydict写入CSV文件。 使用open(filename,'w')作为csvfile: writer = csv.DictWriter(csvfile,fieldnames = fields) 这里,文件对象(csvfile)被转换为DictWriter对象。 在这里,我们将fieldnames指定为参数。 writer.writeheader() writeheader方法使用预先指定的字段名简单地写入csv文件的第一行。 writer.writerows(mydict) writerows方法只是写入所有行,但在每一行中,它只写入值(而不是键)。 所以,最后,我们的CSV文件如下所示: 📷 重点: 在csv模块中,可以给出可选的dialect参数,该参数用于定义特定于特定CSV格式的一组参数。默认情况下,csv模块使用excel方言,使其与excel电子表格兼容。您可以使用register_dialect方法定义自己的方言。 这是一个例子: csv.register_dialect( 'mydialect', delimiter = ',', quotechar = '"', doublequote = True, skipinitialspace = True, lineterminator = '\r\n', quoting = csv.QUOTE_MINIMAL) 现在,在定义csv.reader或csv.writer对象时,我们可以像 这样指定方言: csvreader = csv.reader(csvfile, dialect='mydialect') 现在,考虑一个CSV文件在纯文本中看起来像这样: 📷 我们注意到分隔符不是逗号而是分号。此外,行由两个换行符而不是一行换行。在这种情况下,我们可以指定分隔符和行终止符,如下所示: csvreader = csv.reader(csvfile, delimiter = ';', lineterminator = '\n\n') 因此,这是关于如何在python程序中加载和解析CSV文件的简短而简洁的讨论。

如何在CentOS上创建Kubernetes集群?

土子美互联网从业者
系统环境 kubeadm支持多种系统,这里简单介绍一下需要的系统要求: Ubuntu16.04+ / Debian 9 / CentOS 7 / RHEL 7 / Fedora 25/26(best-effort) / HypriotOS v1.0.1+ / Other 2GB或者以上的RAM(否则将没有足够空间留给app) 2核以上CPU 集群的机器之间必须能通过网络互相通信 SWAP必须被关闭,否则kubelet会出错! 具体的详细信息可以在官方网站上看到。 本篇内容基于aws的ap-northeast-1的ec2, CentOS7的操作系统(ami-4dd5522b),实例类型t2.medium 2核4GB,3台机器,1 master,2 nodes,kubernetes 1.9 版本。为了方便起见,在安全组里面打开了所有的端口和IP访问。 机器配置: [centos@ip-172-31-24-49 ~]$ uname -a Linux ip-172-31-24-49.ap-northeast-1.compute.internal 3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 20 20:32:50 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux 首先 ,我们关闭selinux: $ sudo vim /etc/sysconfig/selinux 📷 把SELINUX改成disabled,然后保存退出。 在我用的ami中,swap是默认关闭的,所以不需要我手动关闭,大家需要确认 自己的环境中swap是否有关闭掉,否则会在之后的环节中出问题。 为了方便我们安装,我们将sshd设置为keepalive: $ sudo -i $ echo "ClientAliveInterval 10" >> /etc/ssh/sshd_config $ echo "TCPKeepAlive yes" >> /etc/ssh/sshd_config $ systemctl restart sshd.service 接下来我们重启一下机器: $ sudo sync $ sudo reboot 至此,准备阶段结束。 安装kubeadm 首先,我们需要在所有机器上都安装 docker, kubeadm, kubelet和 kubectl。 切记:kubeadm不会自动去安装和管理 kubelet和kubectl,所以需要自己去确保安装的版本和你想要安装的kubernetes版本相同。 安装 docker: $ sudo yum install -y docker $ sudo systemctl enable docker && sudo systemctl start docker 在RHEL/CentOS 7 系统上可能会路由失败,我们需要设置一下: $ sudo -i $ cat <<EOF > /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF $ sudo sysctl --system 接下来我们需要安装 kubeadm, kubelet和 kubectl了,我们需要先加一个repo: $ cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF 然后安装: $ sudo yum install -y kubelet kubeadm kubectl $ sudo systemctl enable kubelet && sudo systemctl start kubelet 至此,在所有机器上安装所需的软件已经结束。 使用kubeadm初始化master 安装完所有的依赖之后,我们就可以用 kubeadm初始化master了。 最简单的初始化方法是: $ kubeadm init 除此之外, kubeadm还支持多种方法来配置,具体可以查看一下官方文档。 我们在初始化的时候指定一下kubernetes版本,并设置一下pod-network-cidr(后面的flannel会用到): $ sudo -i $ kubeadm init --kubernetes-version=v1.9.0 --pod-network-cidr=10.244.0.0/16 在这个过程中 kubeadm执行了一系列的操作,包括一些pre-check,生成ca证书,安装etcd和其它控制组件等。 界面差不多如下: 📷 最下面的这行 kubeadm join什么的,就是用来让别的node加入集群的,可以看出非常方便。我们要保存好这一行东西,这是我们之后让node加入集群的凭据,一会儿会用到。 这个时候,我们还不能通过 kubectl来控制集群,要让 kubectl可用,我们需要做: # 对于非root用户 $ mkdir -p $HOME/.kube $ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config $ sudo chown $(id -u):$(id -g) $HOME/.kube/config # 对于root用户 $ export KUBECONFIG=/etc/kubernetes/admin.conf # 也可以直接放到~/.bash_profile $ echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile 接下来要注意,我们必须自己来安装一个network addon。 network addon必须在任何app部署之前安装好。同样的,kube-dns也会在network addon安装好之后才启动。kubeadm只支持CNI-based networks(不支持kubenet)。 比较常见的network addon有: Calico, Canal, Flannel, Kube-router, Romana, WeaveNet等。这里我们使用 Flannel。 $ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml 安装完network之后,你可以通过 kubectlgetpods--all-namespaces来查看 kube-dns是否在running来判断network是否安装成功。 默认情况下,为了保证master的安全,master是不会被调度到app的。你可以取消这个限制通过输入: $ kubectl taint nodes --all node-role.kubernetes.io/master- 加入nodes 终于部署完了我们的master! 现在我们开始加入一些node到我们的集群里面吧! ssh到我们的node节点上,执行刚才下面给出的那个 kubeadm join的命令(每个人不同): $ sudo -i $ kubeadm join --token 72a8a4.2ed9076cd668b8b7 172.31.31.60:6443 --discovery-token-ca-cert-hash sha256:f0894e55d475f882dd40d52c6d01f758017ec5729be632294049f687330f60d2 输出差不多如下图: 📷 这时候,我们去master上输入 kubectlgetnodes查看一下: [root@i-071abd86ed304dc84 ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION i-071abd86ed304dc84 Ready master 12m v1.9.0 i-0c559ad3c0b16fd36 Ready <none> 1m v1.9.0 i-0f3f7462b0a004b5e Ready <none> 47s v1.9.0... 展开详请
系统环境 kubeadm支持多种系统,这里简单介绍一下需要的系统要求: Ubuntu16.04+ / Debian 9 / CentOS 7 / RHEL 7 / Fedora 25/26(best-effort) / HypriotOS v1.0.1+ / Other 2GB或者以上的RAM(否则将没有足够空间留给app) 2核以上CPU 集群的机器之间必须能通过网络互相通信 SWAP必须被关闭,否则kubelet会出错! 具体的详细信息可以在官方网站上看到。 本篇内容基于aws的ap-northeast-1的ec2, CentOS7的操作系统(ami-4dd5522b),实例类型t2.medium 2核4GB,3台机器,1 master,2 nodes,kubernetes 1.9 版本。为了方便起见,在安全组里面打开了所有的端口和IP访问。 机器配置: [centos@ip-172-31-24-49 ~]$ uname -a Linux ip-172-31-24-49.ap-northeast-1.compute.internal 3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 20 20:32:50 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux 首先 ,我们关闭selinux: $ sudo vim /etc/sysconfig/selinux 📷 把SELINUX改成disabled,然后保存退出。 在我用的ami中,swap是默认关闭的,所以不需要我手动关闭,大家需要确认 自己的环境中swap是否有关闭掉,否则会在之后的环节中出问题。 为了方便我们安装,我们将sshd设置为keepalive: $ sudo -i $ echo "ClientAliveInterval 10" >> /etc/ssh/sshd_config $ echo "TCPKeepAlive yes" >> /etc/ssh/sshd_config $ systemctl restart sshd.service 接下来我们重启一下机器: $ sudo sync $ sudo reboot 至此,准备阶段结束。 安装kubeadm 首先,我们需要在所有机器上都安装 docker, kubeadm, kubelet和 kubectl。 切记:kubeadm不会自动去安装和管理 kubelet和kubectl,所以需要自己去确保安装的版本和你想要安装的kubernetes版本相同。 安装 docker: $ sudo yum install -y docker $ sudo systemctl enable docker && sudo systemctl start docker 在RHEL/CentOS 7 系统上可能会路由失败,我们需要设置一下: $ sudo -i $ cat <<EOF > /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF $ sudo sysctl --system 接下来我们需要安装 kubeadm, kubelet和 kubectl了,我们需要先加一个repo: $ cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF 然后安装: $ sudo yum install -y kubelet kubeadm kubectl $ sudo systemctl enable kubelet && sudo systemctl start kubelet 至此,在所有机器上安装所需的软件已经结束。 使用kubeadm初始化master 安装完所有的依赖之后,我们就可以用 kubeadm初始化master了。 最简单的初始化方法是: $ kubeadm init 除此之外, kubeadm还支持多种方法来配置,具体可以查看一下官方文档。 我们在初始化的时候指定一下kubernetes版本,并设置一下pod-network-cidr(后面的flannel会用到): $ sudo -i $ kubeadm init --kubernetes-version=v1.9.0 --pod-network-cidr=10.244.0.0/16 在这个过程中 kubeadm执行了一系列的操作,包括一些pre-check,生成ca证书,安装etcd和其它控制组件等。 界面差不多如下: 📷 最下面的这行 kubeadm join什么的,就是用来让别的node加入集群的,可以看出非常方便。我们要保存好这一行东西,这是我们之后让node加入集群的凭据,一会儿会用到。 这个时候,我们还不能通过 kubectl来控制集群,要让 kubectl可用,我们需要做: # 对于非root用户 $ mkdir -p $HOME/.kube $ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config $ sudo chown $(id -u):$(id -g) $HOME/.kube/config # 对于root用户 $ export KUBECONFIG=/etc/kubernetes/admin.conf # 也可以直接放到~/.bash_profile $ echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile 接下来要注意,我们必须自己来安装一个network addon。 network addon必须在任何app部署之前安装好。同样的,kube-dns也会在network addon安装好之后才启动。kubeadm只支持CNI-based networks(不支持kubenet)。 比较常见的network addon有: Calico, Canal, Flannel, Kube-router, Romana, WeaveNet等。这里我们使用 Flannel。 $ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml 安装完network之后,你可以通过 kubectlgetpods--all-namespaces来查看 kube-dns是否在running来判断network是否安装成功。 默认情况下,为了保证master的安全,master是不会被调度到app的。你可以取消这个限制通过输入: $ kubectl taint nodes --all node-role.kubernetes.io/master- 加入nodes 终于部署完了我们的master! 现在我们开始加入一些node到我们的集群里面吧! ssh到我们的node节点上,执行刚才下面给出的那个 kubeadm join的命令(每个人不同): $ sudo -i $ kubeadm join --token 72a8a4.2ed9076cd668b8b7 172.31.31.60:6443 --discovery-token-ca-cert-hash sha256:f0894e55d475f882dd40d52c6d01f758017ec5729be632294049f687330f60d2 输出差不多如下图: 📷 这时候,我们去master上输入 kubectlgetnodes查看一下: [root@i-071abd86ed304dc84 ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION i-071abd86ed304dc84 Ready master 12m v1.9.0 i-0c559ad3c0b16fd36 Ready <none> 1m v1.9.0 i-0f3f7462b0a004b5e Ready <none> 47s v1.9.0

如何入门小程序开发?

Hello World - 入门 在第一阶段,我们不需要了解小程序历史和技术细节,您只需要跟随我们完成基本的Hello World例子即可。 第一步 参考上一篇教程,下载微信开发者工具,并根据自己对应的操作系统进行安装。 第二步 打开微信开发者工具,选择新建小程序项目,我们先不需理解AppID的概念,新建项目时选择或使用测试号:小程序系统会给你分配测试账号,并取消勾选“建立普通快速启动模板”的选项,然后点击确定,如图。 📷 1540957519915 第三步 在根目录下创建app.json,然后填入如下代码。 { "pages": ["pages/index/index"] } 📷 1540957691677 在根目录下新建pages目录,然后在pages目录下新建index目录,接着在index目录下创建index.wxml,然后填入以下代码。 <text>Hello World</text> 📷 1540957824362 然后点击菜单栏的项目—保存,系统会自动创建index.js、index.json、index.wxss等目录文件,并进行编译,最终我们将看到小程序已经显示我们编写的代码Hello World文件。 📷 1540957897352 恭喜你,已经你已经成功开发出你的第一个小程序啦!这时,你在尝试修改修改index.wxml中的hello world,然后保存,看看会发生什么? 📷 1540958055009 Hello World - 小程序代码组成 在进阶实验前,我们先讲讲小程序的历史及上一步中配置文件的含义。 历史 从技术的维度看,小程序并非凭空冒出来的一个概念。2015年初,微信发布了一整套网页开发工具包,称之为 JS-SDK,开放了拍摄、语音识别、二维码等几十个API。给所有的 Web 开发者打开了一扇全新的窗户,让所有开发者都可以使用到微信的原生能力,去完成一些之前做不到或者难以做到的事情了。 但是在内部测试中,微信团队发现一些复杂的页面会有白屏的问题,例如页面加载了大量的 CSS 或者是 JavaScript 文件,这些文件的执行时间占用了大量的 UI 线程,除了白屏,影响 Web 体验的问题还有缺少操作的反馈,主要表现在页面切换的生硬和点击的迟滞感。微信面临的问题是如何设计一个比较好的系统,使得所有开发者在微信中都能获得比较好的体验。微信团队需要一个快速的加载、更强大的能力、原生的体验、易用且安全的微信数据开放、高效和简单的开发的系统,而这一系统就是本文中需要详细阐述的小程序。 配置文件含义 在上一步中,我们创建了一个app.json文件,还创建了一个index.wxml文件,系统还为我们创建了index.js、index.json、index.wxss等目录文件,接下来,将为大家阐述着几个文件到底是干什么的。为了更直观的展现。我们还是以Hello world为例。 第一步 - json文件 打开刚才的开发工具编辑器,然后在根目录下找到app.json文件,双击打开代码,然后用下面的代码进行替换。 { "pages": [ "pages/index/index", "pages/logs/logs" ], "window": { "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#fff", "navigationBarTitleText": "WeChat", "navigationBarTextStyle": "black" } } 📷 1540961534435 我们看到,当前界面发生了很大的变化,标题栏由原来的黑色变为了白色,在头部多了一个名为WeChat的字符,然后,我们更改navigationBarTitleText内的字符,将WeChat改为自己想设定的字符,我这里改为你自己想设定的字符,然后将原本的navigationBarBackgroundColor内部的#fff改为#ddd,然后保存,看看会发生什么。 📷 1540961900347 我们注意到,开发者工具刷新后,顶部的bar的文字由原来的Wechat变为了你自定义的字符,bar的颜色也发生了变化。 现在明白了吗?JSON文件在小程序代码中扮演静态配置的作用,在小程序运行之前就决定了小程序一些表现,需要注意的是小程序是无法在运行过程中去动态更新JSON 配置文件从而发生对应的变化的。 第二步 - wxml文件 打开入门中创建的index.wxml文件,使用下面的代码替换原有的代码。 <text>当前时间:{{time}}</text> 然后在打开系统创建的index.js文件,找到data: {}行,然后在大括号之间填入下面的代码,如图。 time: (new Date()).toString() 📷 1540962579971 接着,我们按下保存键,看看会发生什么。 📷 1540962612854 我们看到系统自动将{{time}}变成了当前的时间,那这里是如何实现的呢?原来,在小程序中,我们可以说使用JavaScript代码来通过Dom接口来完成界面的实时更新,WXML 通过 {{变量名}} 来绑定 WXML 文件和对应的 JavaScript 文件中的 data 对象属性。我们在index.js定义了当前时间的变量,然后通过WXML中的{{time}}去获取其中的变量。怎么样,大概明白WXML是干什么的了嘛?没明白?没事,我们进行在进行一个实验。 在index.wxml文件中,添加下面的代码。 <view> {{a + b}} + {{c}} = d</view> <view wx:if="{{c > 1}}"> True </view> 和刚才一样,在index.js内的data: {}行,插入以下代码。 time: (new Date()).toString(), a: 1, b: 2, c:3 📷 1540963650112 我们看到,系统已经将我们的a、b、c变量通过逻辑运算并渲染出来,同时,我们使用wx:if来判断数字c的值是否大于1,如果大于这展示True字符。 现在,大概明白WXML是干嘛的了嘛?我们先用官方文档说明下,WXML 全称是 WeiXin Markup Language,是小程序框架设计的一套标签语言,结合小程序的基础组件、事件系统,可以构建出页面的结构。是不是有点看不懂,没关系,我这介绍下,WXML是一种类似HTML超文本标记语言,可以描述你小程序前端展示的长相,可以将你的代码转换为展示页面,后续配合WXSS及JavaScript脚本,可以写出非常漂亮的小程序。 第三步、wxss文件 现在,打开你的index.wxss文件,然后输入下面的代码。 /* pages/index/index.wxss */ .text-red{ color: red } .text-blue{ color: blue } .text-yellow{ color: yellow } 然后,打开index.wxml文件,使用下面的代码替换所有文件 <text class='text-red'>当前时间:{{time}}</text> <view class='text-blue'> {{a + b}} + {{c}} = d</view> <view class='text-yellow' wx:if="{{c > 1}}"> True </view> 保存后看看效果。 📷 1540966942446 我们看到,原来显示为黑色的小程序的字变色为红色、蓝色、黄色。这里改变的颜色刚好与我们编辑index.wxss文件中指定的颜色相同。所以,你明白wxss文件是干什么的了嘛?对的,WXSS与Web开发中的CSS类似。为了更适合小程序开发,WXSS对CSS做了一些补充以及修改。WXSS(WeiXin Style Sheets)是一套用于小程序的样式语言,用于描述WXML的组件样式,也就是视觉上的效果。 第四步、js文件 js文件使用我们已经在第二步中体验过了,小程序的主要开发语言是 JavaScript ,开发者使用 JavaScript 来开发业务逻辑以及调用小程序的 API 来完成业务需求。但是,严格的意义上来说,小程序中 JavaScript 的同浏览器中的 JavaScript 以及 NodeJS 中的 JavaScript 是不相同的。 浏览器中的JavaScript 是由 ECMAScript 和 BOM(浏览器对象模型)以及 DOM(文档对象模型)组成的,Web前端开发者会很熟悉这两个对象模型,它使得开发者可以去操作浏览器的一些表现,比如修改URL、修改页面呈现、记录数据等等。 NodeJS中的JavaScript 是由 ECMAScript 和 NPM以及Native模块组成,NodeJS的开发者会非常熟悉 NPM 的包管理系统,通过各种拓展包来快速的实现一些功能,同时通过使用一些原生的模块例如 FS、HTTP、OS等等来拥有一些语言本身所不具有的能力。 小程序中的 JavaScript 是由ECMAScript 以及小程序框架和小程序 API 来实现的。同浏览器中的JavaScript 相比没有 BOM 以及 DOM 对象,所以类似 JQuery、Zepto这种浏览器类库是无法在小程序中运行起来的,同样的缺少 Native 模块和NPM包管理的机制,小程序中无法加载原生库,也无法直接使用大部分的 NPM 包。 明白了小程序中的 JavaScript 同浏览器以及NodeJS有所不同后,开发者还需要注意到另外一个问题,不同的平台的小程序的脚本执行环境也是有所区别的。 小程序目前可以运行在三大平台: iOS平台,包括iOS9、iOS10、iOS11 Android平台 小程序IDE 这种区别主要是体现三大平台实现的 ECMAScript 的标准有所不同。截止到当前一共有七个版本的ECMAScript 标准,目前开发者大部分使用的是 ECMAScript 5 和 ECMAScript 6 的标准,但是在小程序中, iOS9和iOS10 所使用的运行环境并没有完全的兼容到 ECMAScript 6 标准,一些 ECMAScript 6 中规定的语法和关键字是没有的或者同标准是有所不同的,所以一些开发者会发现有些代码在旧的手机操作系统上出现一些语法错误。为了帮助开发者解决这类问题,小程序IDE提供语法转码工具帮助开发者,将 ECMAScript 6代码转为 ECMAScript 5代码,从而在所有的环境都能得到很好的执行。开发者需要在项目设置中,勾选 ES6 转 ES5 开启此功能。 📷 Hello World - 小程序的能力 在上一个步骤中,我们已经熟悉了小程序的组成及代码布局,这一步,我们将介绍小程序的部分能力,组件及API。和以前一样,我们通过Hello world来进行学习。 小程序的组件与API 我们打开小程序代码组成步骤中的index.wxml文件,然后在以前的代码中,加入下面的代码。 <camera device-position="front" flash="auto" binderror="error" style="width: 100%; height: 300px;"></camera> <button type="primary" bindtap="takePhoto">拍照</button> <view class='text-red'>预览</view> <image mode="widthFix" src="{{src}}"></image> 然后打开index.js文件,在page({后面加入下述代码,如图。 takePhoto() { const ctx = wx.createCameraContext() ctx.takePhoto({ quality: 'high', success: (res) => { this.setData({ src: res.tempImagePath }) } }) }, error(e) { console.log(e.detail) } }) 📷 1540969148552 然后,在你的根目录下创建一个名为app.js的文件,什么内容暂时都不要填写,保存。接下来,我们点击菜单栏的预览按钮,然后用手机扫描弹出的二维码,即可使用手机进行拍照,拍照弹出的照片将附在预览字符下方。 📷 1540969494583 预览效果如图 📷 我们看到,小程序已经能够正常拍照了。那么有同学有疑问了,这里的代码到底做了什么呢?接下来,我将对其解释。 组件 在上面的教程中,我们调用了下面这段代码。 <camera device-position="front" flash="auto" binderror="error" style="width: 100%; height: 300px;"></camera> <button type="primary" bindtap="takePhoto">拍照</button> <view class='text-red'>预览</view> <image mode="widthFix" src="{{src}}"></image> 先不管其他内容,我们主要看看<camera ....... </camera>中间代码的含义。我们看到我们定义了device-position、flash、binderror、style这几个属性。那么这几个属性到底是什么意思呢?我们可以看看官方组件文档,找到camera组件,会看到如下表的信息。 属性名 类型 默认值说明 最低版本 mode String normal有效值为 normal, scanCode 2.1.0device-positionString back 前置或后置,值为front, back flash String auto 闪光灯,值为auto, on, off bindstop EventHandle摄像头在非正常终止时触发,如退出后台等情况 binderror EventHandle用户不允许使用摄像头时触发 bindscancode EventHandle在成功识别到一维码时触发,仅在 mode="scanCode" 时生效2.1.0 我们看到,表中刚好有我们定义的device-position、flash、binderror这几个内容,原来device-position我们设置的front是选择前置摄像头还是后置摄像头,binderror是显示用户不允许使用摄像头会触发的事件。flash是当前选择是否打开闪光灯,这里我们设置的是auto也就是自动状态。style我们可以暂时不用在意,这里指的是上一步中wxss应该写的内容,我们只是写在了wxml文件中。 我们看到,组件是小程序的一个很重要的功能,组件是小程序的基本组成单元,为了让开发者可以快速进行开发,小程序的宿主环境提供了一系列基础组件。我们刚才使用的camera组件,就是官方提供调用系统底层相机的组件。代码中所展示的button、view、image都是一种组件。 限于篇幅,我们不在本文展开所有组件的属性说明,请在使用时前往官方文档进行查阅相关组件说明https://developers.weixin.qq.com/miniprogram/dev/component/。 API 在上文中,我们其实已经调用了官方的api,不信?我们看看下面的代码。 takePhoto() { const ctx = wx.createCameraContext() ctx.takePhoto({ quality: 'high', success: (res) => { this.setData({ src: res.tempImagePath }) } }) }, error(e) { console.log(e.detail) } }) 熟悉吧,这段代码中,我们已经调用了微信官方给出的wx.createCameraContext(),API文件。关于此API的详细使用,可以参考官方API文档。 在这段代码中,我们首先使用const ctx = wx.createCameraContext()这段代码来将wx.createCameraContext()定义为ctx。然后使用ctx.takePhoto调用takePhoto方法进行拍照。关于takePhoto方法的使用,大家可以参考官方文档。我们在代码中定义了quality、success这两个函数。文档中指出,quality指定的是成像质量,我们选择high高质量。success是回调函数,最终存放我们的照片文件。这里存放的是tempImagePath照片文件的临时路径。 然后,我们在index.wxml的button调用index.js中的takePhoto函数。然后在image中调用scr变量做展示。 小程序发布 为了保证小程序的质量,以及符合相关的规范,小程序的发布是需要经过审核的。建议先自行审核,自审完成之后,我们就可以对其进行上传啦。值得注意的是,如果你需要发布,请将这个小程序的AppID改为你在小程序管理页面注册的AppID,点击微信开发者工具的详情,然后修改AppID为你的AppID即可。 📷 1540973253232 打开微信开发者工具,然就点击菜单栏的工具按钮,再点击上传按钮。 📷 1540972890902 在新弹出的页面中,我们设置好版本号及项目备注。 📷 1540972951445 然后点击上传即可。之后,请打开你微信公众平台小程序管理页面,对小程序进行审核发布。 📷 1540973360470 之后的页面中,点击开发版本,然后再点击提交审核,审核通过后,你的小程序就可以上线了!... 展开详请
Hello World - 入门 在第一阶段,我们不需要了解小程序历史和技术细节,您只需要跟随我们完成基本的Hello World例子即可。 第一步 参考上一篇教程,下载微信开发者工具,并根据自己对应的操作系统进行安装。 第二步 打开微信开发者工具,选择新建小程序项目,我们先不需理解AppID的概念,新建项目时选择或使用测试号:小程序系统会给你分配测试账号,并取消勾选“建立普通快速启动模板”的选项,然后点击确定,如图。 📷 1540957519915 第三步 在根目录下创建app.json,然后填入如下代码。 { "pages": ["pages/index/index"] } 📷 1540957691677 在根目录下新建pages目录,然后在pages目录下新建index目录,接着在index目录下创建index.wxml,然后填入以下代码。 <text>Hello World</text> 📷 1540957824362 然后点击菜单栏的项目—保存,系统会自动创建index.js、index.json、index.wxss等目录文件,并进行编译,最终我们将看到小程序已经显示我们编写的代码Hello World文件。 📷 1540957897352 恭喜你,已经你已经成功开发出你的第一个小程序啦!这时,你在尝试修改修改index.wxml中的hello world,然后保存,看看会发生什么? 📷 1540958055009 Hello World - 小程序代码组成 在进阶实验前,我们先讲讲小程序的历史及上一步中配置文件的含义。 历史 从技术的维度看,小程序并非凭空冒出来的一个概念。2015年初,微信发布了一整套网页开发工具包,称之为 JS-SDK,开放了拍摄、语音识别、二维码等几十个API。给所有的 Web 开发者打开了一扇全新的窗户,让所有开发者都可以使用到微信的原生能力,去完成一些之前做不到或者难以做到的事情了。 但是在内部测试中,微信团队发现一些复杂的页面会有白屏的问题,例如页面加载了大量的 CSS 或者是 JavaScript 文件,这些文件的执行时间占用了大量的 UI 线程,除了白屏,影响 Web 体验的问题还有缺少操作的反馈,主要表现在页面切换的生硬和点击的迟滞感。微信面临的问题是如何设计一个比较好的系统,使得所有开发者在微信中都能获得比较好的体验。微信团队需要一个快速的加载、更强大的能力、原生的体验、易用且安全的微信数据开放、高效和简单的开发的系统,而这一系统就是本文中需要详细阐述的小程序。 配置文件含义 在上一步中,我们创建了一个app.json文件,还创建了一个index.wxml文件,系统还为我们创建了index.js、index.json、index.wxss等目录文件,接下来,将为大家阐述着几个文件到底是干什么的。为了更直观的展现。我们还是以Hello world为例。 第一步 - json文件 打开刚才的开发工具编辑器,然后在根目录下找到app.json文件,双击打开代码,然后用下面的代码进行替换。 { "pages": [ "pages/index/index", "pages/logs/logs" ], "window": { "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#fff", "navigationBarTitleText": "WeChat", "navigationBarTextStyle": "black" } } 📷 1540961534435 我们看到,当前界面发生了很大的变化,标题栏由原来的黑色变为了白色,在头部多了一个名为WeChat的字符,然后,我们更改navigationBarTitleText内的字符,将WeChat改为自己想设定的字符,我这里改为你自己想设定的字符,然后将原本的navigationBarBackgroundColor内部的#fff改为#ddd,然后保存,看看会发生什么。 📷 1540961900347 我们注意到,开发者工具刷新后,顶部的bar的文字由原来的Wechat变为了你自定义的字符,bar的颜色也发生了变化。 现在明白了吗?JSON文件在小程序代码中扮演静态配置的作用,在小程序运行之前就决定了小程序一些表现,需要注意的是小程序是无法在运行过程中去动态更新JSON 配置文件从而发生对应的变化的。 第二步 - wxml文件 打开入门中创建的index.wxml文件,使用下面的代码替换原有的代码。 <text>当前时间:{{time}}</text> 然后在打开系统创建的index.js文件,找到data: {}行,然后在大括号之间填入下面的代码,如图。 time: (new Date()).toString() 📷 1540962579971 接着,我们按下保存键,看看会发生什么。 📷 1540962612854 我们看到系统自动将{{time}}变成了当前的时间,那这里是如何实现的呢?原来,在小程序中,我们可以说使用JavaScript代码来通过Dom接口来完成界面的实时更新,WXML 通过 {{变量名}} 来绑定 WXML 文件和对应的 JavaScript 文件中的 data 对象属性。我们在index.js定义了当前时间的变量,然后通过WXML中的{{time}}去获取其中的变量。怎么样,大概明白WXML是干什么的了嘛?没明白?没事,我们进行在进行一个实验。 在index.wxml文件中,添加下面的代码。 <view> {{a + b}} + {{c}} = d</view> <view wx:if="{{c > 1}}"> True </view> 和刚才一样,在index.js内的data: {}行,插入以下代码。 time: (new Date()).toString(), a: 1, b: 2, c:3 📷 1540963650112 我们看到,系统已经将我们的a、b、c变量通过逻辑运算并渲染出来,同时,我们使用wx:if来判断数字c的值是否大于1,如果大于这展示True字符。 现在,大概明白WXML是干嘛的了嘛?我们先用官方文档说明下,WXML 全称是 WeiXin Markup Language,是小程序框架设计的一套标签语言,结合小程序的基础组件、事件系统,可以构建出页面的结构。是不是有点看不懂,没关系,我这介绍下,WXML是一种类似HTML超文本标记语言,可以描述你小程序前端展示的长相,可以将你的代码转换为展示页面,后续配合WXSS及JavaScript脚本,可以写出非常漂亮的小程序。 第三步、wxss文件 现在,打开你的index.wxss文件,然后输入下面的代码。 /* pages/index/index.wxss */ .text-red{ color: red } .text-blue{ color: blue } .text-yellow{ color: yellow } 然后,打开index.wxml文件,使用下面的代码替换所有文件 <text class='text-red'>当前时间:{{time}}</text> <view class='text-blue'> {{a + b}} + {{c}} = d</view> <view class='text-yellow' wx:if="{{c > 1}}"> True </view> 保存后看看效果。 📷 1540966942446 我们看到,原来显示为黑色的小程序的字变色为红色、蓝色、黄色。这里改变的颜色刚好与我们编辑index.wxss文件中指定的颜色相同。所以,你明白wxss文件是干什么的了嘛?对的,WXSS与Web开发中的CSS类似。为了更适合小程序开发,WXSS对CSS做了一些补充以及修改。WXSS(WeiXin Style Sheets)是一套用于小程序的样式语言,用于描述WXML的组件样式,也就是视觉上的效果。 第四步、js文件 js文件使用我们已经在第二步中体验过了,小程序的主要开发语言是 JavaScript ,开发者使用 JavaScript 来开发业务逻辑以及调用小程序的 API 来完成业务需求。但是,严格的意义上来说,小程序中 JavaScript 的同浏览器中的 JavaScript 以及 NodeJS 中的 JavaScript 是不相同的。 浏览器中的JavaScript 是由 ECMAScript 和 BOM(浏览器对象模型)以及 DOM(文档对象模型)组成的,Web前端开发者会很熟悉这两个对象模型,它使得开发者可以去操作浏览器的一些表现,比如修改URL、修改页面呈现、记录数据等等。 NodeJS中的JavaScript 是由 ECMAScript 和 NPM以及Native模块组成,NodeJS的开发者会非常熟悉 NPM 的包管理系统,通过各种拓展包来快速的实现一些功能,同时通过使用一些原生的模块例如 FS、HTTP、OS等等来拥有一些语言本身所不具有的能力。 小程序中的 JavaScript 是由ECMAScript 以及小程序框架和小程序 API 来实现的。同浏览器中的JavaScript 相比没有 BOM 以及 DOM 对象,所以类似 JQuery、Zepto这种浏览器类库是无法在小程序中运行起来的,同样的缺少 Native 模块和NPM包管理的机制,小程序中无法加载原生库,也无法直接使用大部分的 NPM 包。 明白了小程序中的 JavaScript 同浏览器以及NodeJS有所不同后,开发者还需要注意到另外一个问题,不同的平台的小程序的脚本执行环境也是有所区别的。 小程序目前可以运行在三大平台: iOS平台,包括iOS9、iOS10、iOS11 Android平台 小程序IDE 这种区别主要是体现三大平台实现的 ECMAScript 的标准有所不同。截止到当前一共有七个版本的ECMAScript 标准,目前开发者大部分使用的是 ECMAScript 5 和 ECMAScript 6 的标准,但是在小程序中, iOS9和iOS10 所使用的运行环境并没有完全的兼容到 ECMAScript 6 标准,一些 ECMAScript 6 中规定的语法和关键字是没有的或者同标准是有所不同的,所以一些开发者会发现有些代码在旧的手机操作系统上出现一些语法错误。为了帮助开发者解决这类问题,小程序IDE提供语法转码工具帮助开发者,将 ECMAScript 6代码转为 ECMAScript 5代码,从而在所有的环境都能得到很好的执行。开发者需要在项目设置中,勾选 ES6 转 ES5 开启此功能。 📷 Hello World - 小程序的能力 在上一个步骤中,我们已经熟悉了小程序的组成及代码布局,这一步,我们将介绍小程序的部分能力,组件及API。和以前一样,我们通过Hello world来进行学习。 小程序的组件与API 我们打开小程序代码组成步骤中的index.wxml文件,然后在以前的代码中,加入下面的代码。 <camera device-position="front" flash="auto" binderror="error" style="width: 100%; height: 300px;"></camera> <button type="primary" bindtap="takePhoto">拍照</button> <view class='text-red'>预览</view> <image mode="widthFix" src="{{src}}"></image> 然后打开index.js文件,在page({后面加入下述代码,如图。 takePhoto() { const ctx = wx.createCameraContext() ctx.takePhoto({ quality: 'high', success: (res) => { this.setData({ src: res.tempImagePath }) } }) }, error(e) { console.log(e.detail) } }) 📷 1540969148552 然后,在你的根目录下创建一个名为app.js的文件,什么内容暂时都不要填写,保存。接下来,我们点击菜单栏的预览按钮,然后用手机扫描弹出的二维码,即可使用手机进行拍照,拍照弹出的照片将附在预览字符下方。 📷 1540969494583 预览效果如图 📷 我们看到,小程序已经能够正常拍照了。那么有同学有疑问了,这里的代码到底做了什么呢?接下来,我将对其解释。 组件 在上面的教程中,我们调用了下面这段代码。 <camera device-position="front" flash="auto" binderror="error" style="width: 100%; height: 300px;"></camera> <button type="primary" bindtap="takePhoto">拍照</button> <view class='text-red'>预览</view> <image mode="widthFix" src="{{src}}"></image> 先不管其他内容,我们主要看看<camera ....... </camera>中间代码的含义。我们看到我们定义了device-position、flash、binderror、style这几个属性。那么这几个属性到底是什么意思呢?我们可以看看官方组件文档,找到camera组件,会看到如下表的信息。 属性名 类型 默认值说明 最低版本 mode String normal有效值为 normal, scanCode 2.1.0device-positionString back 前置或后置,值为front, back flash String auto 闪光灯,值为auto, on, off bindstop EventHandle摄像头在非正常终止时触发,如退出后台等情况 binderror EventHandle用户不允许使用摄像头时触发 bindscancode EventHandle在成功识别到一维码时触发,仅在 mode="scanCode" 时生效2.1.0 我们看到,表中刚好有我们定义的device-position、flash、binderror这几个内容,原来device-position我们设置的front是选择前置摄像头还是后置摄像头,binderror是显示用户不允许使用摄像头会触发的事件。flash是当前选择是否打开闪光灯,这里我们设置的是auto也就是自动状态。style我们可以暂时不用在意,这里指的是上一步中wxss应该写的内容,我们只是写在了wxml文件中。 我们看到,组件是小程序的一个很重要的功能,组件是小程序的基本组成单元,为了让开发者可以快速进行开发,小程序的宿主环境提供了一系列基础组件。我们刚才使用的camera组件,就是官方提供调用系统底层相机的组件。代码中所展示的button、view、image都是一种组件。 限于篇幅,我们不在本文展开所有组件的属性说明,请在使用时前往官方文档进行查阅相关组件说明https://developers.weixin.qq.com/miniprogram/dev/component/。 API 在上文中,我们其实已经调用了官方的api,不信?我们看看下面的代码。 takePhoto() { const ctx = wx.createCameraContext() ctx.takePhoto({ quality: 'high', success: (res) => { this.setData({ src: res.tempImagePath }) } }) }, error(e) { console.log(e.detail) } }) 熟悉吧,这段代码中,我们已经调用了微信官方给出的wx.createCameraContext(),API文件。关于此API的详细使用,可以参考官方API文档。 在这段代码中,我们首先使用const ctx = wx.createCameraContext()这段代码来将wx.createCameraContext()定义为ctx。然后使用ctx.takePhoto调用takePhoto方法进行拍照。关于takePhoto方法的使用,大家可以参考官方文档。我们在代码中定义了quality、success这两个函数。文档中指出,quality指定的是成像质量,我们选择high高质量。success是回调函数,最终存放我们的照片文件。这里存放的是tempImagePath照片文件的临时路径。 然后,我们在index.wxml的button调用index.js中的takePhoto函数。然后在image中调用scr变量做展示。 小程序发布 为了保证小程序的质量,以及符合相关的规范,小程序的发布是需要经过审核的。建议先自行审核,自审完成之后,我们就可以对其进行上传啦。值得注意的是,如果你需要发布,请将这个小程序的AppID改为你在小程序管理页面注册的AppID,点击微信开发者工具的详情,然后修改AppID为你的AppID即可。 📷 1540973253232 打开微信开发者工具,然就点击菜单栏的工具按钮,再点击上传按钮。 📷 1540972890902 在新弹出的页面中,我们设置好版本号及项目备注。 📷 1540972951445 然后点击上传即可。之后,请打开你微信公众平台小程序管理页面,对小程序进行审核发布。 📷 1540973360470 之后的页面中,点击开发版本,然后再点击提交审核,审核通过后,你的小程序就可以上线了!

腾讯云的实时语音趣味变声是如何实现的呢?有哪些应用场景呢?

腾讯云游戏多媒体引擎GME创新性地引入了变声的玩法,让变声成为了游戏内置的功能。只要接入GME的SDK,游戏研发厂商就可以提供给玩家更加丰富有趣的游戏内语音体验,让玩家在不借助任何外部设备的情况下,实现抠脚大汉变声萝莉、变声口吃的的有趣玩法。 目前,腾讯云GME的这个变声功能已应用在手机QQ上,被亿万QQ用户所使用。用户在拨通QQ电话或者发送语音消息时,选择 “变声”,就可以在“萝莉”、“歪果仁”、“熊孩子”等数十种特色音效中自由切换。 年轻人追求个性,喜欢猎奇。手机QQ这个变声功能帮助用户展现自己的“多面人格”,让聊天更有趣,广受用户好评。 📷 📷 用户使用反馈... 展开详请

请问一下 Gvoice录音时大小始终为0, 检查了路径是对的, 给的是全路径,还有其他的原因吗?

无畏魂者如果对生活没有动力,那和三和大神有几分差别

如何实现基于用户画像大数据的电商防刷架构?

problemQuants
大数据一直在安全对抗领域发挥着重要的作用,从我们的对抗经验来看,大数据不仅仅是数据规模很大,而且还包括两个方面: 数据广度:要有丰富的数据类型。比如,不仅仅要有社交领域的数据、还要有游戏、支付、自媒体等领域的数据,这样就提供了一个广阔的视野让我们来看待黑产的行为特点。 数据深度:黑产的对抗。我们一直强调纵深防御,我们不仅仅要有注册数据,还要有登录,以及账号的使用的数据,这样我们才能更好的识别恶意。 所以想要做风控和大数据的团队,一定要注意在自己的产品上多埋点,拿到足够多的数据,先沉淀下来。 腾讯大数据处理平台团队研发了一个叫魔方的大数据处理和分析的平台,底层我们集成了MySQL、MongoDB,Spark、Hadoop等技术,在用户层面我们只需要写一些简单的SQL语句、完成一些配置就可以实现例行分析。 这里我们收集了社交、电商、支付、游戏等场景的数据,针对这些数据我们建立一些模型,发现哪些是恶意的数据,并且将数据沉淀下来。 沉淀下来的对安全有意义的数据,一方面就存储在魔方平台上,供线下审计做模型使用;另一方面会做成实时的服务,提供给线上的系统查询使用。 一.腾讯用户画像沉淀方法 画像,本质上就是给账号、设备等打标签。 用户画像 = 打标签 我们这里主要从安全的角度出发来打标签,比如IP画像,我们会标注IP是不是代理IP,这些对我们做策略是有帮助的。 以QQ的画像为例,比如,一个QQ只登录IM、不登录其他腾讯的业务、不聊天、频繁的加好友、被好友删除、QQ空间要么没开通、要么开通了QQ空间但是评论多但回复少,这种号码我们一般会标注QQ养号(色情、营销),类似的我们也会给QQ打上其他标签。 标签的类别和明细,需要做风控的人自己去设定,比如:地理位置,按省份标记。性别,安男女标记。其他细致规则以此规律自己去设定。 我们看看腾讯的IP画像,沉淀的逻辑如下图: 📷 一般的业务都有针对IP的频率、次数限制的策略,那么黑产为了对抗,必然会大量采用代理IP来绕过限制。 既然代理IP的识别如此重要,那我们就以代理IP为例来谈下腾讯识别代理IP的过程。 识别一个IP是不是代理IP,技术不外乎就是如下四种: 反向探测技术:扫描IP是不是开通了80,8080等代理服务器经常开通的端口,显然一个普通的用户IP不太可能开通如上的端口。 HTTP头部的X_Forwarded_For:开通了HTTP代理的IP可以通过此法来识别是不是代理IP;如果带有XFF信息,该IP是代理IP无疑。 Keep-alive报文:如果带有Proxy-Connection的Keep-alive报文,该IP毫无疑问是代理IP。 查看IP上端口:如果一个IP有的端口大于10000,那么该IP大多也存在问题,普通的家庭IP开这么大的端口几乎是不可能的。 以上代理IP检测的方法几乎都是公开的,但是盲目去扫描全网的IP,被拦截不说,效率也是一个很大的问题。 因此,我们的除了利用网络爬虫爬取代理IP外,还利用如下办法来加快代理IP的收集:通过业务建模,收集恶意IP(黑产使用代理IP的可能性比较大)然后再通过协议扫描的方式来判断这些IP是不是代理IP。每天腾讯都能发现千万级别的恶意IP,其中大部分还是代理IP。 二.腾讯用户画像类别概览 📷 三.防御逻辑 📷 实时系统使用C/C++开发实现,所有的数据通过共享内存的方式进行存储,相比其他的系统,安全系统更有他自己特殊的情况,因此这里我们可以使用“有损”的思路来实现,大大降低了开发成本和难度。 数据一致性,多台机器,使用共享内存,如何保障数据一致性? 其实,安全策略不需要做到强数据一致性。 从安全本身的角度看,风险本身就是一个概率值,不确定,所以有一点数据不一致,不影响全局。 但是安全系统也有自己的特点,安全系统一般突发流量比较大,我们这里就需要设置各种应急开关,而且需要微信号、短信等方式方便快速切换,避免将影响扩散到后端系统。 四.接入系统 📷 📷 适应的场景包括: 电商o2o刷单、刷券、刷红包 防止虚假账号注册 防止用户名、密码被撞库 防止恶意登录... 展开详请
大数据一直在安全对抗领域发挥着重要的作用,从我们的对抗经验来看,大数据不仅仅是数据规模很大,而且还包括两个方面: 数据广度:要有丰富的数据类型。比如,不仅仅要有社交领域的数据、还要有游戏、支付、自媒体等领域的数据,这样就提供了一个广阔的视野让我们来看待黑产的行为特点。 数据深度:黑产的对抗。我们一直强调纵深防御,我们不仅仅要有注册数据,还要有登录,以及账号的使用的数据,这样我们才能更好的识别恶意。 所以想要做风控和大数据的团队,一定要注意在自己的产品上多埋点,拿到足够多的数据,先沉淀下来。 腾讯大数据处理平台团队研发了一个叫魔方的大数据处理和分析的平台,底层我们集成了MySQL、MongoDB,Spark、Hadoop等技术,在用户层面我们只需要写一些简单的SQL语句、完成一些配置就可以实现例行分析。 这里我们收集了社交、电商、支付、游戏等场景的数据,针对这些数据我们建立一些模型,发现哪些是恶意的数据,并且将数据沉淀下来。 沉淀下来的对安全有意义的数据,一方面就存储在魔方平台上,供线下审计做模型使用;另一方面会做成实时的服务,提供给线上的系统查询使用。 一.腾讯用户画像沉淀方法 画像,本质上就是给账号、设备等打标签。 用户画像 = 打标签 我们这里主要从安全的角度出发来打标签,比如IP画像,我们会标注IP是不是代理IP,这些对我们做策略是有帮助的。 以QQ的画像为例,比如,一个QQ只登录IM、不登录其他腾讯的业务、不聊天、频繁的加好友、被好友删除、QQ空间要么没开通、要么开通了QQ空间但是评论多但回复少,这种号码我们一般会标注QQ养号(色情、营销),类似的我们也会给QQ打上其他标签。 标签的类别和明细,需要做风控的人自己去设定,比如:地理位置,按省份标记。性别,安男女标记。其他细致规则以此规律自己去设定。 我们看看腾讯的IP画像,沉淀的逻辑如下图: 📷 一般的业务都有针对IP的频率、次数限制的策略,那么黑产为了对抗,必然会大量采用代理IP来绕过限制。 既然代理IP的识别如此重要,那我们就以代理IP为例来谈下腾讯识别代理IP的过程。 识别一个IP是不是代理IP,技术不外乎就是如下四种: 反向探测技术:扫描IP是不是开通了80,8080等代理服务器经常开通的端口,显然一个普通的用户IP不太可能开通如上的端口。 HTTP头部的X_Forwarded_For:开通了HTTP代理的IP可以通过此法来识别是不是代理IP;如果带有XFF信息,该IP是代理IP无疑。 Keep-alive报文:如果带有Proxy-Connection的Keep-alive报文,该IP毫无疑问是代理IP。 查看IP上端口:如果一个IP有的端口大于10000,那么该IP大多也存在问题,普通的家庭IP开这么大的端口几乎是不可能的。 以上代理IP检测的方法几乎都是公开的,但是盲目去扫描全网的IP,被拦截不说,效率也是一个很大的问题。 因此,我们的除了利用网络爬虫爬取代理IP外,还利用如下办法来加快代理IP的收集:通过业务建模,收集恶意IP(黑产使用代理IP的可能性比较大)然后再通过协议扫描的方式来判断这些IP是不是代理IP。每天腾讯都能发现千万级别的恶意IP,其中大部分还是代理IP。 二.腾讯用户画像类别概览 📷 三.防御逻辑 📷 实时系统使用C/C++开发实现,所有的数据通过共享内存的方式进行存储,相比其他的系统,安全系统更有他自己特殊的情况,因此这里我们可以使用“有损”的思路来实现,大大降低了开发成本和难度。 数据一致性,多台机器,使用共享内存,如何保障数据一致性? 其实,安全策略不需要做到强数据一致性。 从安全本身的角度看,风险本身就是一个概率值,不确定,所以有一点数据不一致,不影响全局。 但是安全系统也有自己的特点,安全系统一般突发流量比较大,我们这里就需要设置各种应急开关,而且需要微信号、短信等方式方便快速切换,避免将影响扩散到后端系统。 四.接入系统 📷 📷 适应的场景包括: 电商o2o刷单、刷券、刷红包 防止虚假账号注册 防止用户名、密码被撞库 防止恶意登录

如何借助云服务降低金融欺诈风险?

借助反欺诈服务(AntiFraud)主要应用于银行、证券、保险、P2P 等金融行业客户,通过腾讯的智慧风控能力,可以准确识别恶意用户与行为,帮助解决在支付、借贷、理财、风控等业务环节遇到的欺诈威胁,降低企业的损失。 借助反欺诈服务有4个功能:包括 贷前检测,贷后监控,黑产情报,风险分析。 贷前检测:在用户申请借贷时发起检测,精准识别虚假信息申请、冒用身份申请、高危用户申请、机构代办、多头借贷、组团骗贷等互联网金融风险,帮助用户提升反欺诈识别能力。支持对手机号、银行卡、设备、邮箱等信息的检测,产品输出风险欺诈分及风险详情。 贷后监控:用户只需定期发起对存量用户的检测,便可以及时发现跨平台逾期、多头借贷、用户异动等风险,以便重新对借贷人加大催收关注度,减少逾期坏账概率。 黑产情报:腾讯与互联网黑产对抗多年,积累了丰富情报收集和自动学习能力。天御的黑产情报雷达系统能够全面掌握互联网金融黑产的行为特点、从业人员规模、团伙地域化分布以及专业化工具等情况,使得天御反欺诈服务全面掌握黑产特点,并作出针对性的打击策略。 风险分析:用户可以查询平台的风险情况,包括对各类型风险事件的分布和趋势分析。 通过四项功能的联合发力,大大提升了金融投资的安全性。 ... 展开详请
借助反欺诈服务(AntiFraud)主要应用于银行、证券、保险、P2P 等金融行业客户,通过腾讯的智慧风控能力,可以准确识别恶意用户与行为,帮助解决在支付、借贷、理财、风控等业务环节遇到的欺诈威胁,降低企业的损失。 借助反欺诈服务有4个功能:包括 贷前检测,贷后监控,黑产情报,风险分析。 贷前检测:在用户申请借贷时发起检测,精准识别虚假信息申请、冒用身份申请、高危用户申请、机构代办、多头借贷、组团骗贷等互联网金融风险,帮助用户提升反欺诈识别能力。支持对手机号、银行卡、设备、邮箱等信息的检测,产品输出风险欺诈分及风险详情。 贷后监控:用户只需定期发起对存量用户的检测,便可以及时发现跨平台逾期、多头借贷、用户异动等风险,以便重新对借贷人加大催收关注度,减少逾期坏账概率。 黑产情报:腾讯与互联网黑产对抗多年,积累了丰富情报收集和自动学习能力。天御的黑产情报雷达系统能够全面掌握互联网金融黑产的行为特点、从业人员规模、团伙地域化分布以及专业化工具等情况,使得天御反欺诈服务全面掌握黑产特点,并作出针对性的打击策略。 风险分析:用户可以查询平台的风险情况,包括对各类型风险事件的分布和趋势分析。 通过四项功能的联合发力,大大提升了金融投资的安全性。

如何用大数据构建用户画像?

那一年淡然Java研发工程师
用户画像的标签有以下几个维度: 1、自然特征/基本属性 如性别、年龄、体形、地域、职业、教育程度等 2、消费特征/购买能力:如婚否、收入、车、房、孩子、购物类型、品牌偏好、信用水平、购买周期等 3、社会特征/行为特征:如婚姻状况、家庭构成、社交偏好、信息渠道等 4、兴趣特征/心理特征:如兴趣爱好、使用APP行为、浏览收藏内容、互动内容等 了解了自己产品目标客户的具体特征,才能够投其所好,根据消费者的具体特征,为企业营造有特色的营销场景,让自己的品牌快速的被消费者记住,有了用户画像,你的产品定位、品牌定位、商品包装、营销渠道等才能被确定。 所以“用户画像”现在是最聚焦用户的一种理念,帮助你快速在纷繁复杂的市场中瞄准用户,去下功夫。... 展开详请

云计算实现中虚拟化技术是如何运用的?

虚拟化技术是指计算元件在虚拟的基础上而不是真实的基础上运行,它可以扩大硬件的容量,简化软件的重新配置过程,减少软件虚拟机相关开销和支持更广泛的操作系统方面。通过虚拟化技术可实现软件应用与底层硬件相隔离,它包括将单个资源划分成多个虚拟资源的裂分模式,也包括将多个资源整合成一个虚拟资源的聚合模式。虚拟化技术根据对象可分成存储虚拟化、计算虚拟化、网络虚拟化等,计算虚拟化又分为系统级虚拟化、应用级虚拟化和桌面虚拟化目。在云计算实现中。计算系统虚拟化是一切建立在“云”上的服务与应用的基础。虚拟化技术目前主要应用在CPU、操作系统、服务器等多个方面,是提高服务效率的最佳解决方案。 ... 展开详请

腾讯云是如何保障客用户安全的?

楼主石乐志崇文尚武推理极工
现在的互联网都强调“生态”发展,在生态中,腾讯云通过参与制定行业和国家标准,与业界领先的厂商进行合作,横向拓展腾讯云在各方面的安全能力。腾讯云着重与认可的专业厂商进行深度的安全功能集成与服务整合,以完善与强化云端与客户端的安全功能。此外,腾讯云更以云服务市场的形式提供安全合作伙伴的产品和服务。目前,该服务市场中已上架了丰富的安全产品和解决方案供客户选择使用,包括众多行业内优秀的安全产品如:V**、加密机、入侵检测、数据防泄密、UTM、堡垒机、日志审计、数据库安全审计等。腾讯一系列的“生态”产品业务都用到了腾讯云的安全防护,许多云用户也如此。 ... 展开详请

你好,请问有没有详细的ILiveSDK文档说明呢?

领券