天天看點

Python 學習(十)--資料解析

1. 什麼是XML?

XML 指可擴充标記語言(eXtensible Markup Language),标準通用标記語言的子集,是一種用于标記電子檔案使其具有結構性的标記語言。 XML 被設計用來傳輸和存儲資料。XML是一套定義語義标記的規則,這些标記将文檔分成許多部件并對這些部件加以辨別。它也是元标記語言,即定義了用于定義其他與特定領域有關的、語義的、結構化的标記語言的句法語言。

python對XML的解析

常見的XML程式設計接口有DOM和SAX,這兩種接口處理XML檔案的方式不同,當然使用場合也不同。

python有三種方法解析XML,SAX,DOM,以及ElementTree:

  • SAX (simple API for XML )

    python 标準庫包含SAX解析器,SAX用事件驅動模型,通過在解析XML的過程中觸發一個個的事件并調用使用者定義的回調函數來處理XML檔案。

  • DOM(Document Object Model)

    将XML資料在記憶體中解析成一個樹,通過對樹的操作來操作XML。

下面用到的movies.xml内容:

<collection shelf="New Arrivals">
<movie title="Enemy Behind">
   <type>War, Thriller</type>
   <format>DVD</format>
   <year>2003</year>
   <rating>PG</rating>
   <stars>10</stars>
   <description>Talk about a US-Japan war</description>
</movie>
<movie title="Transformers">
   <type>Anime, Science Fiction</type>
   <format>DVD</format>
   <year>1989</year>
   <rating>R</rating>
   <stars>8</stars>
   <description>A schientific fiction</description>
</movie>
   <movie title="Trigun">
   <type>Anime, Action</type>
   <format>DVD</format>
   <episodes>4</episodes>
   <rating>PG</rating>
   <stars>10</stars>
   <description>Vash the Stampede!</description>
</movie>
<movie title="Ishtar">
   <type>Comedy</type>
   <format>VHS</format>
   <rating>PG</rating>
   <stars>2</stars>
   <description>Viewable boredom</description>
</movie>
</collection>
           

2. SAX解析xml

1). SAX是一種基于事件驅動的API。利用SAX解析XML文檔牽涉到兩個部分:解析器和事件處理器。解析器負責讀取XML文檔,并向事件處理器發送事件,如元素開始跟元素結束事件;而事件處理器則負責對事件作出相應,對傳遞的XML資料進行處理。

1、對大型檔案進行處理;

2、隻需要檔案的部分内容,或者隻需從檔案中得到特定資訊。

3、想建立自己的對象模型的時候。

2). 在python中使用sax方式處理xml要先引入xml.sax中的parse函數,還有xml.sax.handler中的ContentHandler。

ContentHandler類方法介紹

  • characters(content)方法

    調用時機:

    1>. 從行開始,遇到标簽之前,存在字元,content的值為這些字元串。

    2>. 從一個标簽,遇到下一個标簽之前, 存在字元,content的值為這些字元串。

    3>. 從一個标簽,遇到行結束符之前,存在字元,content的值為這些字元串。

    4>. 标簽可以是開始标簽,也可以是結束标簽。

  • startDocument()方法: 文檔啟動的時候調用。
  • endDocument()方法: 解析器到達文檔結尾時調用。
  • startElement(name, attrs)方法: 遇到XML開始标簽時調用,name是标簽的名字,attrs是标簽的屬性值字典。
  • endElement(name)方法: 遇到XML結束标簽時調用。

3). make_parser方法

以下方法建立一個新的解析器對象并傳回。

xml.sax.make_parser( [parser_list] )
           

參數說明:

parser_list - 可選參數,解析器清單

4). parser方法

以下方法建立一個 SAX 解析器并解析xml文檔:

xml.sax.parse( xmlfile, contenthandler[, errorhandler])
           

xmlfile - xml檔案名

contenthandler - 必須是一個ContentHandler的對象

errorhandler - 如果指定該參數,errorhandler必須是一個SAX ErrorHandler對象

5). parseString方法

parseString方法建立一個XML解析器并解析xml字元串:

xml.sax.parseString(xmlstring, contenthandler[, errorhandler])
           

xmlstring - xml字元串

6). 示例:

import xml.sax

class MovieHandler(xml.sax.ContentHandler):
    """docstring for MovieHandler"""
    def __init__(self):
        super(MovieHandler, self).__init__()
        self.CurrendData = ""
        self.type = ""
        self.format = ""
        self.year = ""
        self.rating = ""
        self.stars = ""
        self.description = ""

    # 元素開始調用
    def startElement(self, tag, attributes):
        self.CurrendData = tag
        if tag == "movie":
            print("******Movie******")
            title = attributes["title"]
            print("Title: ", title)
            pass
        pass

    # 元素結束調用
    def endElement(self, tag):
        if self.CurrendData == "type":
            print("Type: ", self.type)
        elif self.CurrendData == "format":
            print("Format: ", self.format)
        elif self.CurrendData == "year":
            print("Year: ", self.year)
        elif self.CurrendData == "rating":
            print("Rating: ", self.rating)
        elif self.CurrendData == "stars":
            print("Stars: ", self.stars)
        elif self.CurrendData == "description":
            print("Description: ", self.description)
        self.CurrendData = ""
        pass

    # 讀取字元時調用
    def characters(self, content):
        if self.CurrendData == "type":
            self.type = content
        elif self.CurrendData == "format":
            self.format = content
        elif self.CurrendData == "year":
            self.year = content
        elif self.CurrendData == "rating":
            self.rating = content
        elif self.CurrendData == "stars":
            self.stars = content
        elif self.CurrendData == "description":
            self.description = content
        pass



if (__name__ == "__main__") :
    # 建立一個XMLReader
    parser = xml.sax.make_parser()
    # 關閉命名空間
    parser.setFeature(xml.sax.handler.feature_namespaces, 0)
    # 重寫 ContextHandler
    handler = MovieHandler()
    parser.setContentHandler(handler)

    parser.parse("movies.xml")
    pass
           

列印結果:

Python 學習(十)--資料解析

圖1.png

3. Dom解析xml

檔案對象模型(Document Object Model,簡稱DOM),是W3C組織推薦的處理可擴充置智語言的标準程式設計接口。一個 DOM 的解析器在解析一個 XML 文檔時,一次性讀取整個文檔,把文檔中所有元素儲存在記憶體中的一個樹結構裡,之後你可以利用DOM 提供的不同的函數來讀取或修改文檔的内容和結構,也可以把修改過的内容寫入xml檔案。python中用xml.dom.minidom來解析xml檔案.

示例:

from xml.dom.minidom import parse
import xml.dom.minidom

# 使用minidom解析器打開XML文檔
DOMTree = xml.dom.minidom.parse("movies.xml")

# 擷取collection節點
collection = DOMTree.documentElement
if collection.hasAttribute("shelf"):
    print("Root element: %s" % collection.getAttribute("shelf"))
    pass

# 在集合擷取所有電影
movies = collection.getElementsByTagName("movie")

# 列印每部電影的詳細資訊
for movie in movies:
    print("*******Movie********")
    if movie.hasAttribute("title"):
        print("Title: %s" % movie.getAttribute("title"))
        pass
    pass
    type = movie.getElementsByTagName("type")[0]
    print("Type: %s" % type.childNodes[0].data)
    format = movie.getElementsByTagName("format")[0]
    print("Format: %s" % format.childNodes[0].data)
    rating = movie.getElementsByTagName("rating")[0]
    print("Rating: %s" % rating.childNodes[0].data)
    description = movie.getElementsByTagName("description")[0]
    print("Description: %s" % description.childNodes[0].data)
           
Python 學習(十)--資料解析

圖2.png

4. JSON解析

JSON (JavaScript Object Notation) 是一種輕量級的資料交換格式。它基于ECMAScript的一個子集。

Python3 中可以使用 json 子產品來對 JSON 資料進行編解碼,它包含了兩個函數:

  • json.dumps(): 對資料進行編碼。
  • json.loads(): 對資料進行解碼。
import json
# 字典
data = {
    'no' : 1,
    'name' : 'mazaiting',
    'url' : 'https://www.jianshu.com/u/5d2cb4bfeb15'
}
# 将python字典類型裝換為JSON對象
json_str = json.dumps(data)
print("Python 原始資料: ", repr(data))
print("JSON 對象: ", json_str)

# 将JSON對象轉化為Python字典
data2 = json.loads(json_str)
print("data2['name']: ", data2['name'])
print("data2['url']: ", data2['url'])
           
Python 學習(十)--資料解析

圖3.png

5. 時間

Python 程式能用很多方式處理日期和時間,轉換日期格式是一個常見的功能。Python 提供了一個 time 和 calendar 子產品可以用于格式化日期和時間。時間間隔是以秒為機關的浮點小數。每個時間戳都以自從1970年1月1日午夜(曆元)經過了多長時間來表示。Python 的 time 子產品下有很多函數可以轉換常見日期格式。如函數time.time()用于擷取目前時間戳。

1). 擷取目前時間戳

# 引入time子產品
import time

ticks = time.time()
print("目前時間戳為:", ticks)
           
Python 學習(十)--資料解析

圖4.png

2). 時間元組

很多Python函數用一個元組裝起來的9組數字處理時間:

序号 字段
4位數年 2008
1 1 到 12
2 1到31
3 小時 0到23
4 分鐘 0到59
5 0到61 (60或61 是閏秒)
6 一周的第幾日 0到6 (0是周一)
7 一年的第幾日 1到366 (儒略曆)
8 夏令時 -1, 0, 1, -1是決定是否為夏令時的旗幟

上述也就是struct_time元組。這種結構具有如下屬性:

屬性
tm_year
tm_mon
tm_mday 1 到 31
tm_hour 0 到 23
tm_min 0 到 59
tm_sec 0 到 61 (60或61 是閏秒)
tm_wday
tm_yday 一年中的第幾天,1 到 366
tm_isdst 是否為夏令時,值有:1(夏令時)、0(不是夏令時)、-1(未知),預設 -1

3). 擷取目前時間

從傳回浮點數的時間辍方式向時間元組轉換,隻要将浮點數傳遞給如localtime之類的函數。

import time

localtime = time.localtime(time.time())
print("本地時間為:", localtime)
           
Python 學習(十)--資料解析

圖5.png

4). 擷取格式化的時間

你可以根據需求選取各種格式,但是最簡單的擷取可讀的時間模式的函數是asctime()

import time

localtime = time.asctime(time.localtime(time.time()))
print("本地時間為:", localtime)
           
Python 學習(十)--資料解析

圖6.png

5). 格式化日期

我們可以使用 time 子產品的 strftime 方法來格式化日期:

time.strftime(format[, t])
           
import time

# 格式化成2016-03-20 11:45:39
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

# 格式化成Wed Apr 11 16:56:32 2018形式
print(time.strftime("%a %b %d %H:%M:%S %Y", time.localtime()))

# 将格式字元串轉換為時間戳
a = "Wed Apr 11 16:56:32 2018"
print(time.mktime(time.strptime(a, "%a %b %d %H:%M:%S %Y")))
           
Python 學習(十)--資料解析

圖7.png

6). python中時間日期格式化符号:

%y 兩位數的年份表示(00-99)
%Y 四位數的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小時制小時數(0-23)
%I 12小時制小時數(01-12)
%M 分鐘數(00=59)
%S 秒(00-59)
%a 本地簡化星期名稱
%A 本地完整星期名稱
%b 本地簡化的月份名稱
%B 本地完整的月份名稱
%c 本地相應的日期表示和時間表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等價符
%U 一年中的星期數(00-53)星期天為星期的開始
%w 星期(0-6),星期天為星期的開始
%W 一年中的星期數(00-53)星期一為星期的開始
%x 本地相應的日期表示
%X 本地相應的時間表示
%Z 目前時區的名稱
%% %号本身
           

7). 日期

Calendar子產品有很廣泛的方法用來處理年曆和月曆.

# 擷取某月月曆
import calendar

cal = calendar.month(2018, 4)
print("以下輸出2016年1月份的月曆:")
print(cal)
           
Python 學習(十)--資料解析

圖8.png