Python數(shù)據(jù)處理(一):處理 JSON鸽素、XML、CSV三種格式數(shù)據(jù)

Python 數(shù)據(jù)處理系列博客來(lái)啦亦鳞!

本系列將以《Python數(shù)據(jù)處理》這本書(shū)為基礎(chǔ)馍忽,以書(shū)中每章一篇博客的形式帶大家一起學(xué)習(xí) Python 數(shù)據(jù)處理棒坏。書(shū)中有些地方講的不太詳細(xì),我會(huì)查閱其他資料來(lái)補(bǔ)充遭笋,力爭(zhēng)每篇博客都把知識(shí)點(diǎn)涵蓋全且通俗易懂坝冕。

這本書(shū)主要講了如何用 Python 處理各種類(lèi)型的文件,如 JSON瓦呼、XML喂窟、CSV、Excel央串、PDF 等磨澡。后面幾章還會(huì)講數(shù)據(jù)清洗、網(wǎng)頁(yè)抓取质和、自動(dòng)化和規(guī)奈壬悖化等使用技能。我也是 Python 初學(xué)者饲宿,將以初學(xué)者的角度寫(xiě)文章厦酬,所以博客對(duì)初學(xué)者比較友好。

100 多位經(jīng)驗(yàn)豐富的開(kāi)發(fā)者參與瘫想,在 Github 上獲得了近 1000 個(gè) star 的全棧全平臺(tái)開(kāi)源項(xiàng)目想了解或參與嗎仗阅?
項(xiàng)目地址:https://github.com/cachecats/coderiver

前言

以易于機(jī)器理解的方式來(lái)存儲(chǔ)數(shù)據(jù)的文件格式,通常被稱(chēng)作機(jī)器可讀的 (machine readable)国夜。常見(jiàn)的機(jī)器可讀格式包括:

  • 逗號(hào)分隔值(Comma-Separated Values霹菊,CSV)
  • JavaScript 對(duì)象符號(hào)(JavaScript Object Notation,JSON)
  • 可擴(kuò)展標(biāo)記語(yǔ)言(eXtensible Markup Language支竹,XML)

在口語(yǔ)和書(shū)面語(yǔ)中旋廷,提到這些數(shù)據(jù)格式時(shí)通常使用它們的短名字(如 CSV)。 我們將使用這些縮寫(xiě) 礼搁。

一饶碘、CSV數(shù)據(jù)

CSV 文件(簡(jiǎn)稱(chēng)為 CSV)是指將數(shù)據(jù)列用逗號(hào)分隔的文件。文件的擴(kuò)展名是 .csv馒吴。

另一種數(shù)據(jù)類(lèi)型扎运,叫作制表符分隔值(tab-separated values,TSV)數(shù)據(jù)饮戳,有時(shí)也與 CSV歸為一類(lèi)豪治。TSV 與 CSV 唯一的不同之處在于,數(shù)據(jù)列之間的分隔符是制表符(tab)扯罐,而不是逗號(hào)负拟。文件的擴(kuò)展名通常是 .tsv,但有時(shí)也用 .csv 作為擴(kuò)展名歹河。從本質(zhì)上來(lái)看掩浙,.tsv 文件與 .csv 文件在Python 中的作用是相同的花吟。

我們采用的數(shù)據(jù)源是從世界衛(wèi)生組織(https://www.who.int/zh/home)中下載的數(shù)據(jù)。

打開(kāi)世衛(wèi)組織官網(wǎng)后厨姚,點(diǎn)擊“健康主題”衅澈,“數(shù)據(jù)和統(tǒng)計(jì)” 就能找到很多數(shù)據(jù)。

image

這里下載了關(guān)于嬰幼兒護(hù)理的統(tǒng)計(jì)數(shù)據(jù)谬墙,并重命名為 data.csv今布。

csv 文件可以直接用 Excel 打開(kāi)直觀(guān)的看到,我們用 Excel 打開(kāi)如下圖:

image

接下來(lái)就要用 Python 來(lái)簡(jiǎn)單的處理這些數(shù)據(jù)拭抬。

以列表的形式讀取csv數(shù)據(jù)

編寫(xiě)一個(gè)讀取 csv 文件的程序:

import csv

csvfile = open('./data.csv', 'r')
reader = csv.reader(csvfile)

for row in reader:
    print(row)

import csv 將導(dǎo)入 Python 自帶的 csv 模塊险耀。csvfile = open('./data.csv', 'r') 以只讀的形式打開(kāi)數(shù)據(jù)文件并存儲(chǔ)到變量 csvfile 中。然后調(diào)用 csv 的 reader() 方法將輸出保存在 reader 變量中玖喘,再用 for 循環(huán)將數(shù)據(jù)輸出。

運(yùn)行程序蘑志,控制臺(tái)輸出:

image

可以看到跟 Excel 打開(kāi)的內(nèi)容一致累奈。

以字典的形式讀取csv數(shù)據(jù)

改一下代碼,以字典的形式讀取 csv

import csv

csvfile = open('./data.csv', 'r')
reader = csv.DictReader(csvfile)

for row in reader:
    print(row)

控制臺(tái)輸出:

image

二急但、JSON數(shù)據(jù)

同樣在世衛(wèi)組織官網(wǎng)下載數(shù)據(jù)源澎媒,重命名為 data.json。用格式化工具打開(kāi) json 文件如下:

image

編寫(xiě)程序?qū)?json 進(jìn)行解析

import json

# 將 json 文件讀取成字符串
json_data = open('./data.json').read()
# 對(duì)json數(shù)據(jù)解碼
data = json.loads(json_data)
# data 的類(lèi)型是 字典dict
print(type(data))
# 直接打印 data
print(data)
# 遍歷字典
for k, v in data.items():
    print(k + ':' + str(v))

控制臺(tái)輸出:

image

Python3 中可以使用 json 模塊來(lái)對(duì) JSON 數(shù)據(jù)進(jìn)行編解碼波桩,它包含了兩個(gè)函數(shù):

  • json.dumps(): 對(duì)數(shù)據(jù)進(jìn)行編碼戒努。
  • json.loads(): 對(duì)數(shù)據(jù)進(jìn)行解碼。

在json的編解碼過(guò)程中镐躲,python 的原始類(lèi)型與json類(lèi)型會(huì)相互轉(zhuǎn)換储玫,具體的轉(zhuǎn)化對(duì)照如下:

Python 編碼為 JSON 類(lèi)型轉(zhuǎn)換對(duì)應(yīng)表:

Python JSON
dict object
list, tuple array
str string
int, float, int- & float-derived Enums number
True true
False false
None null

JSON 解碼為 Python 類(lèi)型轉(zhuǎn)換對(duì)應(yīng)表:

JSON Python
object dict
array list
string str
number (int) int
number (real) float
true True
false False
null None

三、XML 數(shù)據(jù)

XML 格式的數(shù)據(jù)既便于機(jī)器讀取萤皂,也便于人工讀取撒穷。但是對(duì)于本章的數(shù)據(jù)集來(lái)說(shuō),預(yù)覽并理解 CSV 文件和 JSON 文件要比 XML 文件容易得多裆熙。

xml 格式說(shuō)明:

  • Tag: 使用<和>包圍的部分端礼;
  • Element:被Tag包圍的部分,如 2003入录,可以認(rèn)為是一個(gè)節(jié)點(diǎn)蛤奥,它可以有子節(jié)點(diǎn);
  • Attribute:在Tag中可能存在的 name/value 對(duì)僚稿,如示例中的 title="Enemy Behind"凡桥,一般表示屬性。

世衛(wèi)組織的數(shù)據(jù)不好理解蚀同,咱們用個(gè)簡(jiǎn)單的能看得懂的電影數(shù)據(jù)來(lái)做演示:

<?xml version="1.0" encoding="UTF-8"?>
<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>

這個(gè)數(shù)據(jù)相對(duì)來(lái)說(shuō)比較簡(jiǎn)單唬血,只有三層望蜡。但原理掌握了,幾層數(shù)據(jù)都能搞定拷恨。

下面編寫(xiě)代碼對(duì)上面的 xml 進(jìn)行解析脖律,解析之后再分別格式化成字典和 json 格式的數(shù)據(jù)輸出:

from xml.etree import ElementTree as ET
import json

tree = ET.parse('./resource/movie.xml')
root = tree.getroot()

all_data = []

for movie in root:
    # 存儲(chǔ)電影數(shù)據(jù)的字典
    movie_data = {}
    # 存儲(chǔ)屬性的字典
    attr_data = {}

    # 取出 type 標(biāo)簽的值
    movie_type = movie.find('type')
    attr_data['type'] = movie_type.text

    # 取出 format 標(biāo)簽的值
    movie_format = movie.find('format')
    attr_data['format'] = movie_format.text

    # 取出 year 標(biāo)簽的值
    movie_year = movie.find('year')
    if movie_year:
        attr_data['year'] = movie_year.text

    # 取出 rating 標(biāo)簽的值
    movie_rating = movie.find('rating')
    attr_data['rating'] = movie_rating.text

    # 取出 stars 標(biāo)簽的值
    movie_stars = movie.find('stars')
    attr_data['stars'] = movie_stars.text

    # 取出 description 標(biāo)簽的值
    movie_description = movie.find('description')
    attr_data['description'] = movie_description.text

    # 獲取電影名字,以電影名為字典的鍵腕侄,屬性信息為字典的值
    movie_title = movie.attrib.get('title')
    movie_data[movie_title] = attr_data
    # 存入列表中
    all_data.append(movie_data)

print(all_data)
# all_data 此時(shí)是一個(gè)列表對(duì)象小泉,用 json.dumps() 將python對(duì)象轉(zhuǎn)換為 json 字符串
json_str = json.dumps(all_data)
print(json_str)

注釋寫(xiě)的比較詳細(xì),下面介紹下 ElementTree 提供的方法冕杠。

3.1 解析的三種方法

ElementTree 解析 xml 有三種方法:

  1. 調(diào)用parse()方法微姊,返回解析樹(shù)

    tree = ET.parse('./resource/movie.xml')
    root = tree.getroot()
    
  2. 調(diào)用from_string(),返回解析樹(shù)的根元素

    data = open('./resource/movie.xml').read()
    root = ET.fromstring(data)
    
  3. 調(diào)用 ElementTree 類(lèi)的 ElementTree(self, element=None, file=None) 方法

    tree = ET.ElementTree(file="./resource/movie.xml")
    root = tree.getroot() 
    

3.2 Element 對(duì)象

class xml.etree.ElementTree.Element(tag, attrib={}, **extra)

Element 對(duì)象的屬性

  • tag: 標(biāo)簽
  • text: 去除標(biāo)簽,獲得標(biāo)簽中的內(nèi)容分预。
  • attrib: 獲取標(biāo)簽中的屬性和屬性值兢交。
  • tail: 這個(gè)屬性可以用來(lái)保存與元素相關(guān)聯(lián)的附加數(shù)據(jù)。它的值通常是字符串笼痹,但可能是特定于應(yīng)用程序的對(duì)象配喳。

Element 對(duì)象的方法

  1. clear():清除所有子元素和所有屬性,并將文本和尾部屬性設(shè)置為None凳干。

  2. get(attribute_name, default=None):通過(guò)指定屬性名獲取屬性值晴裹。

  3. items():以鍵值對(duì)的形式返回元素屬性。

  4. keys():以列表的方式返回元素名救赐。

  5. set(attribute_name,attribute_value):在某標(biāo)簽中設(shè)置屬性和屬性值涧团。

  6. append(subelement):將元素子元素添加到元素的子元素內(nèi)部列表的末尾。

  7. extend(subelements):追加子元素经磅。

  8. find(match, namespaces=None):找到第一個(gè)匹配的子元素泌绣,match可以是標(biāo)簽名或者path。返回Elememt實(shí)例或None预厌。

  9. findall(match, namespaces=None):找到所有匹配的子元素赞别,返回的是一個(gè)元素列表。

  10. findtext(match, default=None, namespaces=None):找到匹配第一個(gè)子元素的文本配乓。返回的是匹配元素中的文本內(nèi)容仿滔。

  11. getchildren():Python3.2后使用 list(elem) 或 iteration.

  12. getiterator(tag=None):Python3.2后使用 Element.iter()

  13. iter(tag=None):以當(dāng)前元素為根創(chuàng)建樹(shù)迭代器。迭代器遍歷這個(gè)元素和它下面的所有元素(深度優(yōu)先級(jí))犹芹。如果標(biāo)簽不是None或’*’崎页,那么只有標(biāo)簽等于標(biāo)簽的元素才會(huì)從迭代器返回。如果在迭代過(guò)程中修改樹(shù)結(jié)構(gòu)腰埂,則結(jié)果是未定義的飒焦。

  14. iterfind(match, namespaces=None): 匹配滿(mǎn)足條件的子元素,返回元素。

3.3 ElementTree 對(duì)象

class xml.etree.ElementTree.ElementTree(element=None, file=None)

ElementTree是一個(gè)包裝器類(lèi)牺荠,這個(gè)類(lèi)表示一個(gè)完整的元素層次結(jié)構(gòu)翁巍,并為標(biāo)準(zhǔn)XML的序列化添加了一些額外的支持。

  1. setroot(element):替換根元素休雌,原來(lái)的根元素中的內(nèi)容會(huì)消失灶壶。

  2. find(match, namespaces=None):從根元素開(kāi)始匹配和 Element.find()作用一樣。

  3. findall(match, namespaces=None):從根元素開(kāi)始匹配和 Element.findall()作用一樣杈曲。

  4. findtext(match, default=None, namespaces=None):從根元素開(kāi)始匹配和 Element.findtext()作用一樣驰凛。

  5. getiterator(tag=None):Python3.2后使用 ElementTree.iter() 代替。

  6. iter(tag=None):迭代所有元素

  7. iterfind(match, namespaces=None):從根元素開(kāi)始匹配和 Element.iterfind()作用一樣担扑。

  8. parse(source, parser=None):解析xml文本恰响,返回根元素。

  9. write(file, encoding=”us-ascii”, xml_declaration=None, default_namespace=None, method=”xml”, *, short_empty_elements=True):寫(xiě)出XML文本涌献。

對(duì) JSON胚宦、XML、CSV三種格式數(shù)據(jù)的處理就講完啦燕垃,下期講如何處理 Excel 文件枢劝,歡迎關(guān)注。


全棧全平臺(tái)開(kāi)源項(xiàng)目 CodeRiver

CodeRiver 是一個(gè)免費(fèi)的項(xiàng)目協(xié)作平臺(tái)利术,愿景是打通 IT 產(chǎn)業(yè)上下游,無(wú)論你是產(chǎn)品經(jīng)理低矮、設(shè)計(jì)師印叁、程序員或是測(cè)試情屹,還是其他行業(yè)人員溅蛉,只要有好的創(chuàng)意、想法收壕,都可以來(lái) CodeRiver 免費(fèi)發(fā)布項(xiàng)目蝗锥,召集志同道合的隊(duì)友一起將夢(mèng)想變?yōu)楝F(xiàn)實(shí)跃洛!

CodeRiver 本身還是一個(gè)大型開(kāi)源項(xiàng)目,致力于打造全棧全平臺(tái)企業(yè)級(jí)精品開(kāi)源項(xiàng)目终议。涵蓋了 React汇竭、Vue、Angular穴张、小程序细燎、ReactNative、Android皂甘、Flutter玻驻、Java、Node 等幾乎所有主流技術(shù)棧偿枕,主打代碼質(zhì)量璧瞬。

目前已經(jīng)有近 100 名優(yōu)秀開(kāi)發(fā)者參與户辫,github 上的 star 數(shù)量將近 1000 個(gè)。每個(gè)技術(shù)棧都有多位經(jīng)驗(yàn)豐富的大佬坐鎮(zhèn)嗤锉,更有兩位架構(gòu)師指導(dǎo)項(xiàng)目架構(gòu)渔欢。無(wú)論你想學(xué)什么語(yǔ)言處于什么技術(shù)水平,相信都能在這里學(xué)有所獲档冬。

通過(guò) 高質(zhì)量源碼 + 博客 + 視頻膘茎,幫助每一位開(kāi)發(fā)者快速成長(zhǎng)。

項(xiàng)目地址:https://github.com/cachecats/coderiver


您的鼓勵(lì)是我們前行最大的動(dòng)力酷誓,歡迎點(diǎn)贊披坏,歡迎送小星星? ~

image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市盐数,隨后出現(xiàn)的幾起案子棒拂,更是在濱河造成了極大的恐慌,老刑警劉巖玫氢,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帚屉,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡漾峡,警方通過(guò)查閱死者的電腦和手機(jī)攻旦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)生逸,“玉大人牢屋,你說(shuō)我怎么就攤上這事〔郯溃” “怎么了烙无?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)遍尺。 經(jīng)常有香客問(wèn)我截酷,道長(zhǎng),這世上最難降的妖魔是什么乾戏? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任迂苛,我火速辦了婚禮,結(jié)果婚禮上鼓择,老公的妹妹穿的比我還像新娘灾部。我一直安慰自己,他們只是感情好惯退,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布赌髓。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锁蠕。 梳的紋絲不亂的頭發(fā)上夷野,一...
    開(kāi)封第一講書(shū)人閱讀 51,598評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音荣倾,去河邊找鬼悯搔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛舌仍,可吹牛的內(nèi)容都是我干的妒貌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼铸豁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼灌曙!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起节芥,我...
    開(kāi)封第一講書(shū)人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤在刺,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后头镊,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蚣驼,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年相艇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了颖杏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡坛芽,死狀恐怖留储,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情靡馁,我是刑警寧澤欲鹏,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布机久,位于F島的核電站臭墨,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏膘盖。R本人自食惡果不足惜胧弛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望侠畔。 院中可真熱鬧结缚,春花似錦、人聲如沸软棺。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至茵宪,卻和暖如春最冰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背稀火。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工暖哨, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人凰狞。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓篇裁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親赡若。 傳聞我的和親對(duì)象是個(gè)殘疾皇子达布,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • pyspark.sql模塊 模塊上下文 Spark SQL和DataFrames的重要類(lèi): pyspark.sql...
    mpro閱讀 9,456評(píng)論 0 13
  • 一. XML數(shù)據(jù)交換格式 XML數(shù)據(jù)交換格式是一種自描述的數(shù)據(jù)交互格式,雖然XML數(shù)據(jù)格式不如JSON "輕便"斩熊,...
    __season____閱讀 2,512評(píng)論 0 7
  • # XML復(fù)習(xí) ## 第一章 ## 思考題 **什么是XML往枣?** XML是可擴(kuò)展性標(biāo)記語(yǔ)言,XML是標(biāo)準(zhǔn)通用標(biāo)記...
    冷漠鐵錘丁富貴閱讀 806評(píng)論 0 0
  • 王陽(yáng)明心學(xué)看眾籌二十五:心是快樂(lè)的根粉渠。王陽(yáng)明曰:撤指裕快活便是功夫。人生難免起起落落霸株,保持一顆快樂(lè)的心很難雕沉,人總會(huì)遇到...
    執(zhí)著的石頭閱讀 452評(píng)論 0 0
  • 從6月17日開(kāi)始記錄第1次冥想,到8月21日完成第30次冥想去件,用時(shí)2個(gè)月的時(shí)間坡椒,這就是記錄的好處。 如果我沒(méi)有做過(guò)...
    恒心者閱讀 178評(píng)論 0 2