Python数据分析与数据化运营

3.12.3 图像的基本预处理

Author
宋天龙
发布于 2019-01-04
2221 次阅读
0 次赞
0 次分享
3.12.3 图像的基本预处理
AI 智能核心导读

本文系统讲解了使用Python从四类核心数据源获取运营数据的具体方法与代码实现。内容涵盖:利用xlrd读取Excel;通过mysql.connector连接MySQL并运用SQL查询;使用pymongo从MongoDB读取非结构化数据;以及调用百度API解析JSON与XML。文章强调,应根据数据规模与业务场景,灵活选择最合适的数据存储与处理工具。

使用 Python 获取运营数据(二):Excel、数据库与 API

说明:本文是《Python 数据分析与数据化运营》中“2.2 使用 Python 获取运营数据”的第二部分。由于本节内容较多,特分为多篇文章进行连载。

2.2.2 从 Excel 获取运营数据

现有的 Excel 分为两种格式:xls(Excel 97-2003)和 xlsx(Excel 2007 及以上)。

Python 处理 Excel 文件主要是第三方模块库 xlrdxlwtpyexcel-xlsxlutilspyExcelerator,以及 win32comopenpyxl 模块,此外 Pandas 中也带有可以读取 Excel 文件的模块(read_excel)。

基于扩展知识的目的,我们使用 xlrd 模块读取 Excel 数据。首先安装该库,在系统终端命令行输入命令 pip install xlrd。然后我们以“附件-chapter2”文件夹 demo.xlsx 数据文件为例,介绍该库的具体应用。数据概览如图 2-7 所示:

2-7
2-7
图 2-7 数据文件内容

python
1import xlrd # 导入库 2 3# 打开文件 4xlsx = xlrd.open_workbook('demo.xlsx') 5 6# 查看所有 sheet 列表 7print('All sheets: %s' % xlsx.sheet_names()) 8print('===================================') # 内容分割线 9 10# 查看 sheet1 的数据概况 11sheet1 = xlsx.sheets()[0] # 获得第一张 sheet,索引从 0 开始 12sheet1_name = sheet1.name # 获得名称 13sheet1_cols = sheet1.ncols # 获得列数 14sheet1_nrows = sheet1.nrows # 获得行数 15print('Sheet1 Name: %s\nSheet1 cols: %s\nSheet1 rows: %s' % (sheet1_name, sheet1_cols, sheet1_nrows)) 16print('===================================') # 内容分割线 17 18# 查看 sheet1 的特定切片数据 19sheet1_nrows4 = sheet1.row_values(4) # 获得第 4 行数据 20sheet1_cols2 = sheet1.col_values(2) # 获得第 2 列数据 21cell23 = sheet1.row(2)[3].value # 查看第 3 行第 4 列数据 22print('Row 4: %s\nCol 2: %s\nCell 1: %s\n' % (sheet1_nrows4, sheet1_cols2, cell23)) 23print('===================================') # 内容分割线 24 25# 查看 sheet1 的数据明细 26for i in range(sheet1_nrows): # 逐行打印 sheet1 数据 27 print(sheet1.row_values(i))

上述代码中,我们先读取一个 Excel 文件,再查看所有 sheet(工作簿)并输出 sheet1 相关属性信息;然后查看 sheet1 中特定数据行、列和元素的信息;最后我们用循环的方式,依次读取每个数据行并打印输出。

以下是代码执行后打印输出的结果:

code
1All sheets: [u'Sheet1'] 2=================================== 3Sheet1 Name: Sheet1 4Sheet1 cols: 4 5Sheet1 rows: 10 6=================================== 7Row 4: [u'431381197408191515', u'\u6709\u6548', 42725.0, u'\u6df1\u5733\u5e02'] 8Col 2: [u'Create_Time', 42725.0, 42725.0, 42725.0, 42725.0, 42725.0, 42725.0, 42725.0, 42725.0, 42725.0] 9Cell 1: 深圳市 10=================================== 11[u'ID_number', u'Status', u'Create_Time', u'Business_City'] 12[u'431381198109106573', u'\u6709\u6548', 42725.0, u'\u6df1\u5733\u5e02'] 13[u'431381198809122734', u'\u6709\u6548', 42725.0, u'\u6df1\u5733\u5e02'] 14[u'431381197903117478', u'\u6709\u6548', 42725.0, u'\u6df1\u5733\u5e02'] 15[u'431381197408191515', u'\u6709\u6548', 42725.0, u'\u6df1\u5733\u5e02'] 16[u'431381197606166011', u'\u6709\u6548', 42725.0, u'\u6df1\u5733\u5e02'] 17[u'43138119850623339X', u'\u6709\u6548', 42725.0, u'\u6df1\u5733\u5e02'] 18[u'431381198908223477', u'\u6709\u6548', 42725.0, u'\u6df1\u5733\u5e02'] 19[u'431381198901176911', u'\u6709\u6548', 42725.0, u'\u6df1\u5733\u5e02'] 20[u'43138119870827275X', u'\u6709\u6548', 42725.0, u'\u6df1\u5733\u5e02']

提示 在上述打印输出的内容中,我们发现第二列、第三列、第四列与原始数据似乎不同。第二列和第四列“异常”的原因是将中文编码统一转换为 Unicode 编码,便于在不同程序间调用;第三列“异常”是由于将日期格式转换为数值格式而已。

上述操作只是将数据从 Excel 中读取出来,基于读取的数据转换为数组便可以进行矩阵计算。由于矩阵计算大多是基于数值型数据实现的,因此上述数据将无法适用于大多数科学计算场景,这点需要注意。

总结:在企业实际场景中,由于 Excel 本身的限制和适用,其无法存储和计算过大(例如千万级的数据记录)的数据量,并且 Excel 本身也不是为了海量数据的应用而产生的。因此,Excel 可以作为日常基本数据处理、补充数据来源或者汇总级别的数据进行读取,同时也可以作为数据结果展示的载体,这种应用下对于大量数值表格的应用效果非常好。


2.2.3 从关系型数据库 MySQL 读取运营数据

在第一章“1.2.4 数据库和客户端”中我们介绍了安装 MySQL 和 Navicat 的方法和关键步骤。这里我们介绍如何利用 Python 从 MySQL 中读取数据。

在“附件-chapter2”文件夹中有一个名为 order.xlsx 的数据文件,我们先把文件导入 MySQL 数据库,然后再基于数据库进行相关操作。

1. 将 Excel 数据导入 MySQL 数据库

第一阶段:新建目标数据库

  1. 打开 Navicat,左侧导航栏中有我们已经建立好的数据库链接,在第一章中我们已经建立好了本地连接,名为“127.0.0.1”。
  2. 双击该数据库连接,会展示出所有当前连接(对应的用户权限)下可用的数据库,如图 2-8。
    2-8
    2-8
    图 2-8 127.0.0.1 下的数据库
  3. 为了保持不同数据的独立性,我们新建一个数据库,单独存放特定主题的数据。在“127.0.0.1”名称上右键,在弹出的菜单中选择新建数据库,然后做如下设置并点击确定。完成之后在左侧的“127.0.0.1”链接下会新增一个刚才新建的数据库“python_data”。

第二阶段:导入 Excel 数据

双击刚才新建的名为“python_data”的数据库名称,激活数据库连接。此时右侧功能栏中的部分功能已经可用。点击“导入向导”,开始导出 Excel 数据。如图 2-10。

2-10
2-10
图 2-10 创建导入向导

  1. 选择数据文件格式:Excel 2007。
  2. 选择数据源文件
    2-11
    2-11
    图 2-11 设置导入数据源
  3. 定义附加选项:由于数据文件中第一行是表头,因此数据从第二行开始;日期分隔符与数据文件一致,需要设置为“-”,其他都为默认值。
    2-12
    2-12
    图 2-12 设置导入附件选项
  4. 设置目标数据表名:设置为 order
  5. 设置字段类型、长度、约束等信息:其中主要的设置是将 order_data 类型设置为 date(日期型),长度为 0(不做限制);order_tme 类型设置为 time(时间型),长度为 0(不做限制);total_amount 类型设置为 float(浮点型),长度默认为 255。
    2-13
    2-13
    图 2-13 设置字段类型等约束

    提示:实际上,我们的数据很可能用不了那么多的“存储空间”,因此在设置时存在数据空间冗余,不过没关系,这里我们仅仅做入门引导之用。真正涉及到数据库表的模型设计有很多学问,这里的设置不会影响我们做数据统计分析之用。

  6. 设置导入模式:由于我们是新创建表,因此设置为:添加。
  7. 启动导入任务:点击“开始”即可。

等待系统导入数据,导入成功后,会在窗口中显示如下信息,最终的信息中包含“successfully”,如图 2-14。点击关闭按钮即可。

2-14
2-14
图 2-14 导入成功提示信息

至此我们已经成功导入数据,在数据库 python_data 下新增了一个名为 order 的数据表。我们要初步验证导入的数据是否与原始数据一致。双击打开该表。打开表之后,会弹出信息提示该表没有主键。该信息不影响我们使用该表,点击确定即可。

2-15
2-15
图 2-15 提示表没有主键

提示 在创建表时,我们完全可以指定主键,例如本案例中的 order_id 是唯一的,那么可指定该字段作为主键,更可以创建一个自增长 ID 作为主键。本节的主要内容是介绍如何导入外部数据到数据库,有关数据库建表还有很多话题,在此不作更多介绍。

打开 order 表之后,会显示如下表预览内容:

2-16
2-16
图 2-16 数据表概览

在当前窗口,点击“文件-查询表”或直接使用快捷键 Ctrl+Q,打开 SQL 窗口,然后输入 SELECT * FROM \order` LIMIT 5;点击“运行”或使用快捷键Ctrl+R`,返回前 5 条结果,如下图 2-17。读者可以在此输入其他 SQL 或直接浏览数据表来核对数据导入是否准确。

注意:由于表名 order 是数据库中的排序关键字,因此在查询表时需要写为 \order``,否则会报错。

2-17
2-17
图 2-17 运行 SQL 并返回结果

导入 Excel 数据主要核对的信息点包括:

  • 数据记录数是否一致:使用 SELECT COUNT(*) FROM \order`;` 或在导入成功提示窗口也可以看到。
  • 数据字段数量是否一致:导入表中的字段不能多也不能少。
  • 查看数据内容是否一致:尤其是日期、时间等非字符串字段的数据,很多时候时间型的数据转换会出现 0000-00-00,这通常是导入设置的日期分隔符问题。
  • 数据精准度是否一致:尤其是原始数据是浮点型,对应到数据库字段是否还是浮点型(注意小数位数),问题通常出现在字段类型和位数设置。
  • 注意字段的最大长度:不同的数值型数据长度位数是不同,例如整数型 tinyintint,浮点型的单精度和双精度浮点等,这对于汇总级别的数据会产生极大影响(因为某些字段的汇总数据可能非常大)。

2. 使用 Python 读取 MySQL 数据

通过 Python 连接 MySQL 需要有 Python 库来建立连接,本节使用 MySQL 官方驱动连接程序,更多信息可在“1.2.3 Python 第三方库”中的“5. 数据库连接库”中找到。以下是 Python 读取数据库数据的基本方法:

python
1import mysql.connector # 导入库 2 3config = { 4 'host': '127.0.0.1', # 默认 127.0.0.1 5 'user': 'root', # 用户名 6 'password': '123456', # 密码 7 'port': 3306, # 端口,默认为 3306 8 'database': 'python_data', # 数据库名称 9 'charset': 'gb2312' # 字符编码 10} 11 12cnn = mysql.connector.connect(**config) # 建立 mysql 连接 13cursor = cnn.cursor() # 获得游标 14sql = "SELECT * FROM `order`" # SQL 语句 15cursor.execute(sql) # 执行 sql 语句 16data = cursor.fetchall() # 通过 fetchall 方法获得数据 17 18for i in data[:2]: # 打印输出前 2 条数据 19 print(i) 20 21cursor.close() # 关闭游标 22cnn.close() # 关闭连接

上述代码中,实现了通过 Python 连接 MySQL 查询所有的数据,并输出前 2 条数据的功能。执行结果如下:

code
1(u'3897894579', datetime.date(2010, 3, 11), datetime.timedelta(0), u'PENDING_ORDER_CONFIRM', u'1038166', 59.0) 2(u'3897983041', datetime.date(2010, 3, 11), datetime.timedelta(0), u'REMOVED', u'1041656', 19.9)

3. 常用 SQL 查询语法

在应用 MySQL 中,除了查询所有数据外,更多时候我们还会应用更多 SQL 技巧来帮助我们快速找到目标数据并作初步处理。以下是常用 SQL 语法:

  • 只查询前 N 条数据而非全部数据行记录(示例:只查询前 100 条数据记录)

    sql
    1SELECT * FROM `order` LIMIT 100;

    知识点LIMIT 为限制的数据记录数方法,语法为 limit m,n,意思是从第 mm+n 条数据。m 可省略,默认值从 0 开始。例如,要从第 11 条开始取,取 10 条可以写为 SELECT * FROM \order` LIMIT 11, 10;`。

  • 只查询特定列(而非全部列)数据(示例:只查询 total_amountorder_id 两列数据)

    sql
    1SELECT total_amount, order_id from `order`;

    知识点:选择特定列只需将列名写到表达式中即可,多个列名用英文逗号分隔。另外,还可以使用 表名.字段名 的写法,这通常出现在多表关联查询中。

  • 查询特定列去重后的数据(示例:查询针对 user_id 去重后的数据)

    sql
    1SELECT DISTINCT user_id FROM `order`;

    知识点:关键词 DISTINCT 用于返回唯一不同的值。如果后面接多个字段,会默认对多个字段同时进行比较,只有多个字段完全相同时才会去重。

  • 查询带有 1 个条件的数据(示例:查询 total_amount < 100 的所有数据)

    sql
    1SELECT * FROM `order` WHERE total_amount < 100;

    知识点WHERE 是条件关键字。本示例中,由于 total_amount 为浮点型,因此直接可与数值型比较;如果是字符串型,则比较值需要加引号。

  • 查询带有多个条件(同时满足)的数据(示例:查询 total_amount < 100statusREMOVED 的所有数据)

    sql
    1SELECT * FROM `order` WHERE total_amount < 100 and `status` = 'REMOVED';

    知识点:多个条件使用 and 表示“且”的关系。由于 status 也是关键字,因此也需要使用反引号包裹。

  • 查询带有多个条件(满足任意一个)的数据(示例:查询 total_amount < 100statusREMOVED 的所有数据)

    sql
    1SELECT * FROM `order` WHERE total_amount < 100 or `status` = 'REMOVED';

    知识点:多个条件使用 or 表示“或”的关系,满足任意一个条件即可。

  • 查询特定条件值在某个值域范围内的数据(示例:查询 status 的值为 REMOVEDNO_PENDING_ACTIONPENDING_ORDER_CONFIRM

    sql
    1SELECT * FROM `order` WHERE `status` in ('REMOVED','NO_PENDING_ACTION','PENDING_ORDER_CONFIRM');

    知识点:对于特定字段采用“穷举法”列出值域,使用 in 列表会使得表达式更简单。

  • 使用正则表达式查询具有复杂条件的数据(示例:查询 user_id 以 106 开头且 order_id 包含 04 的所有订单数据)

    sql
    1SELECT * FROM `order` WHERE user_id LIKE '103%' and order_id LIKE '%04%';

    知识点:通过使用关键字 LIKE 来连接不同的正则语法。以 * 开头:'字符串%';以 * 结尾:'%字符串';包含 *'%字符串%'

  • 将查询到的数据倒序排列(示例:将 total_amount 金额在 10~100 之间的所有数据,按照订单 ID 倒序排序)

    sql
    1SELECT * FROM `order` WHERE 10 < total_amount < 100 ORDER BY order_id DESC;

    知识点:在 ORDER BY 的结尾,使用 DESC 表示倒序(逆序)排序;省略则默认使用 ASC 正序(顺序)排序。

  • 查询指定列中不包含空值的所有数据(示例:查询 order_id 不为空的所有数据)

    sql
    1SELECT * FROM `order` WHERE order_id IS NOT NULL;

    知识点:在 MySQL 中,IS NULL 表示为空,IS NOT NULL 表示非空。需要注意的是,NULL 不代表空字符串或者空格,而是真正意义上的没有任何数据。

上述案例只是展示了如何取数,更多情况下,我们会配合特定函数和方法做数据计算、整合和探索性分析,例如:

  • 使用 MySQL 聚合函数求算术平均值、计数、求最大最小值、做分类汇总等;
  • 使用 MySQL 数学函数,用来求绝对值、对数计算、平方根等;
  • 使用 MySQL 字符串函数进行字符串分割、组合、截取、匹配、处理等;
  • 使用 MySQL 的日期函数进行日期获取、转换、处理等;
  • 使用 MySQL 将多个表(2 个或 2 个以上)数据进行关联、匹配和整合。

4. 延伸思考:在 Python 还是 MySQL 中进行数据处理?

在 Pythoner(Python 工作者)看来,MySQL 的很多工作 Python 本身也能胜任,为什么还要耗费时间和精力学习如何在 MySQL 中完成这些数据工作,直接用 Python 读取数据然后基于 Python 的相关库进行数据运算岂不更好?

  • Python 的工作强项并不是数据计算,而是其灵活、高效、简易和集成多方的工作方式、效率和效果。MySQL(以及其他关系型数据库)作为成熟的数据存储和集成解决方案,在(关系型)数据本身方面更具优势,尤其是对于数据结构定义、关系操作、关系完整性约束等方面具有成熟且稳定的应用价值。因此可以说 MySQL 在结构化数据存储和初步处理工作上比 Python 更专业
  • 还有一个更加关键的原因是,如果所有数据工作都由 Python 完成,那么 Python 的事务处理在某些情况下一定会面临资源瓶颈、工作效率等问题,届时可能会导致程序崩溃和报错,这将大大降低程序的可靠性以及结果输出的效率,对于海量数据工作尤为如此。

因此,很多时候不是 Python 不能做,而是在合适的时机选择最合适的工具来完成才是最好的选择


2.2.4 从非关系型数据库 MongoDB 读取运营数据

由于 MongoDB 一般都是企业级数据存储,因此这里我们使用在第一章已经安装过的 SSH 远程客户端 SecureCRT。如果读者有自己在虚拟机或本地安装 MongoDB,也可以使用,操作方法类似。

1. 连接与配置 MongoDB

  1. 双击 SecureCRT 打开程序,点击顶部的“快速连接”按钮,新建连接。
    2-18
    2-18
    图 2-18 新建快速连接
  2. 根据服务器具体配置情况,配置如下信息,其中主机名和用户名需要单独配置,其他的根据实际情况询问 IT 或运维管理人员(本案例中都是默认值)。可勾选用于以后启动该程序时直接显示快捷入口。
    2-19
    2-19
    图 2-19 填写连接配置信息
  3. 点击连接之后,会弹出密码输入窗口,输入密码,可勾选用于以后无需重复输入密码,具体视公司安全规定执行。
    2-20
    2-20
    图 2-20 填写密码
  4. 如果服务器配置信息填写正确,连接服务器成功会显示如下信息:
    2-21
    2-21
    图 2-21 成功连接服务器

要想通过 Python 调用 MongoDB,需要安装 PyMongoDB,直接使用 pip install pymongo 即可实现。

注意 不同的服务器环境对于可访问外网的限制有差异。对于无法直接从服务器连接外网的,请参照“1.2.3 Python 第三方库”中的方法,先将安装包和依赖包下载到本机,然后再拷贝到服务器上,再通过 setuppip 命令安装。

使用 Python 连接 MongoDB 之前,需要服务器上的 MongoDB 处于启动状态。查看是否成功启动的方法是找一个可以直接连接或访问服务器的浏览器,直接输入 IP:端口,如果出现“It looks like you are trying to access MongoDB over HTTP on the native driver port.”字样的提示则说明已经正常启动和运行。

例如:笔者的服务器上已经启动了该服务,在浏览器中输入 http://10.66.202.134:27017/ 后提示如下信息:

2-22
2-22
图 2-22 MongoDB 服务启动后的浏览器返回信息

提示:MongoDB 也提供了 Windows 版本的程序,有兴趣的读者,可登陆官方下载中心下载程序并进行本地部署安装。

2. 使用 Python 读取 MongoDB 数据

要在服务器上进入 Python 环境,直接在终端窗口输入命令 python。在 Python 命令行窗口中,通过如下方法调用 MongoDB 数据。

python
1from pymongo import MongoClient # 导入库 2 3client = MongoClient() # 建立连接 4client = MongoClient('10.66.202.134', 27017) # 环境变量初始化 5db = client.test_py # 选择 test_py 库 6orders = db.ordersets # 选择 orders 集合 7 8# 定义数据集合用于插入 9terms = [ 10 {"user":"tony", "id": "31020", "age":"30", "products": ["215120", "245101","128410"], "date": "2017-04-06"}, 11 {"user": "lucy", "id": "32210", "age": "29", "products": ["541001", "340740", "450111"],"date": "2017-04-06"} 12] 13 14orders.insert_many(terms) # 插入数据 15print(orders.find_one()) # 获取一文档数据 16print('========================================') 17 18for i in orders.find(): # 获取所有文档数据并展示 19 print(i)

上述代码中,我们连接到 MongoDB 后选择了 test_py 库下的 ordersets 集合,然后插入 2 条数据到集合中,再从集合中查看单独一条以及所有集合数据。以下是代码执行后打印输出的结果:

code
1{u'age': u'30', u'products': [u'215120',u'245101', u'128410'], u'user': u'tony', u'date': u'2017-04-06', u'_id': ObjectId('58eb1f0b2f76bf26108b4898'), u'id': u'31020'} 2======================================== 3{u'age': u'30', u'products': [u'215120', u'245101', u'128410'], u'user': u'tony', u'date': u'2017-04-06', u'_id': ObjectId('58eb1f0b2f76bf26108b4898'), u'id': u'31020'} 4{u'age': u'29', u'products': [u'541001', u'340740', u'450111'], u'user': u'lucy', u'date': u'2017-04-06', u'_id': ObjectId('58eb1f0b2f76bf26108b4899'), u'id': u'32210'}

除了上述基本查询语句外,PyMongo 也提供了类似于 MySQL 一样的条件过滤:

  • 查询特定文档数据(示例:只查询第 2 条数据)

    python
    1orders.find()[1]

    知识点:通过增加索引值可以指定查询特定索引的文档数据。注意索引值从 0 开始。

  • 查询特定范围内的文档数据(示例:只查询第 1-2 条数据)

    python
    1orders.find()[0:2]

    知识点:通过增加索引值可以指定查询特定索引范围的文档数据(切片)。索引结束值默认不包含。

  • 增加查询条件(示例:只查询 userlucy 的文档数据)

    python
    1orders.find({"user": "lucy"}) # 所有数据,注意使用迭代方法查看数据 2orders.find_one({"user": "lucy"}) # 单条数据

    知识点:作为 Key-Value 形式的代表应用之一,MongoDB 几乎所有的用法都以 K-V 的形式存在。只需在 find 函数中,以 Key-Value 的形式设置过滤条件即可。

  • 排序(示例:针对 user 排序输出)

    python
    1orders.find({"user": "lucy"}).sort("user")

    知识点:通过使用 Sort 方法设置排序维度。默认是正序,也可以指定为倒序排列,同时也可以指定多个字段排序规则。

总结:在企业实际应用中,非关系型数据库往往基于“大数据”的场景产生,伴随着海量、实时、多类型等特征而来。这些数据库通过舍弃了关系型数据库的某些特征和约束,然后在特定方面进行增强,因此才能满足特定应用需求。非关系型数据库由于约束性、规范性、一致性和数据准确性低于关系性数据库,因此常用于实时海量数据读写、非结构化和半结构化信息读写、海量集群扩展、特殊场景应用等


2.2.5 从 API 获取运营数据

为了更好的让所有读者都能了解从 API 获取数据的具体过程,本节使用百度免费 API 作为实际数据来源。百度 API 提供了众多地图类功能,可用于基本地图、位置搜索、周边搜索、公交驾车导航、定位服务、地理编码及逆地理编码等。

本节使用的是百度 Web 服务 API 中的 Geocoding API。Geocoding API 用于提供从地址到经纬度坐标或者从经纬度坐标到地址的转换服务,用户可以发送请求且接收 JSON、XML 的返回数据。该应用可用于对运营数据中的地址相关信息进行解析,从而获得有关经纬度信息。

1. 准备工作:获取百度地图 API 密钥 (AK)

要获得该 API,读者需要拥有百度相关账户和 AK 信息:

  1. 获得百度账户:没有账户的读者可在百度通行证免费注册获取。
  2. 注册成为开发者:进入百度地图开放平台完成相关注册。该过程非常简单,遵循引导整个过程在 5 分钟以内即可完成。
    2-23
    2-23
    图 2-23 提交成功
  3. 激活验证:注册完成之后,会有一封名为“【百度地图开放平台】开发者激活邮件”发送验证链接到指定邮箱,点击链接进行验证。
    2-24
    2-24
    图 2-24 激活验证链接
  4. 创建应用:点击“申请秘钥”进入创建应用界面,在该应用创建中,我们主要使用 Geocoding API v2,其他应用服务根据实际需求勾选。IP 白名单区域,如果不做限制,请设置为“0.0.0.0/0”。设置完成后,点击提交。
    2-25
    2-25
    图 2-25 创建应用
  5. 获得 AK 秘钥:完成上述步骤之后,会默认跳转到应用列表界面,界面中的“访问应用(AK)”便是该应用的秘钥。
    2-26
    2-26
    图 2-26 获得 AK 秘钥

2. 获取并解析 JSON 数据

我们先通过 Python 请求该 API 来获得 JSON 格式的数据。本示例的目标是通过给百度 API 发送一条地理位置数据,返回其经纬度信息。本节会用到 Python 第三方库 requests,读者需要先通过 pip install requests 进行安装。完整代码如下:

python
1import requests # 导入库 2 3add = '北京市中关村软件园' # 定义地址 4ak = 'DdOyOKo0VZBgdDFQnyhINKYDGkzBkuQr' # 创建访问应用时获得的 AK 5url = 'http://api.map.baidu.com/geocoder/v2/?address=%s&output=json&ak=%s' # 请求 URL 6 7res = requests.get(url % (add, ak)) # 获得返回请求 8add_info = res.text # 返回文本信息 9print(add_info) # 打印输出
  • 在上述代码中,我们先导入一个 requests 库,该库用来发送网络请求,支持多种发送模式。
  • 第二行我们定义了一个地址,该地址通常是运营中的地址类信息。
  • 第三行 ak 是创建访问应用时获得的 AK,注意百度有每天 6000 次的限制,读者可填写自行申请的 AK。
  • 第四行定义了一个通过 get 方法发送的 URL 请求地址,地址中的 addressak 的具体值使用占位符代替,在后面用到时具体赋值。

提示 在 API 请求方法中,最常用的是 GETPOST 方法。前者用于向服务器以“明文”(所有参数都在 URL 中体现)的形式请求数据;后者则以“暗语”(所有的数据信息都在 HTTP 消息中)以键值对的形式发送,常用于数据保密性高的场景。

以下是代码执行后打印输出的结果:

json
1{"status":0,"result":{"location":{"lng":116.29933765654373,"lat":40.05399730253742},"precise":0,"confidence":40,"level":"工业园区"}}

返回结果包括以下字段:

  • status:返回结果状态值,成功返回 0。
  • location:经纬度坐标,其中 lat 是纬度值,lng 是经度值。
  • precise:位置的附加信息,是否精确查找。1 为精确查找,0 为模糊打点。
  • confidence:可信度,描述打点准确度。
  • level:百度定义的地址类型。

该结果可以通过 JSON 进行格式化处理:

python
1import json # 导入库 2 3add_json = json.loads(add_info) # 加载 Json 字符串对象 4lat_lng = add_json['result']['location'] # 获得经纬度信息 5print(lat_lng) # 打印输出

代码中,我们导入 Python 自带的 json 库。先将获得的地址信息格式化为 JSON 字符串(字典类型),然后通过读取字典的 Key 来获得其 Value。上述代码执行后,返回的结果(字典类型)可进行进一步处理:

code
1{u'lat': 40.05399730253742, u'lng':116.29933765654373}

3. 获取并解析 XML 数据

Geocoding API 也提供 XML 格式的返回数据,下面以获得 XML 格式的数据为例介绍代码过程。

python
1import requests # 导入库 2 3add = '北京市中关村软件园' # 定义地址 4ak = 'DdOyOKo0VZBgdDFQnyhINKYDGkzBkuQr' # 创建访问应用时获得的 AK 5url = 'http://api.map.baidu.com/geocoder/v2/?address=%s&output=xml&ak=%s' # 请求 URL 6 7res = requests.get(url % (add, ak)) # 获得返回请求 8add_info = res.text # 返回文本信息 9print(add_info) # 打印输出

上述所有代码与 JSON 格式的代码完全相同,只在第四行定义 URL 时,将 output 的返回值类型设置为 xml,执行后返回结果如下:

xml
1<?xml version="1.0" encoding="utf-8"?> 2<GeocoderSearchResponse> 3 <status>0</status> 4 <result> 5 <location> 6 <lng>116.299337657</lng> 7 <lat>40.0539973025</lat> 8 </location> 9 <precise>0</precise> 10 <confidence>40</confidence> 11 <level>工业园区</level> 12 </result> 13</GeocoderSearchResponse>

接着我们通过引入一个 XML 格式化处理库来从中提取经纬度信息。我们使用 Python 自带的 xml 进行处理:

python
1import sys 2reload(sys) 3sys.setdefaultencoding('utf-8') # 设置字符编码为 utf-8 4 5import xml.etree.ElementTree as Etree # 导入 xml 中的 ElementTree 方法 6 7root = Etree.fromstring(add_info) # 获得 xml 的根节点 8lng = root[1][0][0].text # 获得 lng 数据 9lat = root[1][0][1].text # 获得 lat 数据 10 11print('lng: %s' % lng) # 格式化打印输出 12print('lat: %s' % lat) # 格式化打印输出

上述代码中,前 4 行实现了一个功能,将代码的字符编码设置为 utf-8,否则系统会默认为 ASCII,对返回的带有中文字符串无法识别而报错。代码第五行导入 XML 自带的 ElementTree 方法,该方法可以实现对 XML 内容的查询、新建、修改等操作。

上述代码执行后返回结果如下:

code
1lng: 116.299337657 2lat: 40.0539973025

总结:在 API 应用中,中文的编码处理常常是非常头疼的细节。因此,如果可以尽量少的直接在 API 的数据中出现中文字符。在实际企业应用中,会出现多种 API 形式,但无论哪种形式,其基本实现思路都是一致的:导入库 → 定义请求变量 → 发送请求 → 获得返回数据 → 格式化并获得目标数据,因此需要熟练掌握 JSON 和 XML 的数据与其他数据的转换方法。

分享
最后修订: 2019-01-04