第5章 办公自动化中的数据存储 在办公自动化中,数据存储是一个关键的环节。数据存储涉及将办公自动化系统所产生的数据进行持久化存储,以便后续的数据分析、报告生成和业务流程支持等操作。 以下是办公自动化中常见的数据存储方式: (1) 数据库: 使用数据库来存储和管理办公自动化系统所产生的数据是一种常见的做法。数据库提供了结构化的数据存储和查询能力,可以根据需求选择不同的数据库类型,如关系型数据库(如MySQL、Oracle)或非关系型数据库(如MongoDB、Redis)等。通过数据库,可以高效地存储、更新和检索数据。 (2) 文件存储: 在一些简单的办公自动化系统中,可以将数据以文件的形式进行存储。常见的文件格式包括文本文件(如CSV、JSON)、Excel文件和XML文件等。文件存储适用于较小规模的数据集,便于数据的导入和导出。 (3) 云存储: 随着云计算的发展,云存储成为了一种方便、安全且可扩展的数据存储方式。通过将数据存储在云端的存储服务(如Amazon S3、Google Cloud Storage、Microsoft Azure Blob Storage等),可以实现数据的远程访问、备份和共享。 (4) 数据仓库: 数据仓库是一种专门用于存储和管理大规模数据的系统。数据仓库通过将多个数据源的数据进行整合和转换,提供一致性、可靠性和高性能的数据存储和查询。数据仓库通常用于企业级的办公自动化系统,以支持复杂的数据分析和报告需求。 无论选择何种数据存储方式,都需要考虑数据的安全性、可靠性、可扩展性和性能等因素。此外,还需要合理设计数据模型和数据结构,以便满足办公自动化系统的数据存储和操作需求。 本章重点介绍MySQL和JSON存储数据。 5.1使用MySQL数据库 MySQL是一个开源的关系型数据库管理系统,被广泛用于金融数据分析和应用程序开发,本节我们介绍如何使用MySQL数据库。 5.1.1MySQL数据库管理系统 MySQL是流行的开放源的数据库管理系统,是Oracle旗下的数据库产品。目前Oracle提供了多个MySQL版本,其中MySQL Community Edition(社区版)是免费的,该版本比较适合中小企业数据库,本书也对这个版本进行介绍。 社区版安装文件下载如图51所示,可以选择不同的平台版本,MySQL可在Windows、Linux和UNIX等操作系统上安装和运行,读者根据自己情况选择不同平台安装文件下载。 图51详细下载页面 5.1.2安装MySQL8数据库 笔者计算机的操作系统是Windows10 64,笔者下载的离线安装包,文件是mysqlinstallercommunity8.0.28.0.msi,双击该文件就可以安装了。 MySQL8数据库安装过程如下: 1. 选择安装类型 安装过程第一个步骤是选择安装类型,对话框如图52所示,此对话框可以让开发人员选择安装类型,如果是为了学习而使用的数据库,则推荐选中Server only,即只安装MySQL服务器,不安装其他的组件。 图52安装类型 在图52所示的对话框中,单击Next按钮进入如图53所示对话框。 然后单击Execute按钮,开始执行安装。 图53安装对话框 2. 配置安装 安装完成后,还需要进行必要的配置过程,其中有两个重要步骤: (1) 配置网络通信端口,如图54所示,默认通信端口是3306,如果没有端口冲突,建议不用修改。 图54网络配置对话框 (2) 配置密码,如图55所示,配置过程可以为root用户设置密码,也可以添加其他普通用户。 图55设置用户密码 3. 配置Path环境变量 为了使用方便,笔者推荐把MySQL安装路径添加到Path环境变量中,如图56所示,打开Windows环境变量设置对话框。 双击Path环境变量,弹出编辑环境变量对话框,如图57所示,在此对话框中添加MySQL安装路径。 5.1.3客户端登录服务器 如果MySQL服务器安装好了,就可以使用了。使用MySQL服务器第一步是通过客户端登录服务器。登录服务器可以使用命令提示符窗口(macOS和Linux中终端窗口)或GUI(图形用户界面)工具登录MySQL数据库,笔者推荐使用命令提示符窗口登录,下面介绍命令提示符窗口登录过程。 图56Path环境变量 图57Path环境变量对话框 使用命令提示符窗口登录服务器完整的指令如下: mysql -h 主机IP地址(主机名) -u 用户 -p 其中h、u、p是参数,说明: (1) h: 是要登录的服务器主机名或IP地址,可以是远程的一个服务器主机。注意h后面可以没有空格。如果是本机登录可以省略。 (2) u: 是登录服务器的用户,这个用户一定是数据库中存在的,并且具有登录服务器的权限。注意u后面可以没有空格。 (3) p: 是用户对应的密码,可以直接p后面输入密码,可以在敲回车键后再输入密码。 图58所示的是mysql指令登录本机服务器。 图58客户端登录服务器 5.1.4图形界面客户端工具 很多人并不习惯使用命令提示符客户端工具来管理和使用MySQL数据库,为此可以使用图形界面的客户端工具,这些图形界面工具有很多,考虑到免费且跨平台,笔者推荐使用MySQL Workbench,它是MySQL官方提供的免费、功能较全的图形界面管理工具。 1. 安装MySQL Workbench 在安装MySQL过程中,选择MySQL Workbench组件,就可以安装和下载MySQL Workbench。使用6.1.2节的MySQL社区版安装文件,双击安装文件,启动如图59所示的MySQL安装器。 图59启动MySQL安装器 单击Add按钮添加组件,进入如图510所示的安装界面,在此选择要安装的MySQL Workbench组件,然后单击按钮将MySQL Workbench组件添加到右侧列表准备安装,如图511所示。 图510查找MySQL Workbench组件 图511选择MySQL Workbench组件 选择好MySQL Workbench组件后,单击Next按钮,进入如图512所示的安装界面,单击Execute按钮开始安装。 图512安装执行 在安装前还要下载MySQL Workbench,如图513所示,下载完成后单击Next按钮开始安装。安装完成后,单击Finish按钮,如图514所示。 图513下载MySQL Workbench 图514安装完成 2. 配置连接数据库 MySQL Workbench作为MySQL数据库客户端管理工具,要想管理数据库,首先需要配置数据库连接。启动MySQL Workbench,进入如图515所示的欢迎页面。 图515欢迎页面 在MySQL Workbench欢迎页面上单击添加按钮,进入如图516所示的Setup New Connection对话框,在该对话框中开发人员可以为连接设置一个名字,此外,还需要设置主机名、端口、用户名和密码。设置密码时,需要单击Store in Vault按钮,弹出如图517所示的Store Password For Connection对话框。所有项目设置完成后,可以测试一下是否能连接成功,单击Test Connection按钮测试连接,如果成功,则弹出如图518所示的对话框。连接成功,单击OK按钮回到欢迎页面,其中myconnect是刚刚配置好的连接,如图519所示。 图516Setup New Connection对话框 图517Store Password For Connection对话框 图518测试连接成功 图519设置完成 3. 管理数据库 双击myconnect连接就可以登录到MySQL工作台,如图520所示,其中SCHEMAS是当前数据库列表,在MySQL中SCHEMAS(模式)就是数据库,其中粗体显示的数据库为当前默认数据库,如果想改变默认数据库,可以右击要设置的数据库,在弹出的快捷菜单选择Set as Default Schema,就可以设置默认数据库了,如图521所示。 图520MySQL工作台 图521设置默认数据库 注: 在图521所示的快捷菜单中还有Create Schema命令,可以创建数据库; Alter Schema命令可以修改数据库; Drop Schema命令可以删除数据库。 例如,要创建school数据库,则需要选择Create Schema,弹出如图522所示的对话框,在Name文本框中可以设置数据库名,另外还可以选择数据库的字符集,设置无误后单击Apply按钮应用设置。如果取消设置,可以单击Revert按钮。 图522创建数据库 单击Apply按钮,弹出如图523所示的Apply SQL Script to Database对话框。确定无误后单击Apply按钮创建数据库,然后进入如图524所示的界面,单击Finish按钮,创建完成。 图523应用脚本对话框 图524创建完成 有关删除和修改数据库的内容不再赘述。 4. 执行SQL语句 如果不喜欢使用图形界面向导创建、管理数据库和表,还可以使用SQL语句直接操作数据库,要想在MySQL Workbench工具中执行SQL语句,则需要打开查询窗口。执行菜单命令File→New Query Tab或单击快捷按钮可打开查询窗口,如图525所示。 图525查询窗口 开发人员可以在查询窗口中输入任何SQL语句,如图526所示。可以单击按钮执行SQL语句,注意单击该按钮时,如果有选中的SQL语句,则执行选中的SQL语句; 如果没有选中任何SQL语句,则执行当前窗口中全部SQL语句。按钮的功能是执行SQL语句到光标所在的位置。 图526执行SQL语句 5. 执行SQL脚本 我们通常会将多条SQL语句编写在一个文本文件中,打开NASDAQ_DB.sql(笔者提供的纳斯达克股票数据)文件如图527所示。执行该脚本文件的操作如下: (1) 建创建数据库nasda; (2) 在nasda建数据库中创建stocks(股票)表; (3) 在stocks表中插入数据; (4) 在nasda建数据库中创建historicalquote(股票历史数据)表; (5) 在historicalquote表中插入数据。 在MySQL Workbench中可以执行SQL脚本文件,首先通过菜单File→Open SQL Script打开脚本文件,打开NASDAQ_DB.sql文件,如图528所示。 图527NASDAQ_DB.sql脚本文件 图528打开NASDAQ_DB.sql文件 以单击按钮执行SQL打开脚本文件,具体过程不再赘述。 5.1.5安装PyMySQL库 安装PyMySQL库可以使用如下pip指令: pip install PyMySQL 在Windows平台命令提示符中安装PyMySQL库安装过程如图529所示。其他平台安装过程也是类似的,这里不再赘述。 图529安装PyMySQL库 另外,由于MySQL8采用了更加安全的加密方法,因此还需要安装cryptography库。安装cryptography库可以使用如下pip指令: pip install cryptography 在Windows平台命令提示符中安装cryptography库安装过程如图530所示。其他平台安装过程也是类似的,这里不再赘述。 图530安装cryptography库 5.1.6访问数据库一般流程 访问数据库操作分为两大类: 查询数据和修改数据。 1. 查询数据 图531查询数据步骤 查询数据就是通过Select语句查询数据库,其流程如图531所示,该流程有如下6个步骤。 (1) 建立数据库连接。数据库访问的第一步是进行数据库连接。建立数据库连接可以通过PyMySQL库提供的connect(parameters...)方法实现,该方法根据parameters参数连接数据库,连接成功返回Connection(数据库连接)对象。 (2) 创建游标对象。游标是暂时保存了SQL操作所获得的数据,创建游标是通过Connection对象的cursor()方法创建的。 (3) 执行查询操作。执行SQL操作是通过游标对象的execute(sql)方法实现的,其中参数sql表示要执行SQL语句字符串。 (4) 提取结果集。执行SQL操作会返回结果集对象,结果集对象的结构与数据库表类似,由记录和字段构成。提取结果集可以通过游标的fetchall()或fetchone()方法实现,fetchall()是提取结果集中的所有记录,fetchone()方法是提取结果集中的一条记录。 (5) 关闭游标。数据库游标使用完成之后,需要关闭游标,关闭游标可以释放资源。 (6) 关闭数据库连接。数据库操作完成之后,需要关闭数据库连接,关闭连接也可以释放资源。 2. 修改数据 修改数据就是通过Insert、Update和Delete等语句修改数据,其流程如图532所示。修改数据与查询数据流程类似,也有6个步骤。但是修改数据时,如果执行SQL操作成功时需要提交数据库事务,如果失败则需要回滚数据库事务。另外,修改数据时不会返回结果集,也就不能从结果集中提取数据了。 图532查询修改数据步骤 数据库事务通常包含了多个对数据库的读/写操作,这些操作是有序的。若事务被提交给了数据库管理系统,则数据库管理系统需要确保该事务中的所有操作都成功完成,结果被永久保存在数据库中。如果事务中有的操作没有成功完成,则事务中的所有操作都需要被回滚,回到事务执行前的状态。 (1) 连接数据库代码: import pymysql # 建立数据库连接 cnx = pymysql.connect(user='username', password='password', host='host_address', database='database_name') 在上述代码中,需要将username、password、host_address和database_name替换为实际的数据库连接信息。 (2) 创建游标对象: 在建立数据库连接后,需要创建一个游标对象,用于执行SQL语句。 cursor = cnx.cursor() (3) 执行SQL查询: 使用游标对象执行SQL查询语句,获取数据库中的数据。 query = "SELECT * FROM table_name" cursor.execute(query) # 获取查询结果 result = cursor.fetchall() 在上述代码中,table_name应替换为实际的表名。 (4) 执行SQL插入/更新: 使用游标对象执行SQL插入或更新语句,将数据写入MySQL数据库。 insert_query = "INSERT INTO table_name (column1, column2) VALUES (%s, %s)" data = ('value1', 'value2') cursor.execute(insert_query, data) # 提交事务 cnx.commit() 在上述代码中,table_name应替换为实际的表名,column1和column2应替换为实际的列名,value1和value2应替换为要插入的实际值。 (5) 关闭游标和数据库连接: 在完成所有数据库操作后,需要关闭游标和数据库连接。 cursor.close() cnx.close() 这样就完成了对MySQL数据库的读写操作。 以上代码示例是基本的MySQL数据库读写操作,具体的SQL查询和插入/更新语句需要根据实际情况进行调整。此外,还应该考虑异常处理、数据类型转换等方面的处理。 5.1.7案例1: 访问苹果股票数据 下面通过一个案例介绍如何使用Python语言访问MySQL数据库。 案例背景: 该案例的该项目的数据库设计模型如图533所示,项目中包含两个数据表: 股票信息表(Stocks)和股票历史价格表(HistoricalQuote)。 图533数据库设计模型 数据库设计模型中各个表说明如下: 1. 股票信息表 股票信息表(英文名Stocks)是纳斯达克股票,股票代号(英文名Symbol)是主键,股票信息表结构如表51所示。该项目目前的功能不包括维护股票信息表,所需要数据在创建数据表时预先插入。 表51股票信息表结构 字段名数据类型长度精度主键外键备注 Symbolvarchar(10)10—是否股票代号 Companyvarchar(50)50—否否公司 Industryvarchar(10)10—否否所属行业 2. 股票历史价格表 股票历史价格表(英文名HistoricalQuote)是某一只股票的历史价格表,交易日期(英文名HDate)是主键,股票历史价格表结构如表52所示。 表52股票历史价格表结构 字段名数据类型长度精度主键外键备注 HDatedate—是否交易日期 Opendecimal(8,4)84否否开盘价 Highdecimal(8,4)84否否最高价 Lowdecimal(8,4)84否否最低价 Closedecimal(8,4)84否否收盘价 Volumebigint—否否成交量 Symbolvarchar(10)10—否是股票代号 编写及执行SQL脚本这里不再赘述。 那么根据股票代号查询股历史数据的Python代码如下: import pymysql # 建立数据库连接 cnx = pymysql.connect( host='127.0.0.1', user='root', password='12345', database='nasdaq' ) # 创建游标对象 cursor = cnx.cursor() # 定义查询语句和参数 query = "SELECT * FROM historicalquote WHERE Symbol = %s" ① params = ('AAPL',) # 执行查询语句 cursor.execute(query, params) ② # 获取查询结果 result = cursor.fetchall() ③ # 输出查询结果 for row in result: ④ print(row) # 关闭游标和数据库连接 cursor.close() cnx.close() 上述代码执行后,输出结果如下。 (datetime.date(2018, 2, 1), Decimal('167.1650'), Decimal('168.6200'), Decimal('166.7600'), Decimal('167.7800'), 44453230, 'AAPL') ... (datetime.date(2023, 1, 31), Decimal('166.8700'), Decimal('168.4417'), Decimal('166.5000'), Decimal('167.4300'), 32234520, 'AAPL') 代码解释如下:  代码第①行在这一行中,定义了查询语句,使用了参数占位符 %s 来表示待传入的参数。  代码第②行execute()方法用于执行查询语句,并将参数值传递给查询语句中的占位符。在这里,params变量包含了要绑定的参数值。  代码第③行使用 fetchall() 方法获取查询结果集。这个方法会返回一个包含所有查询结果的列表。  代码第④行使用 for 循环遍历结果列表,并输出每一行的内容。 最后,在代码的末尾,通过调用close()方法关闭游标对象和数据库连接,释放相关资源。 请注意,代码中的连接参数(host、user、password、database)是示例值,需要根据实际情况进行修改。同时,查询的表名、列名以及参数值也需要根据数据库的实际结构进行调整。 这段代码的作用是连接到数据库,执行一条查询语句,将结果打印输出,并关闭数据库连接。在这个示例中,查询的条件是Symbol='AAPL',即查询 historicalquote表中Symbol列为 'AAPL' 的数据行,AAPL是苹果股票代号。 5.2使用Pandas读写MySQL数据库 Pandas提供了用于读取和写入MySQL数据库的函数。下面是几个常用的函数: (1) pd.read_sql(query, con): 从MySQL数据库中执行查询语句并返回结果作为DataFrame。query是查询语句,con是与MySQL数据库建立的连接对象。 (2) df.to_sql(name, con, if_exists='fail', index=False): 将DataFrame中的数据写入MySQL数据库中的表。name是目标表的名称,con是与MySQL数据库建立的连接对象,if_exists是指定写入操作的行为,默认为'fail',表示如果目标表已存在,则引发异常。index=False表示不将DataFrame的索引写入数据库。 (3) pd.read_sql_table(table_name, con): 从MySQL数据库中读取整个表的数据并返回结果作为DataFrame。table_name是表的名称,con是与MySQL数据库建立的连接对象。 这些函数可以方便地与MySQL数据库进行数据的读取和写入操作。 建议在使用Pandas读取数据时,使用SQLAlchemy的connectable(engine/connection)创建数据库连接对象,而不推荐使用pymysql.connect()来创建数据库连接对象。这是因为使用SQLAlchemy的connectable可以避免不兼容性问题。 SQLAlchemy是一个Python SQL工具和对象关系映射(ORM)库,它提供了一种与数据库进行交互的高级抽象和灵活性。它支持多种数据库后端,并提供了统一的API,使得在不同数据库之间切换变得更加容易。 使用SQLAlchemy,你可以执行以下操作: (1) 创建数据库连接: 通过create_engine()函数创建数据库连接对象,指定数据库类型、主机、用户名、密码和数据库名称等参数。 (2) 执行SQL查询: 使用连接对象的execute()方法执行SQL查询语句。 (3) 获取查询结果: 通过执行查询后返回的结果集对象,使用fetchall()、fetchone()等方法获取查询结果。 (4) 执行事务操作: 使用连接对象的begin()、commit()和rollback()等方法执行数据库事务操作。 (5) ORM映射: 使用SQLAlchemy的ORM功能,将数据库表映射为Python对象,实现面向对象的数据库操作,简化了数据库的访问和操作。 通过使用SQLAlchemy,我们可以更方便地操作数据库,实现数据读取、写入和查询等功能,并且具有较高的灵活性和可扩展性。它也被广泛应用于许多Python项目和框架中,如Django、Flask等。 示例: 使用Pandas从数据库读取股票数据 下面我们是要使用Pandas库的pd.read_sql_table(table_name,con)函数从historicalquote(股票历史数据)表读取数据,具体代码如下: import pandas as pd import pymysql from sqlalchemy import create_engine # 创建数据库连接 engine = create_engine('mysql+pymysql://root:12345@localhost/nasdaq') # 从MySQL数据库中读取数据 df = pd.read_sql_table('historicalquote', engine) print(df) 示例运行后,输出结果如下: HDateOpenHighLow CloseVolumeSymbol 02018-02-01167.165168.6200166.7600167.7844453230 AAPL 12018-02-02166.000166.8000160.1000160.5085957050 AAPL 22018-02-05159.100163.8800156.0000156.4972215320 AAPL 32018-02-06154.830163.7200154.0000163.0368171940 AAPL 42018-02-07163.085163.4000159.0685159.5451467440 AAPL ......... ... ... ... ...... 60 2023-01-29170.160170.1600167.0700167.9650565420 AAPL 61 2023-01-30165.525167.3700164.7000166.9745635470 AAPL 62 2023-01-31166.870168.4417166.5000167.4332234520 AAPL 63 2023-07-01100.250105.5000 98.7500102.80100000 AAPL 64 2023-07-02103.000106.2000101.5000105.40120000 AAPL [65 rows x 7 columns] 上述代码使用了 pd.read_sql_table('historicalquote', engine)函数读取historicalquote表查询所有字段,如果只是关系部分字段,这可以使用pd.read_sql(query, engine)函数。 那么对应代码如下: import pandas as pd import pymysql from sqlalchemy import create_engine # 创建数据库连接 engine = create_engine('mysql+pymysql://root:12345@localhost/nasdaq') # 从MySQL数据库中读取数据 query = "SELECT HDate,Open,High, Low,Close FROM historicalquote WHERE Symbol = 'AAPL'" df = pd.read_sql(query, engine) print(df) 示例运行后,输出结果如下: HDateOpen High LowClose 0 2018-02-01167.165168.6200166.7600167.78 1 2018-02-02166.000166.8000160.1000160.50 2 2018-02-05159.100163.8800156.0000156.49 3 2018-02-06154.830163.7200154.0000163.03 4 2018-02-07163.085163.4000159.0685159.54 ... ...... ... ...... 602023-01-29170.160170.1600167.0700167.96 612023-01-30165.525167.3700164.7000166.97 622023-01-31166.870168.4417166.5000167.43 632023-07-01100.250105.5000 98.7500102.80 642023-07-02103.000106.2000101.5000105.40 rows x 5 columns] 5.3JSON数据交换格式 JSON是一种轻量级的数据交换格式。所谓轻量级,是与XML文档结构相比而言的。描述项目的字符少,所以描述相同数据所需的字符个数要少,那么传输速度就会提高,而流量也会减少。 5.3.1JSON文档结构 由于Web和移动平台开发对流量的要求是尽可能少,对速度的要求是尽可能快,而轻量级的数据交换格式JSON就成为理想的数据交换格式。 构成JSON文档的两种结构分别为对象(object)和数组(array)。其中,对象是“名称: 值”对集合,它类似于Python中Map类型,而数组是一连串元素的集合。 JSON对象是一个无序的“名称/值”对集合,一个对象以“{”开始,以“}”结束。每个“名称”后跟一个“:”,“名称: 值”对之间使用“,”分隔,“名称”是字符串类型(string),“值”可以是任何合法的JSON类型。JSON对象的语法表如图534所示。 图534JSON对象的语法表 下面是一个JSON对象的例子: { "name":"a.htm", "size":345, "saved":true } JSON数组是值的有序集合,以“[”开始,以“]”结束,值之间使用“,”分隔。JSON数组的语法表如图535所示。 图535JSON数组的语法表 下面是一个JSON数组的例子: ["text","html","css"] JSON数组中的值可以是双引号括起来的字符串、数字、对象、数组、true、false或null,而且这些结构可以嵌套。JSON值的语法结构图如图536所示。 图536JSON值的语法结构图 5.3.2JSON数据编码 在Python程序中要想将Python数据网络传输和存储,可以将Python数据转换为JSON数据再进行传输和存储,这个过程称为“编码(encode)”。 在编码过程中Python数据转换为JSON数据的映射关系如表53所示。 表53Python数据与JSON数据映射关系 PythonJSONPythonJSON 字典对象Truetrue 列表、元组数组Falsefalse 字符串字符串Nonenull 整数、浮点等数字类型数字 JSON数据在网络传输或保存到磁盘中时,推荐使用JSON对象,偶尔也使用JSON数组。所以一般情况下只有Python的字典、列表和元组才需要编码,Python字典编码JSON对象; Python列表和元组编码JSON数组。 Python提供的内置模块json可以帮助实现JSON的编码和解码,JSON编码使用dumps()和dump()函数,dumps()函数将编码的结果以字符串形式返回,dump()函数将编码的结果保存到文件对象(类似文件对象或流)中。 下面具体介绍JSON数据编码过程,示例代码如下: import json # 准备数据 py_dict = {'name': 'tony', 'age': 30, 'sex': True}# 创建字典对象 py_list = [1, 3]# 创建列表对象 py_tuple = ('A', 'B', 'C')# 创建元组对象 py_dict['a'] = py_list# 添加列表到字典中 py_dict['b'] = py_tuple# 添加元组到字典中 print(py_dict) print(type(py_dict))# # 编码过程 json_obj = json.dumps(py_dict) ① print(json_obj) print(type(json_obj))# # 编码过程 json_obj = json.dumps(py_dict, indent=4) ② # 漂亮的格式化字符串后输出 print(json_obj) # 写入JSON数据到data1.json文件 with open('data/data1.json', 'w') as f: json.dump(py_dict, f) ③ # 写入JSON数据到data2.json文件 with open('data/data2.json', 'w') as f: json.dump(py_dict, f, indent=4) ④ 上述代码运行,输出结果如下: {'name': 'tony', 'age': 30, 'sex': True, 'a': [1, 3], 'b': ('A', 'B', 'C')} {"name": "tony", "age": 30, "sex": true, "a": [1, 3], "b": ["A", "B", "C"]} { "name": "tony", "age": 30, "sex": true, "a": [ 1, 3 ], "b": [ "A", "B", "C" ] } 解释如下:  上述代码第①行是对Python字典对象py_dict进行编码,编码的结果是返回字符串,这个字符串中没有空格和换行等字符,可见减少字节数适合网络传输和保存。  代码第②行也是对Python字典对象py_dict进行编码,在dumps()函数中使用了参数indent。indent可以格式化字符串,indent=4表示缩进4个空格,这种漂亮的格式化的字符串,主要用于显示和日志输出,但不适合网络传输和保存。  代码第③行和第④行是dump()函数将编码后的字符串保存到文件中,dump()与dumps()函数具有类似的参数,这里不再赘述。 5.3.3JSON数据解码 编码的相反过程是“解码”(decode),即将JSON数据转换为Python数据。从网络中接收或从磁盘中读取JSON数据时,需要解码为Python数据。 在编码过程中,JSON数据转换为Python数据的映射关系如表54所示。 表54JSON数据与Python数据映射关系 JSONPythonJSONPython 对象字典实数数字浮点 数组列表trueTrue 字符串字符串falseFalse 整数数字整数nullNone json模块提供的解码函数是loads()和load(),loads()函数将JSON字符串数据进行解码,返回Python数据,load()函数读取文件或流,对其中的JSON数据进行解码,返回结果为Python数据。 下面具体介绍JSON数据解码过程,示例代码如下: import json # 准备数据 json_obj = r'{"name": "tony", "age": 30, "sex": true, "a": [1, 3], "b": ["A", "B", "C"]}' ① py_dict = json.loads(json_obj) ② print(type(py_dict))# print(py_dict['name']) print(py_dict['age']) print(py_dict['sex']) py_lista = py_dict['a']# 取出列表对象 print(py_lista) py_listb = py_dict['b']# 取出列表对象 print(py_listb) # 读取JSON数据到data2.json文件 with open('data/data2.json', 'r') as f: data = json.load(f) ③ print(data) print(type(data))# 解释如下:  代码第①行是一个表示JSON对象的字符串。  代码第②行是对JSON对象字符串进行解码,返回Python字典对象。  代码第③行是从data2.json文件中读取JSON数据解析解码,返回Python字典对象。 5.3.4案例2: 解码搜狐证券贵州茅台股票数据 我们在3.3.3节介绍过使用Selenium从搜狐证券网爬取贵州茅台股票数据,事实上网页中的股票数据,通过如下网址返回: http://q.stock.sohu.com/hisHq?code=cn_600519&stat=1&order=D&period=d&callback=historySearchHandler&rt=jsonp&0.8115656498417958 直接将网址在浏览器中打开,如图537所示,浏览器展示了一个字符串。从返回的字符串可见,并不是一个有效的JSON数据,而JSON数据是放置在historySearchHandler(…)中的,historySearchHandler应该是一个JavaScript变量或函数,开发人员只需要关心括号中的JSON字符串就可以了。 图537浏览器中展示返回的字符串 笔者将上述返回的JSON字符串进行了处理并保存为“贵州茅台股票数据.json”文件,具体处理过程不再赘述,最后获取的文件内容如图538所示。 图538“贵州茅台股票数据.json”文件 解码“贵州茅台股票数据.json”文件具体代码如下: import json import pandas as pd data = [] with open('data/贵州茅台股票数据.json', 'r') as json_file: ① data_dict = json.load(json_file) ② hqlist = data_dict['hq'] ③ for item in hqlist: fields = {} fields['Date'] = item[0]# 日期 ④ fields['Open'] = item[1]# 开盘 fields['Close'] = item[2]# 收盘 fields['Low'] = item[5]# 最低 fields['High'] = item[6]# 最高 fields['Volume'] = item[7]# 成交量 ⑤ data.append(fields) ⑥ df = pd.DataFrame(data) ⑦ print(df) 示例运行后,输出结果如下: DateOpen CloseLow High Volume 0 2023-07-033209.163243.983209.163246.86312371392 1 2023-06-303178.923202.063177.993212.99265379888 2 2023-06-293185.423182.383179.533196.50250340064 3 2023-06-283183.493189.383157.123192.66276231936 4 2023-06-273153.313189.443148.273194.41287604320 ... .................. 752023-03-103255.513230.083229.503262.15281135424 762023-03-093285.943276.093260.003289.06264021856 772023-03-083271.883283.253263.693283.25260443552 782023-03-073320.213285.103284.413342.86389957952 792023-03-063332.023322.033308.733333.06340530432 [80 rows x 6 columns] 解释代码:  代码第①行打开名为'贵州茅台股票数据.json'的JSON文件,并将其赋值给json_file变量。使用with语句可以确保在处理完文件后自动关闭文件。  代码第②行将JSON文件内容加载为Python字典,并将其赋值给data_dict变量。JSON文件中的数据被转换为Python的字典形式,便于后续的处理。  代码第③行从data_dict字典中获取键为'hq'的值,并将其赋值给hqlist变量。假设JSON文件中有一个键为'hq'的列表,该列表包含了一组股票数据。  代码第④行for item in hqlist::这是一个for循环,用于遍历hqlist列表中的每个元素,每个元素称为item。  代码第⑤行将item列表中的第一个元素(索引为0)赋值给fields字典的键'Date'。假设该元素是日期。  代码第⑥行fields['Open'] = item[1]~fields['Volume'] = item[7]: 这些行代码将item列表中不同索引位置的元素分别赋值给fields字典的相应键,例如,将第二个元素赋值给'Open'键,第三个元素赋值给'Close'键,以此类推。假设这些元素分别表示开盘价、收盘价、最低价、最高价和成交量。  代码第⑦行df=pd.DataFrame(data): 这行代码将data列表转换为Pandas DataFrame对象,并将其赋值给df变量。 5.4本章总结 本章主要介绍了办公自动化中数据存储的两种常用方式——MySQL数据库和JSON格式,以及在Python中对其的操作。 首先,介绍了MySQL数据库管理系统的特点,并学习了如何安装MySQL数据库。我们还学习了如何使用命令行客户端以及图形界面工具管理MySQL数据库。 随后,安装了PyMySQL库,并学习了如何使用Python程序访问MySQL数据库的一般流程。通过一个示例,我们连接MySQL数据库,并读取了苹果股票数据。 接下来,介绍了如何用Pandas从MySQL数据库中读取和写入数据。Pandas提供了便捷的数据库接口,可以大幅简化数据库操作。 此外,还介绍了JSON这种轻量级的数据交换格式。JSON使用JavaScript语法来表示数据对象、数组等。我们学习了JSON的编码与解码,并完成了一个将爬取的贵州茅台股票数据解码为Python字典的示例。 总体而言,本章介绍的MySQL数据库和JSON数据格式在办公自动化中数据存储功能非常关键。熟练掌握它们的操作可以大大提高程序获取和处理数据的效率。