阿里云 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日志并进行多维度分析。
目录
相关文章
|
23天前
|
数据采集 数据可视化 数据挖掘
利用Python自动化处理Excel数据:从基础到进阶####
本文旨在为读者提供一个全面的指南,通过Python编程语言实现Excel数据的自动化处理。无论你是初学者还是有经验的开发者,本文都将帮助你掌握Pandas和openpyxl这两个强大的库,从而提升数据处理的效率和准确性。我们将从环境设置开始,逐步深入到数据读取、清洗、分析和可视化等各个环节,最终实现一个实际的自动化项目案例。 ####
|
7天前
|
分布式计算 大数据 数据处理
技术评测:MaxCompute MaxFrame——阿里云自研分布式计算框架的Python编程接口
随着大数据和人工智能技术的发展,数据处理的需求日益增长。阿里云推出的MaxCompute MaxFrame(简称“MaxFrame”)是一个专为Python开发者设计的分布式计算框架,它不仅支持Python编程接口,还能直接利用MaxCompute的云原生大数据计算资源和服务。本文将通过一系列最佳实践测评,探讨MaxFrame在分布式Pandas处理以及大语言模型数据处理场景中的表现,并分析其在实际工作中的应用潜力。
33 2
|
13天前
|
弹性计算 安全 开发工具
灵码评测-阿里云提供的ECS python3 sdk做安全组管理
批量变更阿里云ECS安全组策略(批量变更)
|
21天前
|
数据采集 分布式计算 大数据
构建高效的数据管道:使用Python进行ETL任务
在数据驱动的世界中,高效地处理和移动数据是至关重要的。本文将引导你通过一个实际的Python ETL(提取、转换、加载)项目,从概念到实现。我们将探索如何设计一个灵活且可扩展的数据管道,确保数据的准确性和完整性。无论你是数据工程师、分析师还是任何对数据处理感兴趣的人,这篇文章都将成为你工具箱中的宝贵资源。
|
1月前
|
传感器 物联网 开发者
使用Python读取串行设备的温度数据
本文介绍了如何使用Python通过串行接口(如UART、RS-232或RS-485)读取温度传感器的数据。详细步骤包括硬件连接、安装`pyserial`库、配置串行端口、发送请求及解析响应等。适合嵌入式系统和物联网应用开发者参考。
53 3
|
1月前
|
数据采集 JavaScript 程序员
探索CSDN博客数据:使用Python爬虫技术
本文介绍了如何利用Python的requests和pyquery库爬取CSDN博客数据,包括环境准备、代码解析及注意事项,适合初学者学习。
81 0
|
域名解析 网络协议 Linux
Python实现阿里云域名DDNS支持ipv4和ipv6
Python实现阿里云域名DDNS支持ipv4和ipv6
22180 5
Python实现阿里云域名DDNS支持ipv4和ipv6
|
21天前
|
人工智能 数据可视化 数据挖掘
探索Python编程:从基础到高级
在这篇文章中,我们将一起深入探索Python编程的世界。无论你是初学者还是有经验的程序员,都可以从中获得新的知识和技能。我们将从Python的基础语法开始,然后逐步过渡到更复杂的主题,如面向对象编程、异常处理和模块使用。最后,我们将通过一些实际的代码示例,来展示如何应用这些知识解决实际问题。让我们一起开启Python编程的旅程吧!
|
20天前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
8天前
|
Unix Linux 程序员
[oeasy]python053_学编程为什么从hello_world_开始
视频介绍了“Hello World”程序的由来及其在编程中的重要性。从贝尔实验室诞生的Unix系统和C语言说起,讲述了“Hello World”作为经典示例的起源和流传过程。文章还探讨了C语言对其他编程语言的影响,以及它在系统编程中的地位。最后总结了“Hello World”、print、小括号和双引号等编程概念的来源。
101 80