Python3 網絡傳輸數據的處理(json / xml / base64)

本文由 Luzhuo 編寫,轉發請保留該信息. 
原文: http://blog.csdn.net/Rozol/article/details/72760548

以下代碼以Python3.6.1爲例 
Less is more!

json

#!/usr/bin/env python
# coding=utf-8
__author__ = 'Luzhuo'
__date__ = '2017/5/4'
# json_demo.py json格式的數據
# 解析和創建json數據
# 編碼: 默認編碼爲"ascii", 中文(非ASCII字符)將被轉義

import json


class Person:
    def __init__(self):
        self.name = "luzhuo"
        self.age = 23
        self.lists = [4, 5, 6, "中文"]

data = {"dicts": None, "class": None}
dicts = {"name": "luzhuo", "age": 21, "lists": [1, 2, 3, "中文"]}


def json_encode():
    '''
    編碼
    '''

    # 編碼字典
    data_dicts = json.dumps(dicts, indent=4)
    print(data_dicts)
    data["dicts"] = data_dicts

    # 編碼類
    data_class = json.dumps(Person(), indent=4, default=lambda obj: obj.__dict__)
    print(data_class)
    data["class"] = data_class


def json_decode():
    '''
    解碼
    '''

    # 解碼字典
    dicts = json.loads(data["dicts"])
    print(dicts)

    # 解碼類(實際上是被解析成了字典)
    clazz = json.loads(data["class"])
    print(clazz)



def json_func():
    # 將obj序列轉爲fp, skipkeys:是否跳過非Python基本類型的數據, ensure_ascii:是否將非ASCII字符轉義, check_circular:是否進行容器循環引用檢查, indent:格式化None/int, default:def default(obj):爲不能爲序列化的函數調用, sort_keys:是否按鍵排序
    # json.dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
    json.dump(dicts, open("file.txt", "w"))
    # 將obj序列轉爲json格式的str
    # json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
    data_str = json.dumps(dicts)

    # 從fp反序列化爲python對象
    # json.load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
    data_dict = json.load(open("file.txt"))
    # 從str反序列化爲python對象
    # json.loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
    data_dict = json.loads(data_str)

    # Json解碼器
    # class json.JSONDecoder(object_hook=None, parse_float=None, parse_int=None, parse_constant=None, strict=True, object_pairs_hook=None)
    jsondecoder = json.JSONDecoder()

    data_dict = jsondecoder.decode("")  # 解碼字符串json文檔
    data_dict = jsondecoder.raw_decode("")  # 解碼字符串json文檔, 返回(Python形式, 原始json文檔的字節數)

    # Json編碼器
    # class json.JSONEncoder(skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)
    jsonencode = json.JSONEncoder()

    # jsonencode.default(o)  # 返回可序列化對象, 在子類中重寫並實現
    jsonencode.encode(dicts)  # 編碼, 字符串形式
    jsonencode.iterencode(dicts)  # 編碼, 可迭代對象


if __name__ == "__main__":
    json_encode()
    json_decode()

    # json_func()

xml

#!/usr/bin/env python
# coding=utf-8
__author__ = 'Luzhuo'
__date__ = '2017/5/24'
# xml_demo.py xml格式的數據
# 解析和創建xml數據
# 傳統的接口傳的數據還是xml
# 這裏只講ElementTree, 其他兩種方式再說...-.-!

# 解析XML文件有三種方式:
    # 1. SAX: 適合讀取大文件,數據流形式讀取,速度快,內存佔用少,通過回調函數返回數據
    # 2. DOM: 適合讀取小文件,數據映射到內存中的樹,速度慢,耗內存
    # 3. ElementTree: 默認適合小文件, 遞增解析方式適合大中文件,數據生成元素樹,速度快,內存佔用少

data = '''<?xml version='1.0' encoding='utf-8'?>
        <data>
            <student name="liuyan">
                <age>21</age>
            </student>
            <student name="tanwei">
                <age>22</age>
            </student>
        </data>
        '''

import xml.etree.ElementTree as et

path = "xml.xml"  # xml裏的數據與data相同
def et_encode():
    '''
    編碼爲xml數據
    '''

    # 創建
    root = et.Element("data")  # 根元素
    name = et.SubElement(root, "name", attrib={"show": "yes"})  # 子元素
    age = et.SubElement(name, "age")
    age.text = '21'

    et_ = et.ElementTree(root)  # 生成xml
    et_.write("new.xml", encoding="utf-8", xml_declaration=True)
    et.dump(root)  # 寫入文件



def et_decode():
    '''
    xml數據解碼
    '''

    tree = et.parse(path)
    root = tree.getroot()  # 獲取根元素
    # 遍歷xml文檔
    for child in root:  # 第二層
        print(child.tag, child.attrib, child.text) # tag:元素名 attrib:屬性{key:value} text:內容
        for i in child:  # 第三層
            print(i.tag, i.attrib, i.text)

    # 遍歷所有age元素
    for node in root.iter("age"):
        print(node.tag, node.text)

    # 修改元素
    for node in root.iter("age"):
        new_year = int(node.text) + 1
        node.text = str(new_year)  # 修改值
        node.set("updated", "age")  # 添加屬性
    tree.write(path, encoding="utf-8", xml_declaration=True)

    # 刪除元素
    for student in root.findall("student"):  # findall()定位元素可使用XPath表達式
        age = int(student.find("age").text)
        if age > 22:
            root.remove(student)  # 刪除元素
    tree.write(path, encoding="utf-8", xml_declaration=True)


def et_func():
    '''
    ElementTree
    '''
    # 創建
    # xml.etree.ElementTree.parse(source, parser=None)  // xml解析到元素樹中, source:文件名 / file-obj
    tree = et.parse(path)

    # xml.etree.ElementTree.SubElement(parent, tag, attrib={}, **extra) // 穿件元素實例, parent:父元素, tag:子元素名稱, attrib:{attr:value}, extra:其他關鍵字屬性
    elem = et.SubElement(elem, "name", attrib={"show": "yes"})
    # xml.etree.ElementTree.fromstring(text) // 從字符換解析xml, 返回Element實例
    elem = et.fromstring(data)
    # xml.etree.ElementTree.fromstringlist(sequence, parser=None) // 同fromstring
    elem = et.fromstringlist(data)
    # xml.etree.ElementTree.XML(text, parser=None) // 同fromstring
    elem = et.XML(data)
    # xml.etree.ElementTree.XMLID(text, parser=None) // 從字符串中解析xml, 並返回(元素, 字典)
    elem, dicts = et.XMLID(data)
    # xml.etree.ElementTree.Comment(text=None) // 註釋元素, text:註釋內容(bytes / Unicode字符串), XMLParser跳過註釋,ElementTree只包含註釋結點
    elem = et.Comment(r"註釋")
    # xml.etree.ElementTree.ProcessingInstruction(target, text=None) // PI元素, target:PI目標字符串, text:PI內容字符串, 返回元素實例, XMLParser跳過該元素, ElementTree只包含節點
    # xml.etree.ElementTree.register_namespace(prefix, uri) // 註冊命名空間前綴, prefix:前綴, uri:命名空間
    et.register_namespace("web", "http://luzhuo.me")

    # xml遞增的方式解析到元素樹中(適合大文件), source:文件名/file-obj, events:要報告的事件("start", "end"(默認), "start-ns", "end-ns), parser:可選的解析器(XMLParser的子類)
    # xml.etree.ElementTree.iterparse(source, events=None)
    events, elem = et.iterparse(path)

    # xml.etree.ElementTree.dump(elem) // 將元素樹寫成普通的xml文件
    et.dump(elem)
    # xml字符串表示形式, method:"xml"(默認)."html"."text"
    # xml.etree.ElementTree.tostring(element, encoding="us-ascii", method="xml", *, short_empty_elements=True)
    strs = et.tostring(elem, encoding="utf-8")
    # xml.etree.ElementTree.tostringlist(element, encoding="us-ascii", method="xml", *, short_empty_elements=True) // 同tostring
    strs = et.tostringlist(elem)

    boolean = et.iselement(elem)  # 是否是元素對象


    # --- Element 對象 ---
    # class xml.etree.ElementTree.Element(tag, attrib={}, ** extra) // 元素類, tag:bytes/Unicode字符串, attrib:{attr:value}

    elem.tag  # 元素名
    elem.text  # 元素內容(標籤的內容<a>text</a>)
    elem.tail  # 元素內容(標籤之後的內容</a>text)
    dicts = elem.attrib  # 屬性字典
    elem.clear()  # 刪除所有元素,屬性
    elem.get("age", default=None)  # 獲取屬性的值
    key, value = elem.items()  # 元素屬性列表(key, value)返回
    elem.keys()  # 元素的屬性列表
    elem.set(key, value)  # 設置元素的屬性
    elem.append(elem)  # 添加元素到末尾(直接下級)
    # elem.extend(elem)  # 添加元素到末尾, 源碼是調用_children列表.extentd()方式添加元素,不知爲何.append()有用,而extentd()無效果
    # find(match, namespaces=None) // 匹配(直接下級)第一個子元素, match:元素名 / XPath, namespaces:命名空間
    elem = elem.find("root")
    # findall(match, namespaces=None) // 匹配(直接下級)所有子元素, match:元素名 / XPath
    elems = elem.findall("root")
    # findtext(match, default=None, namespaces=None) // 匹配(直接下級)第一個子元素的文本
    texts = elem.findtext("root")
    elem.insert(1, elem)  # 插入子元素, index:位置, subelement:子元素
    # iter(tag=None)  # 指定(所有下級)元素名的迭代器(深度優先)
    elem.iter("root")
    elem.iterfind("root")  # 匹配(直接下級)所有子元素, 返回迭代器
    elem.itertext()  # 文本迭代器(所有下級)
    elem.remove(elem)  # 刪除子元素


    # --- ElementTree 對象 ---
    # ElementTree包裝類, 表示整個元素的層次結構, element:根元素, file:如果給定,將生成初始化樹
    # class xml.etree.ElementTree.ElementTree(element=None, file=None)
    et_ = et.ElementTree(elem)
    # parse(source, parser=None) // 解析xml到元素樹, source:文件名 / file-obj
    et_ = et_.parse(path)

    et_.getroot()  # 獲取根元素
    et_.__setroot(elem)  # 替換根元素
    et_._find("root", namespaces=None)  # 同Element.find()
    et_._findall("root", namespaces=None)  #同Element.findall()
    et_._findtext("root", default=None, namespaces=None)  # Element.findtext()

    et_.iter(tag=None)  # Element.iter()
    # iterfind(match, namespaces=None) // Element.iterfind()
    et_.iterfind("root")

    # 將元素樹寫入文件, file:文件名/file-obj, xml_declaration:是否顯示聲明信息, default_namespace:命名空間("xmlns"), method:"xml"(默認)/"html"/"text", short_empty_elements:是否自閉標籤(默認True)
    # write(file, encoding="us-ascii", xml_declaration=None, default_namespace=None, method="xml", *, short_empty_elements=True)
    et_.write("new.xml", encoding="utf-8", xml_declaration=True)


    # 異常
    # class xml.etree.ElementTree.ParseError
        # code # 錯誤嗎
        # position # 行列



# XPath表達式
# tag   標籤名的所有子元素
# *     所有子元素
# .     選擇當前節點(相對路徑)
# //    該級別下的所有元素
# ..    父元素
# [@attrib='value'] 具有指定屬性的所有元素
# [tag] 標籤名的直接子元素
# [tag='text']  該級別下爲標籤名的所有元素
# [position]    指定位置的元素[1, last()-1]

# 案例:
# root.findall("./student")  # root元素下的所有student元素
# root.findall(".//student[@name='liuyan']")  # student下所有name屬性爲liuyan的元素
# root.findall(".//*[@name='liuyan']/age")  # root元素下的所有name屬性爲liuyan的元素下的 age元素
# root.findall(".//student[2]")  # 所有student元素的第二個元素


if __name__ == "__main__":
    et_encode()
    et_decode()

    # et_func()

base64

#!/usr/bin/env python
# coding=utf-8
__author__ = 'Luzhuo'
__date__ = '2017/5/19'
# base64_demo.py 將二進制數據編碼爲可打印ASCII字符,並且可解碼爲二進制
# 支持: base16 base32 base64 base85
# 可作用文本 / URL / HTTP POST
# 現代接口: 支持 字節(bytes-like object) 的 編碼 和 解碼
# 傳統接口: 支持 文件對象 的 編碼 和 解碼


import base64


def base64_demo():
    # 使用Base64編碼/解碼
    bytes = base64.b64encode(b'luzhuo.me')
    print(bytes)

    bytes = base64.b64decode(bytes)
    print(bytes)

    # 對文件的內容進行編碼
    base64.encode(open("file.txt", "rb"), open("base.txt", "wb"))



def base54_func():
    # 現代接口
    # base64.b64encode(s, altchars=None) // Base64編碼
    bytes = base64.b64encode(b'luzhuo.me')
    # base64.b64decode(s, altchars=None, validate=False)  // Base64解碼, validate:True(非字母字符拋binascii.Error), False(非字母字符丟棄)
    bytes = base64.b64decode(bytes)
    # base64.standard_b64encode(s) // 標準的Base64字母表編碼(同b64encode)
    bytes = base64.standard_b64encode(b'luzhuo.me')
    # base64.standard_b64decode(s) // 標準的Base64字母表解碼(同b64decode)
    bytes = base64.standard_b64decode(bytes)
    # base64.urlsafe_b64encode(s) // 使用URL和文件系統安全的字母表編碼
    bytes = base64.urlsafe_b64encode(b'luzhuo.me')
    # base64.urlsafe_b64decode(s) // 使用URL和文件系統安全的字母表解碼
    bytes = base64.urlsafe_b64decode(bytes)
    # base64.b32encode(s) // Base32編碼
    bytes = base64.b32encode(b'luzhuo.me')
    # base64.b32decode(s, casefold=False, map01=None) // Base32解碼
    bytes = base64.b32decode(bytes)
    # base64.b16encode(s) // 使用Base16編碼
    bytes = base64.b16encode(b'luzhuo.me')
    # base64.b16decode(s, casefold=False) // Base16解碼
    bytes = base64.b16decode(bytes)
    # base64.a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False) // Ascii85編碼
    bytes = base64.a85encode(b'luzhuo.me')
    # base64.a85decode(b, *, foldspaces=False, adobe=False, ignorechars=b' \t\n\r\v') // Ascii85解碼
    bytes = base64.a85encode(bytes)
    # base64.b85encode(b, pad=False) // base85編碼
    bytes = base64.b85encode(b'luzhuo.me')
    # base64.b85decode(b) // base85解碼
    bytes = base64.b85decode(bytes)

    # 傳統接口
    # base64.encode(input, output) // 編碼, input從文件讀取二進制數據, output寫入文件 (每76個字節後 和 末尾 插入b'\n')
    base64.encode(open("file.txt", "rb"), open("base.txt", "wb"))
    # base64.decode(input, output) // 解碼
    base64.decode(open("base.txt", "rb"), open("file.txt", "wb"))
    bytes = base64.encodebytes(b'luzhuo.me')  # 編碼 (每76個字節後 和 末尾 插入b'\n')
    bytes = base64.decodebytes(bytes)  # 解碼




if __name__ == "__main__":
    base64_demo()

    # base54_func()


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章