国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Python 自動化指南(繁瑣工作自動化)第二版:十六、使用 CSV 文件和 JSON 數(shù)據(jù)

這篇具有很好參考價值的文章主要介紹了Python 自動化指南(繁瑣工作自動化)第二版:十六、使用 CSV 文件和 JSON 數(shù)據(jù)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

原文:https://automatetheboringstuff.com/2e/chapter16/

Python 自動化指南(繁瑣工作自動化)第二版:十六、使用 CSV 文件和 JSON 數(shù)據(jù)

在第 15 章,你學(xué)習(xí)了如何從 PDF 和 Word 文檔中提取文本。這些文件是二進(jìn)制格式的,需要特殊的 Python 模塊來訪問它們的數(shù)據(jù)。另一方面,CSV 和 JSON 文件只是純文本文件。您可以在文本編輯器(如 Mu)中查看它們。但是 Python 還附帶了特殊的csvjson模塊,每個模塊都提供了幫助您處理這些文件格式的函數(shù)。

CSV 代表“逗號分隔值”,CSV 文件是存儲為純文本文件的簡化電子表格。Python 的csv模塊使得解析 CSV 文件變得很容易。

JSON(讀作“JAY-saw”或“Jason”——怎么讀并不重要,因為人們會說你讀錯了)是一種將信息作為 JavaScript 源代碼存儲在純文本文件中的格式。(JSON 是 JavaScript 對象符號的縮寫。)使用 JSON 文件不需要了解 JavaScript 編程語言,但是了解 JSON 格式很有用,因為它在許多 Web 應(yīng)用中使用。

CSV 模塊

CSV 文件中的每一行代表電子表格中的一行,行中的單元格用逗號分隔。例如,的電子表格example.xlsx在一個 CSV 文件中會是這樣的:

4/5/2015 13:34,Apples,73
4/5/2015 3:41,Cherries,85
4/6/2015 12:46,Pears,14
4/8/2015 8:59,Oranges,52
4/10/2015 2:07,Apples,152
4/10/2015 18:10,Bananas,23
4/10/2015 2:40,Strawberries,98

我將在本章的交互式 Shell 示例中使用這個文件。您可以從下載example.csv或者在文本編輯器中輸入文本并保存為example.csv。

CSV 文件很簡單,缺少 Excel 電子表格的許多功能。例如,CSV 文件:

  • 它們的值沒有類型——一切都是字符串
  • 沒有字體大小或顏色的設(shè)置
  • 沒有多個工作表
  • 無法指定單元格的寬度和高度
  • 不能有合并單元格
  • 不能嵌入圖像或圖表

CSV 文件的優(yōu)點是簡單。CSV 文件被許多類型的程序廣泛支持,可以在文本編輯器(包括 Mu)中查看,并且是表示電子表格數(shù)據(jù)的一種直接方式。CSV 格式與廣告中的完全一樣:它只是一個由逗號分隔的值組成的文本文件。

由于 CSV 文件只是文本文件,您可能會嘗試將它們作為字符串讀入,然后使用您在第 9 章中學(xué)到的技術(shù)處理該字符串。例如,由于 CSV 文件中的每個單元格都由逗號分隔,所以您可以在每行文本上調(diào)用split(',')來獲取逗號分隔的值作為字符串列表。但并不是 CSV 文件中的每個逗號都代表兩個單元格之間的邊界。CSV 文件也有自己的轉(zhuǎn)義字符集,允許逗號和其他字符作為值的一部分包含在其中。split()方法不處理這些轉(zhuǎn)義字符。因為這些潛在的陷阱,你應(yīng)該總是使用csv模塊來讀寫 CSV 文件。

reader對象

要用csv模塊從 CSV 文件中讀取數(shù)據(jù),您需要創(chuàng)建一個reader對象。一個reader對象讓你遍歷 CSV 文件中的行。在交互 Shell 中輸入以下內(nèi)容,當(dāng)前工作目錄中有example.csv :

   >>> import csv # ?
   >>> exampleFile = open('example.csv') # ?
   >>> exampleReader = csv.reader(exampleFile) # ?
   >>> exampleData = list(exampleReader) # ?
   >>> exampleData # ?
   [['4/5/2015 13:34', 'Apples', '73'], ['4/5/2015 3:41', 'Cherries', '85'],
   ['4/6/2015 12:46', 'Pears', '14'], ['4/8/2015 8:59', 'Oranges', '52'],
   ['4/10/2015 2:07', 'Apples', '152'], ['4/10/2015 18:10', 'Bananas', '23'],
   ['4/10/2015 2:40', 'Strawberries', '98']]

Python 自帶了csv模塊,所以我們可以導(dǎo)入它 ? 而不必先安裝它。

要使用csv模塊讀取一個 CSV 文件,首先使用open()函數(shù) ? 打開它,就像您處理任何其他文本文件一樣。但不是在open()返回的File對象上調(diào)用read()readlines()方法,而是將其傳遞給csv.reader()函數(shù) ?。這將返回一個reader對象供您使用。注意,您沒有將文件名字符串直接傳遞給csv.reader()函數(shù)。

訪問reader對象中的值的最直接的方法是通過將它傳遞給list()? 來將其轉(zhuǎn)換成普通的 Python 列表。在這個reader對象上使用list()會返回一個列表列表,您可以將它存儲在一個類似exampleData的變量中。在 Shell 中輸入exampleData顯示列表列表 ?。

現(xiàn)在您已經(jīng)將 CSV 文件作為一個列表列表,您可以使用表達(dá)式exampleData[row][col]訪問特定行和列的值,其中rowexampleData中一個列表的索引,col是您希望從該列表中獲得的項目的索引。在交互式 Shell 中輸入以下內(nèi)容:

>>> exampleData[0][0]
'4/5/2015 13:34'
>>> exampleData[0][1]
'Apples'
>>> exampleData[0][2]
'73'
>>> exampleData[1][1]
'Cherries'
>>> exampleData[6][1]
'Strawberries'

從輸出中可以看到,exampleData[0][0]進(jìn)入第一個列表并給出第一個字符串,exampleData[0][2]進(jìn)入第一個列表并給出第三個字符串,依此類推。

for循環(huán)中從reader對象中讀取數(shù)據(jù)

對于大的 CSV 文件,您將希望在一個for循環(huán)中使用reader對象。這避免了一次將整個文件加載到內(nèi)存中。例如,在交互式 Shell 中輸入以下內(nèi)容:

>>> import csv
>>> exampleFile = open('example.csv')
>>> exampleReader = csv.reader(exampleFile)
>>> for row in exampleReader:
        print('Row #' + str(exampleReader.line_num) + ' ' + str(row))
Row #1 ['4/5/2015 13:34', 'Apples', '73']
Row #2 ['4/5/2015 3:41', 'Cherries', '85']
Row #3 ['4/6/2015 12:46', 'Pears', '14']
Row #4 ['4/8/2015 8:59', 'Oranges', '52']
Row #5 ['4/10/2015 2:07', 'Apples', '152']
Row #6 ['4/10/2015 18:10', 'Bananas', '23']
Row #7 ['4/10/2015 2:40', 'Strawberries', '98']

在您導(dǎo)入了csv模塊并從 CSV 文件中創(chuàng)建了一個reader對象之后,您可以遍歷reader對象中的行。每行是一個值列表,每個值代表一個單元格。

print()函數(shù)調(diào)用打印當(dāng)前行的編號和該行的內(nèi)容。要獲得行號,使用reader對象的line_num變量,它包含當(dāng)前行的行號。

reader對象只能循環(huán)一次。要重新讀取 CSV 文件,您必須調(diào)用csv.reader來創(chuàng)建一個reader對象。

writer對象

一個writer對象允許你將數(shù)據(jù)寫入一個 CSV 文件。要創(chuàng)建一個writer對象,可以使用csv.writer()函數(shù)。在交互式 Shell 中輸入以下內(nèi)容:

   >>> import csv
   >>> outputFile = open('output.csv', 'w', newline='') # ?
   >>> outputWriter = csv.writer(outputFile) # ?
   >>> outputWriter.writerow(['spam', 'eggs', 'bacon', 'ham'])
   21
   >>> outputWriter.writerow(['Hello, world!', 'eggs', 'bacon', 'ham'])
   32
   >>> outputWriter.writerow([1, 2, 3.141592, 4])
   16
   >>> outputFile.close()

首先調(diào)用open()并傳遞'w'以寫模式打開一個文件 ?。這將創(chuàng)建一個對象,然后你可以傳遞給csv.writer()? 來創(chuàng)建一個writer對象。

在 Windows 上,您還需要為open()函數(shù)的newline關(guān)鍵字參數(shù)傳遞一個空字符串。由于超出本書范圍的技術(shù)原因,如果你忘記設(shè)置newline參數(shù),那么output.csv中的行將是雙倍行距,如圖圖 16-1 所示。

Python 自動化指南(繁瑣工作自動化)第二版:十六、使用 CSV 文件和 JSON 數(shù)據(jù)

圖 16-1:如果你忘記了open()中的newline=''關(guān)鍵字參數(shù),CSV 文件將會是雙倍行距。

writer對象的writerow()方法接受一個列表參數(shù)。列表中的每個值都放在輸出 CSV 文件中自己的單元格中。writerow()的返回值是寫入文件中該行的字符數(shù)(包括換行符)。

這段代碼生成一個類似于下面的output.csv文件:

spam,eggs,bacon,ham
"Hello, world!",eggs,bacon,ham
1,2,3.141592,4

注意在 CSV 文件中,writer對象是如何用雙引號自動轉(zhuǎn)義值'Hello, world!'中的逗號的。csv模塊讓您不必親自處理這些特殊情況。

delimiterlineterminator關(guān)鍵字參數(shù)

假設(shè)您希望用制表符而不是逗號來分隔單元格,并且希望行是雙倍行距。您可以在交互式 Shell 中輸入如下內(nèi)容:

   >>> import csv
   >>> csvFile = open('example.tsv', 'w', newline='')
   >>> csvWriter = csv.writer(csvFile, delimiter='\t', lineterminator='\n\n') # ?
   >>> csvWriter.writerow(['apples', 'oranges', 'grapes'])
   24
   >>> csvWriter.writerow(['eggs', 'bacon', 'ham'])
   17
   >>> csvWriter.writerow(['spam', 'spam', 'spam', 'spam', 'spam', 'spam'])
   32
   >>> csvFile.close()

這將更改文件中的分隔符和行結(jié)束符。分隔符是出現(xiàn)在一行單元格之間的字符。默認(rèn)情況下,CSV 文件的分隔符是逗號。行結(jié)束符是出現(xiàn)在一行末尾的字符。默認(rèn)情況下,行結(jié)束符是換行符。您可以通過使用帶有csv.writer()delimiterlineterminator關(guān)鍵字參數(shù)將字符更改為不同的值。

傳遞delimiter='\t'lineterminator='\n\n'? 將單元格之間的字符更改為制表符,將行之間的字符更改為兩個換行符。然后我們調(diào)用writerow()三次,得到三行。

這將生成一個名為example.tsv的文件,其內(nèi)容如下:

apples  oranges grapes
eggs    bacon   ham
spam    spam    spam    spam    spam    spam    

現(xiàn)在我們的單元格由制表符分隔,我們使用文件擴(kuò)展名tsv,用于制表符分隔的值。

DictReaderDictWriter CSV 對象

對于包含標(biāo)題行的 CSV 文件,使用DictReaderDictWriter對象通常比使用readerwriter對象更方便。

readerwriter對象通過使用列表讀寫 CSV 文件行。DictReaderDictWriter CSV 對象執(zhí)行相同的功能,但是使用字典,它們使用 CSV 文件的第一行作為這些字典的鍵。

前往下載exampleWithHeader.csv文件。這個文件與example.csv相同,除了它在第一行中有時間戳、水果和數(shù)量作為列標(biāo)題。

要讀取該文件,請在交互式 Shell 中輸入以下內(nèi)容:

>>> import csv
>>> exampleFile = open('exampleWithHeader.csv')
>>> exampleDictReader = csv.DictReader(exampleFile)
>>> for row in exampleDictReader:
...     print(row['Timestamp'], row['Fruit'], row['Quantity'])
...
4/5/2015 13:34 Apples 73
4/5/2015 3:41 Cherries 85
4/6/2015 12:46 Pears 14
4/8/2015 8:59 Oranges 52
4/10/2015 2:07 Apples 152
4/10/2015 18:10 Bananas 23
4/10/2015 2:40 Strawberries 98

在循環(huán)內(nèi)部,DictReader object 將row設(shè)置為一個字典對象,其鍵來自第一行的標(biāo)題。(嗯,從技術(shù)上來說,它將row設(shè)置為一個OrderedDict對象,你可以像使用字典一樣使用它;它們之間的區(qū)別超出了本書的范圍。)使用一個DictReader對象意味著你不需要額外的代碼來跳過第一行的標(biāo)題信息,因為DictReader對象為你做了這件事。

如果您試圖將DictReader對象與第一行沒有列標(biāo)題的example.csv一起使用,DictReader對象將使用'4/5/2015 13:34'、'Apples''73'作為字典鍵。為了避免這種情況,您可以為DictReader()函數(shù)提供第二個參數(shù),其中包含虛構(gòu)的頭名稱:

>>> import csv
>>> exampleFile = open('example.csv')
>>> exampleDictReader = csv.DictReader(exampleFile, ['time', 'name',
'amount'])
>>> for row in exampleDictReader:
...     print(row['time'], row['name'], row['amount'])
...
4/5/2015 13:34 Apples 73
4/5/2015 3:41 Cherries 85
4/6/2015 12:46 Pears 14
4/8/2015 8:59 Oranges 52
4/10/2015 2:07 Apples 152
4/10/2015 18:10 Bananas 23
4/10/2015 2:40 Strawberries 98

因為example.csv的第一行沒有任何用于每列標(biāo)題的文本,所以我們創(chuàng)建了自己的:'time'、'name''amount'。

DictWriter對象使用字典創(chuàng)建 CSV 文件。

>>> import csv
>>> outputFile = open('output.csv', 'w', newline='')
>>> outputDictWriter = csv.DictWriter(outputFile, ['Name', 'Pet', 'Phone'])
>>> outputDictWriter.writeheader()
>>> outputDictWriter.writerow({'Name': 'Alice', 'Pet': 'cat', 'Phone': '555-
1234'})
20
>>> outputDictWriter.writerow({'Name': 'Bob', 'Phone': '555-9999'})
15
>>> outputDictWriter.writerow({'Phone': '555-5555', 'Name': 'Carol', 'Pet':
'dog'})
20
>>> outputFile.close()

如果您希望您的文件包含一個標(biāo)題行,通過調(diào)用writeheader()來編寫該行。否則,跳過調(diào)用writeheader()從文件中省略一個標(biāo)題行。然后用一個writerow()方法調(diào)用寫入 CSV 文件的每一行,傳遞一個字典,該字典使用文件頭作為鍵,包含要寫入文件的數(shù)據(jù)。

這段代碼創(chuàng)建的output.csv文件如下所示:

Name,Pet,Phone
Alice,cat,555-1234
Bob,,555-9999
Carol,dog,555-5555

注意,你傳遞給writerow()的字典中鍵-值對的順序并不重要:它們是按照給DictWriter()的鍵的順序編寫的。例如,即使您在第四行的NamePet鍵和值之前傳遞了Phone鍵和值,電話號碼仍然出現(xiàn)在輸出的最后。

還要注意,任何丟失的鍵,比如{'Name': 'Bob', 'Phone': '555-9999'}中的'Pet',在 CSV 文件中都會是空的。

項目:從 CSV 文件中移除文件頭

假設(shè)您有一份從數(shù)百個 CSV 文件中刪除第一行的枯燥工作。也許您會將它們輸入到一個自動化的流程中,該流程只需要數(shù)據(jù),而不需要列頂部的標(biāo)題。你可以在 Excel 中打開每個文件,刪除第一行,然后重新保存文件——但這需要幾個小時。讓我們寫一個程序來代替它。

該程序?qū)⑿枰蜷_當(dāng)前工作目錄下每個csv擴(kuò)展名的文件,讀入 CSV 文件的內(nèi)容,將沒有第一行的內(nèi)容重寫到同名文件中。這將用新的無頭內(nèi)容替換 CSV 文件的舊內(nèi)容。

警告

和往常一樣,每當(dāng)你編寫一個修改文件的程序時,一定要先備份這些文件,以防你的程序不按你期望的方式運行。你不想意外刪除你的原始文件。

在高層次上,程序必須做到以下幾點:

  1. 在當(dāng)前工作目錄中查找所有 CSV 文件。
  2. 讀入每個文件的全部內(nèi)容。
  3. 跳過第一行,將內(nèi)容寫入一個新的 CSV 文件。

在代碼級別,這意味著程序需要做以下事情:

  1. os.listdir()開始循環(huán)文件列表,跳過非 CSV 文件。
  2. 創(chuàng)建一個 CSV reader對象并讀入文件的內(nèi)容,使用line_num屬性來決定跳過哪一行。
  3. 創(chuàng)建一個 CSV writer對象并將讀入的數(shù)據(jù)寫出到新文件中。

對于這個項目,打開一個新的文件編輯器窗口,保存為removeCsvHeader.py。

第一步:遍歷每個 CSV 文件

您的程序需要做的第一件事是遍歷當(dāng)前工作目錄的所有 CSV 文件名的列表。讓您的removeCsvHeader.py看起來像這樣:

#! python3
# removeCsvHeader.py - Removes the header from all CSV files in the current
# working directory.
import csv, os
os.makedirs('headerRemoved', exist_ok=True)
# Loop through every file in the current working directory.
for csvFilename in os.listdir('.'):
     if not csvFilename.endswith('.csv'):
         continue    # skip non-csv files # ?
     print('Removing header from ' + csvFilename + '...')
     # TODO: Read the CSV file in (skipping first row).
     # TODO: Write out the CSV file.

調(diào)用os.makedirs()將創(chuàng)建一個headerRemoved文件夾,所有的無頭 CSV 文件將被寫入其中。在os.listdir('.')上的一個for循環(huán)可以讓你完成一部分,但是它會遍歷工作目錄中的所有文件,所以你需要在循環(huán)的開始添加一些代碼,跳過不以.csv結(jié)尾的文件名。當(dāng)遇到非 CSV 文件時,continue語句 ? 使for循環(huán)移動到下一個文件名。

程序運行時會有一些輸出,打印出一條消息,說明程序正在處理哪個 CSV 文件。然后,添加一些關(guān)于程序其余部分應(yīng)該做什么的TODO注釋。

第二步:讀入 CSV 文件

程序不會刪除 CSV 文件的第一行。相反,它創(chuàng)建一個沒有第一行的 CSV 文件的新副本。由于副本的文件名與原始文件名相同,副本將覆蓋原始文件名。

程序需要一種方法來跟蹤它當(dāng)前是否在第一行循環(huán)。將以下內(nèi)容添加到removeCsvHeader.py中。

#! python3
# removeCsvHeader.py - Removes the header from all CSV files in the current 
# working directory.
--snip--
    # Read the CSV file in (skipping first row).
    csvRows = []
    csvFileObj = open(csvFilename)
    readerObj = csv.reader(csvFileObj)
    for row in readerObj:
        if readerObj.line_num == 1:
            continue    # skip first row
        csvRows.append(row)
    csvFileObj.close()
    # TODO: Write out the CSV file.

reader對象的line_num屬性可用于確定它當(dāng)前正在讀取 CSV 文件中的哪一行。另一個for循環(huán)將遍歷從 CSV reader對象返回的行,除了第一行之外的所有行將被附加到csvRows

當(dāng)for循環(huán)遍歷每一行時,代碼檢查readerObj.line_num是否被設(shè)置為1。如果是,它執(zhí)行一個continue來移動到下一行,而不把它附加到csvRows。對于之后的每一行,條件將始終為False,并且該行將被附加到csvRows。

第三步:寫出沒有第一行的 CSV 文件

現(xiàn)在csvRows包含了除第一行之外的所有行,這個列表需要寫到headerRemoved文件夾中的一個 CSV 文件中。將以下內(nèi)容添加到removeCsvHeader.py :

   #! python3
   # removeCsvHeader.py - Removes the header from all CSV files in the current 
   # working directory.
   --snip--
   # Loop through every file in the current working directory.
   for csvFilename in os.listdir('.'): # ?
       if not csvFilename.endswith('.csv'):
           continue    # skip non-CSV files
       --snip--
       # Write out the CSV file.
       csvFileObj = open(os.path.join('headerRemoved', csvFilename), 'w',
                    newline='')
       csvWriter = csv.writer(csvFileObj)
       for row in csvRows:
           csvWriter.writerow(row)
       csvFileObj.close()

CSV writer對象將使用csvFilename(我們在 CSV 讀取器中也使用了它)將列表寫入到headerRemoved中的 CSV 文件中。這將覆蓋原始文件。

一旦我們創(chuàng)建了writer對象,我們就遍歷存儲在csvRows中的子列表,并將每個子列表寫入文件。

代碼執(zhí)行后,外層for循環(huán) ? 將從os.listdir('.')開始循環(huán)到下一個文件名。當(dāng)這個循環(huán)結(jié)束時,程序就完成了。

為了測試你的程序,從nostarch.com/automatestuff2下載removeCsvHeader.zip并解壓到一個文件夾中。運行該文件夾中的removeCsvHeader.py程序。輸出將如下所示:

Removing header from NAICS_data_1048.csv...
Removing header from NAICS_data_1218.csv...
--snip--
Removing header from NAICS_data_9834.csv...
Removing header from NAICS_data_9986.csv...

這個程序應(yīng)該在每次從 CSV 文件中刪除第一行時打印一個文件名。

類似程序的創(chuàng)意

您可以為 CSV 文件編寫的程序類似于您可以為 Excel 文件編寫的程序,因為它們都是電子表格文件。您可以編寫程序來完成以下任務(wù):

  • 比較一個 CSV 文件中不同行之間或多個 CSV 文件之間的數(shù)據(jù)。
  • 將特定數(shù)據(jù)從 CSV 文件復(fù)制到 Excel 文件,反之亦然。
  • 檢查 CSV 文件中的無效數(shù)據(jù)或格式錯誤,并提醒用戶注意這些錯誤。
  • 從 CSV 文件中讀取數(shù)據(jù)作為 Python 程序的輸入。

JSON 和 API

JavaScript 對象符號是將數(shù)據(jù)格式化為單個人類可讀字符串的一種流行方式。JSON 是 JavaScript 程序編寫數(shù)據(jù)結(jié)構(gòu)的原生方式,通常類似于 Python 的pprint()函數(shù)會產(chǎn)生的結(jié)果。為了處理 JSON 格式的數(shù)據(jù),您不需要了解 JavaScript。

下面是一個格式化為 JSON 的數(shù)據(jù)示例:

{"name": "Zophie", "isCat": true, 
 "miceCaught": 0, "napsTaken": 37.5, 
 "felineIQ": null}

了解 JSON 是很有用的,因為許多網(wǎng)站提供 JSON 內(nèi)容作為程序與網(wǎng)站交互的一種方式。這被稱為提供應(yīng)用編程接口(API) 。訪問 API 與通過 URL 訪問任何其他網(wǎng)頁是一樣的。區(qū)別在于 API 返回的數(shù)據(jù)是為機(jī)器格式化的(例如用 JSON );API 不容易讓人讀懂。

許多網(wǎng)站以 JSON 格式提供數(shù)據(jù)。Data.gov、推特、雅虎、谷歌、Tumblr、維基百科、Flickr、Reddit、IMDb、爛番茄、LinkedIn 和許多其他流行的網(wǎng)站都提供 API 供程序使用。其中一些網(wǎng)站需要注冊,而注冊幾乎總是免費的。為了獲得想要的數(shù)據(jù),您必須找到程序需要請求哪些 URL 的文檔,以及返回的 JSON 數(shù)據(jù)結(jié)構(gòu)的一般格式。這個文檔應(yīng)該由提供 API 的任何站點提供;如果他們有一個“開發(fā)者”頁面,在那里尋找文檔。

使用 API,您可以編寫執(zhí)行以下操作的程序:

  • 從網(wǎng)站上搜集原始數(shù)據(jù)。(訪問 API 往往比下載網(wǎng)頁和用 BeautifulSoup 解析 HTML 更方便。)
  • 自動從您的一個社交網(wǎng)絡(luò)帳戶下載新帖子,并將其發(fā)布到另一個帳戶。例如,你可以把你的 Tumblr 帖子發(fā)到臉書。
  • 從 IMDb、爛番茄和維基百科中提取數(shù)據(jù),放入你電腦上的一個文本文件中,為你的個人電影收藏創(chuàng)建一個“電影百科全書”。

您可以在參考資料中的看到一些 JSON APIs 的例子。

JSON 并不是將數(shù)據(jù)格式化為可讀字符串的唯一方法。還有許多其他格式,包括 XML(可擴(kuò)展標(biāo)記語言)、TOML (Tom 的顯而易見的最小化語言)、YML(另一種標(biāo)記語言)、INI(初始化),甚至是過時的 ASN.1(抽象語法符號一)格式,所有這些都提供了一種將數(shù)據(jù)表示為人類可讀文本的結(jié)構(gòu)。本書不會涉及這些,因為 JSON 已經(jīng)迅速成為使用最廣泛的替代格式,但是有第三方 Python 模塊可以輕松處理它們。

json模塊

Python 的json模塊為json.loads()json.dumps()函數(shù)處理帶有 JSON 數(shù)據(jù)的字符串和 Python 值之間轉(zhuǎn)換的所有細(xì)節(jié)。JSON 不能存儲每一種 Python 值。它只能包含以下數(shù)據(jù)類型的值:字符串、整數(shù)、浮點、布爾、列表、字典和NoneType。JSON 不能表示特定于 Python 的對象,比如File對象、CSV readerwriter對象、Regex對象或 Selenium WebElement對象。

loads()函數(shù)讀取 JSON

要將包含 JSON 數(shù)據(jù)的字符串轉(zhuǎn)換成 Python 值,請將其傳遞給json.loads()函數(shù)。(該名稱的意思是“加載字符串”,而不是“加載”)在交互式 Shell 中輸入以下內(nèi)容:

>>> stringOfJsonData = '{"name": "Zophie", "isCat": true, "miceCaught": 0,
"felineIQ": null}'
>>> import json
>>> jsonDataAsPythonValue = json.loads(stringOfJsonData)
>>> jsonDataAsPythonValue
{'isCat': True, 'miceCaught': 0, 'name': 'Zophie', 'felineIQ': None}

導(dǎo)入json模塊后,可以調(diào)用loads()并向其傳遞一串 JSON 數(shù)據(jù)。注意,JSON 字符串總是使用雙引號。它將以 Python 字典的形式返回數(shù)據(jù)。Python 字典不是按順序排列的,所以在打印jsonDataAsPythonValue時,鍵值對可能會以不同的順序出現(xiàn)。

編寫 JSON 與dumps()函數(shù)

json.dumps()函數(shù)(意思是“轉(zhuǎn)儲字符串”,而不是“轉(zhuǎn)儲”)將把 Python 值轉(zhuǎn)換成 JSON 格式的數(shù)據(jù)字符串。在交互式 Shell 中輸入以下內(nèi)容:

>>> pythonValue = {'isCat': True, 'miceCaught': 0, 'name': 'Zophie',
'felineIQ': None}
>>> import json
>>> stringOfJsonData = json.dumps(pythonValue)
>>> stringOfJsonData
'{"isCat": true, "felineIQ": null, "miceCaught": 0, "name": "Zophie" }'

該值只能是以下基本 Python 數(shù)據(jù)類型之一:字典、列表、整數(shù)、浮點、字符串、布爾或None。

項目:獲取當(dāng)前天氣數(shù)據(jù)

查看天氣似乎很簡單:打開你的網(wǎng)絡(luò)瀏覽器,點擊地址欄,輸入一個天氣網(wǎng)站的 URL(或者搜索一個然后點擊鏈接),等待頁面加載,瀏覽所有的廣告,等等。

實際上,如果你有一個程序可以下載未來幾天的天氣預(yù)報并以純文本格式打印出來,那么你可以跳過很多無聊的步驟。這個程序使用第 12 章中的requests模塊從網(wǎng)上下載數(shù)據(jù)。

總的來說,該程序完成了以下工作:

  1. 從命令行讀取請求的位置
  2. 從 OpenWeatherMap.org 下載 JSON 天氣數(shù)據(jù)
  3. 將 JSON 數(shù)據(jù)的字符串轉(zhuǎn)換為 Python 數(shù)據(jù)結(jié)構(gòu)
  4. 打印今天和未來兩天的天氣

因此,代碼需要執(zhí)行以下操作:

  1. 連接sys.argv中的字符串以獲得位置。
  2. 調(diào)用requests.get()下載天氣數(shù)據(jù)。
  3. 調(diào)用json.loads()將 JSON 數(shù)據(jù)轉(zhuǎn)換成 Python 數(shù)據(jù)結(jié)構(gòu)。
  4. 打印天氣預(yù)報。

對于這個項目,打開一個新的文件編輯器窗口,并將其保存為getOpenWeather.py。然后在你的瀏覽器中訪問openweathermap.org/api并注冊一個免費帳戶,以獲得一個 API 密鑰,也稱為應(yīng)用 ID,對于 OpenWeatherMap 服務(wù)來說,它是一個類似于'30144aba38018987d84710d0e319281e'的字符串代碼。除非你計劃每分鐘進(jìn)行 60 次以上的 API 調(diào)用,否則你不需要為這項服務(wù)付費。對 API 密鑰保密;任何知道它的人都可以編寫使用您帳戶的使用配額的腳本。

第一步:從命令行參數(shù)獲取位置

這個程序的輸入將來自命令行。使getOpenWeather.py看起來像這樣:

#! python3
# getOpenWeather.py - Prints the weather for a location from the command line.
APPID = 'YOUR_APPID_HERE'
import json, requests, sys
# Compute location from command line arguments.
if len(sys.argv) < 2:
    print('Usage: getOpenWeather.py city_name, 2-letter_country_code')
    sys.exit()
location = ' '.join(sys.argv[1:])
# TODO: Download the JSON data from OpenWeatherMap.org's API.
# TODO: Load JSON data into a Python variable.

在 Python 中,命令行參數(shù)存儲在sys.argv列表中。APPID變量應(yīng)該設(shè)置為您的帳戶的 API 密鑰。沒有這個密鑰,您對天氣服務(wù)的請求將會失敗。在#! shebang 行和import語句之后,程序?qū)z查是否有多個命令行參數(shù)。(回想一下,sys.argv總是至少有一個元素sys.argv[0],它包含 Python 腳本的文件名。)如果列表中只有一個元素,那么用戶沒有在命令行上提供位置,并且在程序結(jié)束之前將向用戶提供“用法”消息。

OpenWeatherMap 服務(wù)要求查詢格式為城市名、逗號和兩個字母的國家代碼(如“US”代表美國)。你可以在en.wikipedia.org/wiki/ISO_3166-1_alpha-2找到這些代碼的列表。我們的腳本顯示檢索到的 JSON 文本中列出的第一個城市的天氣。不幸的是,同名的城市,如俄勒岡州的波特蘭和緬因州的波特蘭,都將被包括在內(nèi),盡管 JSON 文本將包括經(jīng)度和緯度信息以區(qū)分這兩個城市。

命令行參數(shù)按空格拆分。命令行參數(shù)San Francisco, US將使sys.argv保持['getOpenWeather.py', 'San', 'Francisco,', 'US']。因此,調(diào)用join()方法來連接除了sys.argv中第一個以外的所有字符串。將這個連接的字符串存儲在一個名為location的變量中。

第二步:下載 JSON 數(shù)據(jù)

OpenWeatherMap.org以 JSON 格式提供實時天氣信息。首先你必須在網(wǎng)站上注冊一個免費的 API 密匙。(此鍵用于限制您在他們的服務(wù)器上發(fā)出請求的頻率,以降低他們的帶寬成本。)您的程序只需下載位于api.openweathermap.org/data/2.5/forecast/daily?q=<LOC>&cnt=3&appid=<APIkey>的頁面,其中位置<LOC>是您想要了解其天氣的城市名稱,<APIkey>是您的個人 API key。將以下內(nèi)容添加到getOpenWeather.py中。

#! python3
# getOpenWeather.py - Prints the weather for a location from the command line.
--snip--
# Download the JSON data from OpenWeatherMap.org's API.
url ='https://api.openweathermap.org/data/2.5/forecast/daily?q=%s&cnt=3&APPID=%s ' % (location,
APPID)
response = requests.get(url)
response.raise_for_status()
# Uncomment to see the raw JSON text:
#print(response.text)    
# TODO: Load JSON data into a Python variable.

我們從命令行參數(shù)中得到location。為了創(chuàng)建我們想要訪問的 URL,我們使用了%s占位符,并將存儲在location中的任何字符串插入到 URL 字符串中的那個位置。我們將結(jié)果存儲在url中,并將url傳遞給requests.get()。requests.get()調(diào)用返回一個Response對象,您可以通過調(diào)用raise_for_status()來檢查它的錯誤。如果沒有出現(xiàn)異常,下載的文本將在response.text中。

第三步:加載 JSON 數(shù)據(jù)并打印天氣

response.text成員變量保存一大串 JSON 格式的數(shù)據(jù)。要將其轉(zhuǎn)換為 Python 值,請調(diào)用json.loads()函數(shù)。JSON 數(shù)據(jù)將如下所示:

{'city': {'coord': {'lat': 37.7771, 'lon': -122.42},
          'country': 'United States of America',
          'id': '5391959',
          'name': 'San Francisco',
          'population': 0},
 'cnt': 3,
 'cod': '200',
 'list': [{'clouds': 0,
           'deg': 233,
           'dt': 1402344000,
           'humidity': 58,
           'pressure': 1012.23,
           'speed': 1.96,
           'temp': {'day': 302.29,
                    'eve': 296.46,
                    'max': 302.29,
                    'min': 289.77,
                    'morn': 294.59,
                    'night': 289.77},
           'weather': [{'description': 'sky is clear',
                        'icon': '01d',
--snip--

您可以通過將weatherData傳遞給pprint.pprint()來查看這些數(shù)據(jù)。你可能想查看openweathermap.org以獲得更多關(guān)于這些字段含義的文檔。例如,在線文檔會告訴你'day'后的302.29是白天的開爾文溫度,而不是攝氏度或華氏度。

你要的天氣描述在'main''description'之后。為了整齊地打印出來,將以下內(nèi)容添加到getOpenWeather.py中。

   ! python3
   # getOpenWeather.py - Prints the weather for a location from the command line.
   --snip--
   # Load JSON data into a Python variable.
   weatherData = json.loads(response.text)
   # Print weather descriptions.
   w = weatherData['list'] # ?
   print('Current weather in %s:' % (location))
   print(w[0]['weather'][0]['main'], '-', w[0]['weather'][0]['description'])
   print()
   print('Tomorrow:')
   print(w[1]['weather'][0]['main'], '-', w[1]['weather'][0]['description'])
   print()
   print('Day after tomorrow:')
   print(w[2]['weather'][0]['main'], '-', w[2]['weather'][0]['description'])

請注意代碼是如何將weatherData['list']存儲在變量w中的,以節(jié)省您鍵入 ? 的時間。您使用w[0]w[1]w[2]分別檢索今天、明天和后天天氣的字典。每個字典都有一個'weather'鍵,其中包含一個列表值。您感興趣的是第一個列表項,它是一個嵌套字典,在索引 0 處還有幾個鍵。這里,我們打印存儲在'main''description'鍵中的值,用連字符分隔。

當(dāng)使用命令行參數(shù)getOpenWeather.py San Francisco, CA運行該程序時,輸出如下所示:

Current weather in San Francisco, CA:
Clear - sky is clear
Tomorrow:
Clouds - few clouds
Day after tomorrow:
Clear - sky is clear

(天氣是我喜歡住在舊金山的原因之一?。?/p>

類似程序的創(chuàng)意

訪問天氣數(shù)據(jù)可以構(gòu)成許多類型程序的基礎(chǔ)。您可以創(chuàng)建類似的程序來執(zhí)行以下操作:

  • 收集幾個露營地或徒步旅行路線的天氣預(yù)報,看看哪個會有最好的天氣。
  • 制定一個計劃,定期檢查天氣,如果你需要將植物移到室內(nèi),會給你發(fā)送霜凍警告。(第 17 章講述日程安排,第 18 章解釋如何發(fā)送電子郵件。)
  • 從多個站點獲取天氣數(shù)據(jù)并一次顯示,或者計算并顯示多個天氣預(yù)測的平均值。

總結(jié)

CSV 和 JSON 是存儲數(shù)據(jù)的常見純文本格式。它們很容易被程序解析,同時仍然是人類可讀的,所以它們通常用于簡單的電子表格或 Web 應(yīng)用數(shù)據(jù)。csvjson模塊大大簡化了 CSV 和 JSON 文件的讀寫過程。

前幾章已經(jīng)教你如何使用 Python 來解析各種文件格式的信息。一個常見的任務(wù)是從各種格式中提取數(shù)據(jù),并對其進(jìn)行解析以獲得您需要的特定信息。這些任務(wù)通常特定于商業(yè)軟件沒有最佳幫助的情況。通過編寫自己的腳本,您可以讓計算機(jī)處理以這些格式渲染的大量數(shù)據(jù)。

在第 18 章中,你將脫離數(shù)據(jù)格式,學(xué)習(xí)如何讓你的程序通過發(fā)送電子郵件和文本信息與你交流。

練習(xí)題

  1. Excel 電子表格有哪些 CSV 電子表格沒有的功能?

  2. 你傳遞給csv.reader()csv.writer()什么來創(chuàng)建readerwriter對象?

  3. readerwriter對象的File對象需要在什么模式下打開?

  4. 什么方法獲取列表參數(shù)并將其寫入 CSV 文件?

  5. delimiterlineterminator關(guān)鍵字參數(shù)是做什么的?

  6. 什么函數(shù)接受一串 JSON 數(shù)據(jù)并返回一個 Python 數(shù)據(jù)結(jié)構(gòu)?

  7. 哪個函數(shù)采用 Python 數(shù)據(jù)結(jié)構(gòu)并返回一串 JSON 數(shù)據(jù)?

實踐項目

為了練習(xí),編寫一個程序來完成以下任務(wù)。

Excel 到 CSV 轉(zhuǎn)換器

Excel 只需點擊幾下鼠標(biāo)就可以將電子表格保存為 CSV 文件,但是如果您必須將數(shù)百個 Excel 文件轉(zhuǎn)換為 CSV 文件,則需要花費數(shù)小時的點擊時間。使用第十二章的中的openpyxl模塊,編寫一個程序,讀取當(dāng)前工作目錄中的所有 Excel 文件,并將其輸出為 CSV 文件。

一個 Excel 文件可能包含多個工作表;您必須為每張工作表創(chuàng)建一個 CSV 文件。CSV 文件的文件名應(yīng)為<excel_file_name>_<worksheet_title>.csv,其中<excel_file_name>是不帶文件擴(kuò)展名的 Excel 文件的文件名(例如,'spam_data',而不是'spam_data.xlsx'),<worksheet_title>是來自Worksheet對象的title變量的字符串。

這個程序?qū)S多嵌套的for循環(huán)。程序的框架看起來會像這樣:

for excelFile in os.listdir('.'):
    # Skip non-xlsx files, load the workbook object.
    for sheetName in wb.get_sheet_names():
        # Loop through every sheet in the workbook.
        sheet = wb.get_sheet_by_name(sheetName)
        # Create the CSV filename from the Excel filename and sheet title.
        # Create the csv.writer object for this CSV file.
        # Loop through every row in the sheet.
        for rowNum in range(1, sheet.max_row + 1):
            rowData = []    # append each cell to this list
            # Loop through each cell in the row.
            for colNum in range(1, sheet.max_column + 1):
                # Append each cell's data to rowData.
            # Write the rowData list to the CSV file.
        csvFile.close()

nostarch.com/automatestuff2下載 ZIP 文件excelSpreadsheets.zip并將電子表格解壓到與你的程序相同的目錄下。您可以將這些文件用作測試程序的文件。文章來源地址http://www.zghlxwxcb.cn/news/detail-400092.html

到了這里,關(guān)于Python 自動化指南(繁瑣工作自動化)第二版:十六、使用 CSV 文件和 JSON 數(shù)據(jù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Python 自動化指南(繁瑣工作自動化)第二版:十六、使用 CSV 文件和 JSON 數(shù)據(jù)

    Python 自動化指南(繁瑣工作自動化)第二版:十六、使用 CSV 文件和 JSON 數(shù)據(jù)

    原文:https://automatetheboringstuff.com/2e/chapter16/ 在第 15 章,你學(xué)習(xí)了如何從 PDF 和 Word 文檔中提取文本。這些文件是二進(jìn)制格式的,需要特殊的 Python 模塊來訪問它們的數(shù)據(jù)。另一方面,CSV 和 JSON 文件只是純文本文件。您可以在文本編輯器(如 Mu)中查看它們。但是 Python 還附帶

    2023年04月08日
    瀏覽(656)
  • Python 自動化指南(繁瑣工作自動化)第二版:二十、使用 GUI 自動化控制鍵盤和鼠標(biāo)

    Python 自動化指南(繁瑣工作自動化)第二版:二十、使用 GUI 自動化控制鍵盤和鼠標(biāo)

    原文:https://automatetheboringstuff.com/2e/chapter20/ 了解用于編輯電子表格、下載文件和啟動程序的各種 Python 模塊是很有用的,但有時您需要使用的應(yīng)用沒有任何模塊。在計算機(jī)上實現(xiàn)任務(wù)自動化的終極工具是你編寫的直接控制鍵盤和鼠標(biāo)的程序。這些程序可以通過發(fā)送虛擬擊鍵和

    2024年02月09日
    瀏覽(100)
  • 讓自動化測試秒殺繁瑣操作?試試PO模式設(shè)計框架

    讓自動化測試秒殺繁瑣操作?試試PO模式設(shè)計框架

    目錄:導(dǎo)讀 引言 po模式 優(yōu)勢: ?目錄解釋: 頁面對象設(shè)計模式: base基礎(chǔ)層: page對象層: ?test:測試層 data數(shù)據(jù)層: ?common層: ?untils: ?config層: run層: report: 結(jié)語 你是否曾經(jīng)因為每次更新功能都要重新寫一堆自動化測試代碼而感到疲憊不堪? 或者因為頁面元素的頻繁變

    2024年02月02日
    瀏覽(100)
  • 無需繁瑣手工操作,如何利用Web自動化測試元素定位做到快速高效的測試?

    在Web自動化測試中,元素定位是非常重要的環(huán)節(jié)。因為我們需要找到需要進(jìn)行操作的頁面元素,例如按鈕、輸入框、下拉菜單等等。元素定位可以幫助我們在自動化測試中對這些元素進(jìn)行操作,如點擊、輸入和驗證等。 在華為工作了10年的大佬出的Web自動化測試教程,華為現(xiàn)

    2024年02月05日
    瀏覽(448)
  • 告別重復(fù)工作,用Python實現(xiàn)辦公自動化,提高工作效率

    告別重復(fù)工作,用Python實現(xiàn)辦公自動化,提高工作效率

    996 一直是互聯(lián)網(wǎng)老生常談的話題了,但拋開其他只談工作本身,你有沒有想過, 下班晚、加班,有時候可能是因為自己工作比較低效? 先給你分享一個案例: 場景是在維護(hù)日活超過 3 億用戶的微博私信平臺,在一個業(yè)務(wù)模塊中,需要批量替換 200 臺服務(wù)器中的軟件配置,而

    2024年02月06日
    瀏覽(94)
  • 深度解析appium自動化測試,掌握移動端測試的最新技術(shù),從此告別繁瑣手工測試

    目錄 一、什么是appium? 二、appium的使用場景 三、appium的基礎(chǔ)知識 四、appium代碼示例

    2024年01月19日
    瀏覽(91)
  • Python自動化Clicknium指南1

    Python自動化Clicknium指南1

    Clicknium 是一個Python UI自動化庫,主要用來自動化Windows桌面應(yīng)用和網(wǎng)頁應(yīng)用。由于Clicknium沒中文文檔, 本文將系統(tǒng)的介紹一下Clicknium的使用方法。 Clicknium通過錄制鼠標(biāo)點擊UI元素,自動生成Locator,其中存儲了該UI元素的各種屬性,使Clicknium可以通過locator重新定位到對應(yīng)的UI元

    2024年02月06日
    瀏覽(85)
  • 10個Python自動化腳本助你工作更加高效

    所以,請你把這篇文章放在你的收藏清單上,以備不時之需,在IT行業(yè)里,程序員的學(xué)習(xí)永無止境…… 現(xiàn)在,讓我們開始吧。 ? 使用這個很棒的自動化腳本,可以幫助把圖像處理的更好,你可以像在 Photoshop 中一樣編輯它們。 該腳本使用流行的是 Pillow 模塊 通過使用以下自動

    2024年02月06日
    瀏覽(94)
  • 《編程菜鳥學(xué) Python 數(shù)據(jù)分析》讓工作自動化起來!

    《編程菜鳥學(xué) Python 數(shù)據(jù)分析》讓工作自動化起來!

    隨著我國企業(yè)數(shù)字化和信息化的深入,企業(yè)對辦公自動化的效率和靈活性要求越來越高。Python作為一種開源的軟件應(yīng)用開發(fā)方式,通過提供強(qiáng)大豐富的庫文件包,極大地簡化了應(yīng)用開發(fā)過程,降低了技術(shù)門檻。Python開發(fā)有哪些優(yōu)勢、挑戰(zhàn)以及實踐方法呢? 在我們的日常工作中

    2024年04月09日
    瀏覽(98)
  • 【Python數(shù)據(jù)分析】讓工作自動化起來,無所不能的Python

    【Python數(shù)據(jù)分析】讓工作自動化起來,無所不能的Python

    隨著我國企業(yè)數(shù)字化和信息化的深入,企業(yè)對辦公自動化的效率和靈活性要求越來越高。Python作為一種開源的軟件應(yīng)用開發(fā)方式,通過提供強(qiáng)大豐富的庫文件包,極大地簡化了應(yīng)用開發(fā)過程,降低了技術(shù)門檻。Python開發(fā)有哪些優(yōu)勢、挑戰(zhàn)以及實踐方法呢? 在我們的日常工作中

    2024年04月13日
    瀏覽(116)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包