阿里云 SLS 数据加工中使用 Python 数据编码

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 数据编码在大数据处理的基础操作,本文讨论了 Python3 中的数据编码方案,以及在 SLS 数据加工中内置的数据编解码函数使用。

引文

数据编码是互联网上计算机之间交流的语言基础,如果计算机之间甲流使用的是哪种编码方式没有达成共识,就会出现“锟斤拷���”这样的魔幻字符。
在大数据系统中,这样的场景非常常见,主要原因在于数据的数据的生产与处理是隔离的,比如不同的业务系统各自独立运行,其产生的数据都汇集到大数据系统进行统一处理。
以下是一个数据样例,直观看上去这个数据非常复杂,看不出其中的具体内容。这里我们将讨论Python的数据编码方式(Python3),以及在阿里云 SLS 数据加工中如何应用Python的编码方案快速的实现数据编码处理。

{\x22time\x22:1644460630577,\x22type\x22:\x22track\x22,\x22distinct_id\x22:\x221111111\x22,\x22login_id\x22:\x221111111\x22,\x22anonymous_id\x22:\x22b13f22aca3faa599\x22,\x22lib\x22:{\x22$lib_method\x22:\x22autoTrack\x22,\x22$lib\x22:\x22Android\x22,\x22$lib_version\x22:\x225.2.6\x22,\x22$app_version\x22:\x221.1.23\x22,\x22$lib_detail\x22:\x22com.zeekrlife.second_hand.view.TestActivity######\x22},\x22event\x22:\x22$AppViewScreen\x22,\x22properties\x22:{\x22$os_version\x22:\x222.0.0\x22,\x22$model\x22:\x22XXX\x22,\x22$os\x22:\x22iOS\x22,\x22$screen_width\x22:1133,\x22$brand\x22:\x22TEST\x22,\x22$screen_height\x22:2453,\x22$app_version\x22:\x221.1.23\x22,\x22$lib\x22:\x22Android\x22,\x22$device_id\x22:\x22b13f22aca3faa599\x22,\x22$app_name\x22:\x22\xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81\x22,\x22$lib_version\x22:\x225.2.6\x22,\x22$timezone_offset\x22:-480,\x22$app_id\x22:\x22com.zeekrlife.mobile\x22,\x22$manufacturer\x22:\x22TEST\x22,\x22platform_type\x22:\x22Android\x22,\x22$referrer_title\x22:\x22\xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81\x22,\x22$wifi\x22:true,\x22$network_type\x22:\x22WIFI\x22,\x22$referrer\x22:\x22com.zeekrlife.main.MainActivity\x22,\x22$url\x22:\x22com.zeekrlife.second_hand.view.TestActivity\x22,\x22$screen_name\x22:\x22com.zeekrlife.second_hand.view.TestActivity\x22,\x22$title\x22:\x22\xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81\x22,\x22$lib_method\x22:\x22autoTrack\x22,\x22$is_first_day\x22:false,\x22$ip\x22:\x2210.200.88.32\x22,\x22$is_login_id\x22:false,\x22$city\x22:\x22\xE4\xBF\x9D\xE7\x95\x99IP\x22,\x22$province\x22:\x22\xE4\xBF\x9D\xE7\x95\x99IP\x22,\x22$country\x22:\x22\xE4\xBF\x9D\xE7\x95\x99IP\x22},\x22_flush_time\x22:1644460631538,\x22map_id\x22:\x221111111\x22,\x22user_id\x22:1234567890,\x22recv_time\x22:1644460631756,\x22project\x22:\x22haha\x22}\xC2\xA0

Python 数据编码

字符编码基础

首先我们来看几个基础编码概念。

  1. ASCII 编码定义了最初计算机可识别的127个字符,包括英文大小写字母、数字、~!@等特殊符号,也就是常见的键盘按键所代表的字符。比如英文字母A的编号为65(16进制位0x41),* 的编号为42。
  2. Unicode编码 。随着互联网发展,127个字符是远远不够的,因为各种语言文字都需要在互联网传播,新的符号也不断的被创造出来,Unicode 字符集就是为此而设计的。其目标是将我们使用到的所有字符都列举出来,并将其编号。比如英文字母A的编号为U+0041,中文字“我”的编号为U+6211,Emoji表情符号👍 的编号为U+1F44D。
  3. UTF-8 编码。Unicode编码带来2个问题:一是字符非常多,如果所有字符都是用相同的二进制位存储,对与存储空间有很大的浪费;另一个是字符不断的扩展,无法定义出使用多少二进制位可以完全表达。考虑到这些问题,UTF-8编码方式设计为一种变长编码,也就是不同的字符,其二进制表达位数不一样,编号越大的字符其编码长度也就越长,其使用频率相对较低,所以加大成都的节省存储空间。比如,英文字母A的编码十六进制串位0x41(长度位1个字节,与其ASCII码一致),中文字“我”的编码为0xe68891(长度为3个字节),Emoji表情符号👍 的编码为0xf09f918d(长度为4个字节)。GBK、Latin-1等编码方式设计都与UTF-8类似。

Python 字符编码

我们先来总结下 Python 的字符串编码的基础。Python 2 由于官方已不再支持,所以本文的讨论只针对Python 3。
加入我在 Python 代码中定义一个变量 x="hello 地球",那么这里面其实有两个内在的编码设计点:

  1. 字符串类型其实是程序代码中的概念,用于代码的编写。以上x 这个Python变脸存储的是Unicode字符串。
  2. 这段代码本身使用的是 UFT-8 编码存储的,数据落盘存储时需要转为特定的编码方式

Python 对与数据编码的转换会涉及到两个方向:

  1. Unicode ==> UTF-8/GBK,从字符串类型转为二进制编码类型,可以使用 "string".encode() 方法。
  2. UTF-8/GBK ==> Unicode,从二进制编码类型转为字符串类型,可以使用 b"bytes".decode() 方法.

如果数据编码要做转换 UTF-8 ==> GBK,则需要做两次转换:UTF-8 ==> Unicode ==> GBK。

另外一个Python字符串处理中常见的概念时 raw string。转义字符设计初衷是将特殊字符(无法直接表示)通过普通字符组合的方式表达出来,这样就可以在程序代码中直接使用,比如代码中使用\n来表示换行,这里反斜杠就是转义字符。当我们需要确切的表示\+n这两个字符连接的字符串时,就需要在转义一次,表示为x="\\n"。如果代码中出现多个连续反斜杠时,可读性就变得极差,因为看到的反斜杠数目与真实逻辑所表达数目是不一致的。Python 中考虑到了这个问题,直接使用 r(raw的缩写)作为字符串定义的前缀,比如x=r"\n"就可以表示\+n这两个字符连接的字符串。

SLS 数据加工应用

SLS 数据加工中通过内置函数来实现编码的转换:str_encode/str_decode,其使用方式与Python中的 str.encode()/bytes.decode() 完全一致,以上中提到的复杂数据为例。
原始数据如下:

content: {\x22time\x22:1644460630577,\x22type\x22:\x22track\x22,\x22distinct_id\x22:\x221111111\x22,\x22login_id\x22:\x221111111\x22,\x22anonymous_id\x22:\x22b13f22aca3faa599\x22,\x22lib\x22:{\x22$lib_method\x22:\x22autoTrack\x22,\x22$lib\x22:\x22Android\x22,\x22$lib_version\x22:\x225.2.6\x22,\x22$app_version\x22:\x221.1.23\x22,\x22$lib_detail\x22:\x22com.haha.second_hand.view.TestActivity######\x22},\x22event\x22:\x22$AppViewScreen\x22,\x22properties\x22:{\x22$os_version\x22:\x222.0.0\x22,\x22$model\x22:\x22XXX\x22,\x22$os\x22:\x22iOS\x22,\x22$screen_width\x22:1133,\x22$brand\x22:\x22TEST\x22,\x22$screen_height\x22:2453,\x22$app_version\x22:\x221.1.23\x22,\x22$lib\x22:\x22Android\x22,\x22$device_id\x22:\x22b13f22aca3faa599\x22,\x22$app_name\x22:\x22\xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81\x22,\x22$lib_version\x22:\x225.2.6\x22,\x22$timezone_offset\x22:-480,\x22$app_id\x22:\x22com.haha.mobile\x22,\x22$manufacturer\x22:\x22TEST\x22,\x22platform_type\x22:\x22Android\x22,\x22$referrer_title\x22:\x22\xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81\x22,\x22$wifi\x22:true,\x22$network_type\x22:\x22WIFI\x22,\x22$referrer\x22:\x22com.haha.main.MainActivity\x22,\x22$url\x22:\x22com.haha.second_hand.view.TestActivity\x22,\x22$screen_name\x22:\x22com.haha.second_hand.view.TestActivity\x22,\x22$title\x22:\x22\xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81\x22,\x22$lib_method\x22:\x22autoTrack\x22,\x22$is_first_day\x22:false,\x22$ip\x22:\x2210.200.88.32\x22,\x22$is_login_id\x22:false,\x22$city\x22:\x22\xE4\xBF\x9D\xE7\x95\x99IP\x22,\x22$province\x22:\x22\xE4\xBF\x9D\xE7\x95\x99IP\x22,\x22$country\x22:\x22\xE4\xBF\x9D\xE7\x95\x99IP\x22},\x22_flush_time\x22:1644460631538,\x22map_id\x22:\x221111111\x22,\x22user_id\x22:1234567890,\x22recv_time\x22:1644460631756,\x22project\x22:\x22haha\x22}\xC2\xA0

加工脚本:

e_set(
    "content",
    str_decode(
        str_encode(
            str_decode(str_encode(v("content"), "latin1"), "unicode_escape"), "latin1",
        ),
        "utf8",
    ),
)

结果如下,是一个JSON对象:

content: {"time":1644460630577,"type":"track","distinct_id":"1111111","login_id":"1111111","anonymous_id":"b13f22aca3faa599","lib":{"$lib_method":"autoTrack","$lib":"Android","$lib_version":"5.2.6","$app_version":"1.1.23","$lib_detail":"com.haha.second_hand.view.TestActivity######"},"event":"$AppViewScreen","properties":{"$os_version":"2.0.0","$model":"XXX","$os":"iOS","$screen_width":1133,"$brand":"TEST","$screen_height":2453,"$app_version":"1.1.23","$lib":"Android","$device_id":"b13f22aca3faa599","$app_name":"我是谁","$lib_version":"5.2.6","$timezone_offset":-480,"$app_id":"com.haha.mobile","$manufacturer":"TEST","platform_type":"Android","$referrer_title":"我是谁","$wifi":true,"$network_type":"WIFI","$referrer":"com.haha.main.MainActivity","$url":"com.haha.second_hand.view.TestActivity","$screen_name":"com.haha.second_hand.view.TestActivity","$title":"我是谁","$lib_method":"autoTrack","$is_first_day":false,"$ip":"10.200.88.32","$is_login_id":false,"$city":"保留IP","$province":"保留IP","$country":"保留IP"},"_flush_time":1644460631538,"map_id":"1111111","user_id":1234567890,"recv_time":1644460631756,"project":"haha"}  

编解码函数通过 errors 参数来处理编码错误,其可选值:

  1. ignore:忽略
e_set("xxx", str_encode("test 测试数据", encoding="ascii", errors="ignore"))

结果为:
xxx: "test "

  1. strict:直接报错,丢弃此条数据
e_set("xxx", str_encode("test 测试数据", encoding="ascii", errors="ignore"))

执行时直接报错。

  1. replace:使用?替换
e_set("xxx", str_encode("test 测试数据", encoding="ascii", errors="replace"))

结果为:

xxx: "test ????"
  1. xmlcharrefreplace:使用 XML 字符引用替换
e_set("xxx", str_encode("test 测试数据", encoding="ascii", errors="xmlcharrefreplace"))

结果为:

xxx: "test 测试数据"

总结

数据编码在大数据处理的基础操作,本文讨论了 Python3 中的数据编码方案,以及在 SLS 数据加工中内置的数据编解码函数使用。
参考资料:

  1. 《Python and Unicode》PPT
  2. Python 文档 Unicode HOWTO

下图是 SLS 团队的技术博客,我们会不定期推出技术文章分享和产品更新介绍,欢迎大家订阅,有任何问题也欢迎与我们反馈。
SLS QR.png

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
24天前
|
数据采集 数据可视化 数据挖掘
利用Python自动化处理Excel数据:从基础到进阶####
本文旨在为读者提供一个全面的指南,通过Python编程语言实现Excel数据的自动化处理。无论你是初学者还是有经验的开发者,本文都将帮助你掌握Pandas和openpyxl这两个强大的库,从而提升数据处理的效率和准确性。我们将从环境设置开始,逐步深入到数据读取、清洗、分析和可视化等各个环节,最终实现一个实际的自动化项目案例。 ####
|
1天前
|
数据采集 Web App开发 监控
Python爬虫:爱奇艺榜单数据的实时监控
Python爬虫:爱奇艺榜单数据的实时监控
|
8天前
|
分布式计算 大数据 数据处理
技术评测:MaxCompute MaxFrame——阿里云自研分布式计算框架的Python编程接口
随着大数据和人工智能技术的发展,数据处理的需求日益增长。阿里云推出的MaxCompute MaxFrame(简称“MaxFrame”)是一个专为Python开发者设计的分布式计算框架,它不仅支持Python编程接口,还能直接利用MaxCompute的云原生大数据计算资源和服务。本文将通过一系列最佳实践测评,探讨MaxFrame在分布式Pandas处理以及大语言模型数据处理场景中的表现,并分析其在实际工作中的应用潜力。
37 2
|
14天前
|
弹性计算 安全 开发工具
灵码评测-阿里云提供的ECS python3 sdk做安全组管理
批量变更阿里云ECS安全组策略(批量变更)
|
23天前
|
数据采集 分布式计算 大数据
构建高效的数据管道:使用Python进行ETL任务
在数据驱动的世界中,高效地处理和移动数据是至关重要的。本文将引导你通过一个实际的Python ETL(提取、转换、加载)项目,从概念到实现。我们将探索如何设计一个灵活且可扩展的数据管道,确保数据的准确性和完整性。无论你是数据工程师、分析师还是任何对数据处理感兴趣的人,这篇文章都将成为你工具箱中的宝贵资源。
|
1月前
|
传感器 物联网 开发者
使用Python读取串行设备的温度数据
本文介绍了如何使用Python通过串行接口(如UART、RS-232或RS-485)读取温度传感器的数据。详细步骤包括硬件连接、安装`pyserial`库、配置串行端口、发送请求及解析响应等。适合嵌入式系统和物联网应用开发者参考。
53 3
|
1月前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
361 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
15天前
|
监控 安全 Apache
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。
|
2月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
336 3
|
25天前
|
存储 监控 安全
什么是事件日志管理系统?事件日志管理系统有哪些用处?
事件日志管理系统是IT安全的重要工具,用于集中收集、分析和解释来自组织IT基础设施各组件的事件日志,如防火墙、路由器、交换机等,帮助提升网络安全、实现主动威胁检测和促进合规性。系统支持多种日志类型,包括Windows事件日志、Syslog日志和应用程序日志,通过实时监测、告警及可视化分析,为企业提供强大的安全保障。然而,实施过程中也面临数据量大、日志管理和分析复杂等挑战。EventLog Analyzer作为一款高效工具,不仅提供实时监测与告警、可视化分析和报告功能,还支持多种合规性报告,帮助企业克服挑战,提升网络安全水平。