《让繁琐工作自动化》十四、处理 CSV 文件和JSON 数据

1. 基础语法

1.1 CSV模块

(1)读取CSV文件

csvobj = open(csvfile)                   #打开CSV文件
readerpbj = csv.reader(csvobj)           #将其转换为reader对象

(2)写入数据

output = open(csvfile, 'w', newline='')  # 创建要写入的CSV文件
csvwriter = csv.writer(output)  # 将其转换为writer对象
csvwriter.writerow(row)  # 用writerow函数写入数据

(3)关键字参数

csvwriter = csv.writer(csvfiel , delimiter = '\t , lineterminator = '\n\n')  # delimiter参数为分隔符 lineterminator参数为间距

(4)实例应用

删除许多CSV文件的第一行,重新写入一个_removed文件

import  csv,os
#找寻当前路径下所有CSV
for csvfile in os.listdir('.'):
    if not csvfile.endswith('.csv'):
        continue
    print('Remove header from '+csvfile +' ...')
 
#将除第一行之外的所有行添加到列表中
    csvrow = []
    csvobj = open(csvfile)
    readerpbj = csv.reader(csvobj)
    for row in readerpbj:
        if readerpbj.line_num ==1:
            continue
        csvrow.append(row)
    csvobj.close()
 
#写入新CSV文件
    output = open('Removed'+csvfile,'w')
    # output = open(os.path.join('RemovedHeader',csvfile),'w',newline='')
    csvwriter = csv.writer(output)
    for row in csvrow:
        csvwriter.writerow(row)
    output.close() 

1.2 JSON模块

(1)json.loads()

将包含JSON数据的字符串转换为Python的值

weatherData = json.loads(response.text)

(2)json.dumps()

讲一个Python值转换为JSON格式的字符串

value = {'isCat':True'name':'Zophie} Jsondata = json.dumps(value)

2.项目:从 CSV 文件中删除表头

假设你有一个枯燥的任务,要删除几百 CSV 文件的第一行。也许你会将它们送入一个自动化的过程,只需要数据,不需要每列顶部的表头。可以在 Excel 中打开每个文件,删除第一行,并重新保存该文件,但这需要几个小时。让我们写一个程序来做这件事。

该程序需要打开当前工作目录中所有扩展名为.csv 的文件,读取 CSV 文件的内容,并除掉第一行的内容重新写入同名的文件。这将用新的、无表头的内容替换CSV 文件的旧内容。

与往常一样,当你写程序修改文件时,一定要先备份这些文件,以防万一你的程序没有按期望的方式工作。你不希望意外地删除原始文件。

总的来说,该程序必须做到以下几点:

• 找出当前工作目录中的所有 CSV 文件。

• 读取每个文件的全部内容。

• 跳过第一行,将内容写入一个新的 CSV 文件。

在代码层面上,这意味着该程序需要做到以下几点:

• 循环遍历从 os.listdir()得到的文件列表,跳过非 CSV 文件。

• 创建一个 CSV Reader 对象,读取该文件的内容,利用 line_num 属性确定要跳过哪一行。

• 创建一个 CSV Writer 对象,将读入的数据写入新文件。

针对这个项目,打开一个新的文件编辑器窗口,并保存为 removeCsvHeader.py。

第 1 步:循环遍历每个 CSV 文件

#! 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.

第 2 步:读入 CSV 文件

#! 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.

第 3 步:写入 CSV 文件,没有第一行

#! 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()

第 4 步:类似程序的想法

针对 CSV 文件写的程序类似于针对 Excel 文件写的程序,因为它们都是电子表格文件。你可以编程完成以下任务:

• 在一个 CSV 文件的不同行,或多个 CSV 文件之间比较数据。

• 从 CSV 文件拷贝特定的数据到 Excel 文件,或反过来。

• 检查 CSV 文件中无效的数据或格式错误,并向用户提醒这些错误。

• 从 CSV 文件读取数据,作为 Python 程序的输入。

项目:取得当前的天气数据

检查天气似乎相当简单:打开 Web 浏览器,点击地址栏,输入天气网站的 URL(或搜索一个,然后点击链接),等待页面加载,跳过所有的广告等。

其实, 如果有一个程序,下载今后几天的天气预报,并以纯文本打印出来,就可以跳过很多无聊的步骤。该程序利用第 11 章介绍的 requests 模块,从网站下载数据。

总的来说,该程序将执行以下操作:

• 从命令行读取请求的位置。

• 从 http://OpenWeatherMap.org 下载 JSON 天气数据。

• 将 JSON 数据字符串转换成 Python 的数据结构。

• 打印今天和未来两天的天气。

因此,代码需要完成以下任务:

• 连接 sys.argv 中的字符串,得到位置。

• 调用 requests.get(),下载天气数据。

• 调用 json.loads(),将 JSON 数据转换为 Python 数据结构。

• 打印天气预报。

针对这个项目,打开一个新的文件编辑器窗口,并保存为 quickWeather.py。

第 1 步:从命令行参数获取位置

#! python3
# quickWeather.py - Prints the weather for a location from the command line.

import json, requests, sys

# Compute location from command line arguments.
if len(sys.argv) < 2:
    print('Usage: quickWeather.py location')
    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.

第 2 步:下载 JSON 数据

#! python3
# quickWeather.py - Prints the weather for a location from the command line.

--snip--

# Download the JSON data from OpenWeatherMap.org's API.
url ='http://api.openweathermap.org/data/2.5/forecast/daily?q=%s&cnt=3' % (location)
response = requests.get(url)
response.raise_for_status()

# TODO: Load JSON data into a Python variable.

第 3 步:加载 JSON 数据并打印天气

{'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,查看这个数据。你可能要查找 http://openweathermap.org/,找到关于这些字段含义的文档。例如,在线文档会告诉你, ‘day’后面的 302.29 是白天的开尔文温度,而不是摄氏或华氏温度。

你想要的天气描述在’main’和 ‘description’之后。为了整齐地打印出来,在quickWeather.py 中添加以下代码。

#! python3
# quickWeather.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'])

如果用命令行参数 quickWeather.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

第 4 步:类似程序的想法

访问气象数据可以成为多种类型程序的基础。你可以创建类似程序,完成以下任务:

• 收集几个露营地点或远足路线的天气预报,看看哪一个天气最好。

• 如果需要将植物移到室内,安排一个程序定期检查天气并发送霜冻警报(第15 章介绍了定时调度,第 16 章介绍了如何发送电子邮件)。

• 从多个站点获得气象数据,同时显示,或计算并显示多个天气预报的平均值。

该项目因为http://openweathermap.org/网站自2015年以后需要注册并申请认证key,相关代码不能正常运行,会报:requestsHTTPError: 401 Client Error: Unauthorized for url

我在国内找到了一个可以使用的网站,并将代码做了一点修改:

#! python3
# quickWeather.py - Prints the current weather for a location from the command line.

import json, requests, sys

# Compute location from command line arguments.
if len(sys.argv) < 2:
    print('Usage: quickWeather.py location')
    sys.exit()
location = ' '.join(sys.argv[1:])

# Download the JSON data from OpenWeatherMap.org's API
weatherJsonUrl = 'http://wthrcdn.etouch.cn/weather_mini?city=' + location  # 将链接定义为一个字符串
response = requests.get(weatherJsonUrl)      # 获取并下载页面,其内容会保存在respons.text成员变量里面
response.raise_for_status()	# 这句代码的意思如果请求失败的话就会抛出异常,请求正常就什么也不会做

# Load JSON data into a Python variable.
weatherData = json.loads(response.text)

# Print weather descriptions.
import pprint            	#导入pprint模块
pprint.pprint(weatherData)	#漂亮打印出天气字典

w = weatherData['data']['forecast']
print('Current weather in %s:' % (location))
print(w[0]['high'], ',',w[0]['low'],'-', w[0]['type'])
print()
print('Tomorrow:')
print(w[1]['high'], ',',w[1]['low'],'-', w[1]['type'])
print()
print('Day after tomorrow:')
print(w[2]['high'], ',',w[2]['low'],'-', w[2]['type'])

运行结果:

D:\Users\Administrator\Desktop\Automate the Boring Stuff with Python\automate_online-materials>py quickWeather.py 怀柔
{'data': {'city': '怀柔',
          'forecast': [{'date': '10日星期一',
                        'fengli': '<![CDATA[<3级]]>',
                        'fengxiang': '南风',
                        'high': '高温 26℃',
                        'low': '低温 17℃',
                        'type': '多云'},
                       {'date': '11日星期二',
                        'fengli': '<![CDATA[<3级]]>',
                        'fengxiang': '南风',
                        'high': '高温 24℃',
                        'low': '低温 16℃',
                        'type': '多云'},
                       {'date': '12日星期三',
                        'fengli': '<![CDATA[<3级]]>',
                        'fengxiang': '南风',
                        'high': '高温 27℃',
                        'low': '低温 16℃',
                        'type': '多云'},
                       {'date': '13日星期四',
                        'fengli': '<![CDATA[<3级]]>',
                        'fengxiang': '东南风',
                        'high': '高温 28℃',
                        'low': '低温 19℃',
                        'type': '多云'},
                       {'date': '14日星期五',
                        'fengli': '<![CDATA[<3级]]>',
                        'fengxiang': '西风',
                        'high': '高温 27℃',
                        'low': '低温 18℃',
                        'type': '阴'}],
          'ganmao': '各项气象条件适宜,无明显降温过程,发生感冒机率较低。',
          'wendu': '23',
          'yesterday': {'date': '9日星期日',
                        'fl': '<![CDATA[<3级]]>',
                        'fx': '南风',
                        'high': '高温 27℃',
                        'low': '低温 14℃',
                        'type': '晴'}},
 'desc': 'OK',
 'status': 1000}
Current weather in 怀柔:
高温 26 , 低温 17 - 多云

Tomorrow:
高温 24 , 低温 16 - 多云

Day after tomorrow:
高温 27 , 低温 16 - 多云

这也是我喜欢待在怀柔的原因:)

3.小结

CSV 和 JSON 是常见的纯文本格式,用于保存数据。它们很容易被程序解析,同时仍然让人可读,所以它们经常被用作简单的电子表格或网络应用程序的数据。csv 和 json 模块大大简化了读取和写入 CSV 和 JSON 文件的过程。

前面几章教你如何利用 Python 从各种各样的文件格式的解析信息。一个常见的任务是接受多种格式的数据,解析它,并获得需要的特定信息。这些任务往往非常特别,商业软件并不是最有帮助的。通过编写自己的脚本,可以让计算机处理大量以这些格式呈现的数据。

在第 15 章,你将从数据格式中挣脱,学习如何让程序与你通信,发送电子邮件和文本消息。

4.习题

1.哪些功能是 Excel 电子表格有,而 CSV 电子表格没有?

     Excel 电子表格的值可以是字符串以外的数据类型单元格可以有不
同的字体大小或顔色设置单元格可以有不同的宽度和高度相邻的单元格可以
合并可以嵌入图像和图表

2.向 csv.reader()和 csv.writer()传入什么,来创建 Reader 和 Writer 对象?

传入一个 File 对象,通过调用 open() 获得。

3.对于 Reader 和 Writer 对象,File 对象需要以什么模式打开?

对于 Reader 对象,File 对象需要以读二进制模式('rb')打开,对于 Writer
对象,需要以写二进制模式('wb')打开。

4.什么方法接受一个列表参数,并将其写入 CSV 文件?

writerow() 方法。

5.delimiter 和 lineterminator 关键字参数有什么用?

delimiter 参数改变了分隔一行中单元格所用的字符串。
lineterminator 参数改变了分隔行的字符串。

6.什么函数接受一个 JSON 数据的字符串,并返回一个 Python 数据结构?

json.loads()

7.什么函数接受一个 Python 数据结构,并返回一个 JSON 数据的字符串?

json.dumps()

5 实践项目

5.1 EXCEL到CSV的转换程序

将当前路径下的CSV文件全部输出为CSV文件,一个Excel文件中可能包含多个工作表,必须为每个表创建一个CSV文件,重命名格式为 文件名_表标题.csv

# 2018/9/10 11:18
import csv, openpyxl, os


for file in os.listdir('.'):
    # Skip non-xlsx files, load the workbook object.
    if not file.endswith('.xlsx'):  # 不是xlsx文件就接着往下找
        continue
    wb = openpyxl.load_workbook(file)
    sheets = wb.sheetnames  # 找到当前文件中所有sheet

    for i in range(len(sheets)):
        # Loop through every sheet in the workbook.
        sheet = wb.get_sheet_by_name(sheets[i])  # 在sheets列表中依次循环找

        # Create the CSV filename from the Excel filename and sheet title.
        print('正在写入' + sheet.title + '文件')
        csvfilename = open(file.split('.')[0] + sheet.title + '.csv', 'w')
        # Create the csv.writer object for this CSV file.
        csvwriter = csv.writer(csvfilename)

        # Loop through each cell in the row.
        for rownum in range(1, sheet.max_row + 1):  # 循环每一个cell的值,将每一行写入rowdata中
            rowdata = []  # append each cell to this list
            # Loop through every row in the sheet.
            for colnum in range(1, sheet.max_column + 1):
                # Append each cell's data to rowData.
                rowdata.append(sheet.cell(row=rownum, column=colnum).value)
            # Write the rowData list to the CSV file.
            csvwriter.writerow(rowdata)  # 将每一行的值写入csv文件中
        csvfilename.close()

    原文作者:li li
    原文地址: https://zhuanlan.zhihu.com/p/44057696
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞