购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

5.7 上机实践演练
——开放数据的提取与应用

随着世界各个国家和地区致力于倡导数据开放,培养民众的数据能力,支持数据创新的推动,中国各地在推行开放数据(Open Data)上也不遗余力,纷纷设立了开放平台、网站供民众使用。例如,北京市政务数据资源网、上海市政府数据服务网等,可以提供浏览和下载的数据有经济建设、道路交通、资源环境等。人们可以很方便地获取所需的开放数据,通过程序的开发将这些数据进行更有效的应用。本章的范例将介绍如何从公开数据平台获取数据并加以运用。

5.7.1 什么是开放数据

开放数据是开放、免费、透明的数据,不受著作权、专利权所限制,任何人都可以自由使用和散布。这些开放数据通常会以开放文件格式(如CSV、XML及JSON等格式)提供用户下载应用,经过汇总和整理之后,这些开放数据就能提供更有效的信息,甚至成为有价值的商品。

例如,有人将开放数据平台开放的空气污染与降雨数据汇总和整理成图表,并且在超出一定数值时提出警示。

北京市政务数据资源网的网址为 www.bjdata.gov.cn ,网站首页如图5-18所示。这些网站集合了不少开放数据,大家可以去看看有哪些是自己需要的数据。

图5-18

5.7.2 获取开放数据

开放数据平台一般会提供三种数据格式的数据文件供用户下载:XML、JSON及CSV。有的平台也会直接提供Excel格式的数据文件供人们下载。

如果数据更新频率较高,比如“空气质量实时监测数据”通常每小时更新一次,对于这类数据,我们可以在文件链接处右击,再选择“复制链接网址”来获取URL(Uniform Resource Locator,网址),然后通过Python随时获取最新的数据,下一小节将说明如何操作。

虽然开放数据是免费获取的,但是在使用时大部分都会要求必须标示数据的来源,因此下载前需要先阅读授权说明。

CSV、XML和JSON三种开放数据格式是常见的数据交换格式,CSV格式是用逗号分隔的纯文本文件(如图5-19所示),前面已经介绍并且使用过,这里不再赘述。下面说明XML与JSON格式。

技巧

为了便于演示如何编写程序使用这些开放数据,我们用一个样例的小数据文件,以免数据过大影响我们运行范例程序的效率,大家在实际工作中用真实的数据文件替换掉这个样例文件即可。

图5-19

1.XML格式

XML是可扩展标记语言(Extensible Markup Language),允许用户自行定义标签(tags),可以定义每种商业文件的格式,并且能用于不同的应用程序。XML格式类似HTML,与HTML最大的不同在于XML是以结构与信息内容为目标的,由标签定义出文件的结构,如标题、作者、书名等,补足了HTML只能定义文件格式的缺点,XML的特点是易于设计并且可以跨平台使用,如图5-20所示。

图5-20

标签是以“<”与“>”符号括起来,各个标签称为“元素(element)”,标签必须成对,包括“开始标签”与“结束标签”,标签之间的文字称为内容(content),如图5-21所示。

图5-21

XML的文件结构就像树结构一样,以这份XML文件为例,<SiteName>的父元素是<Data>,每一组<Data>元素里面都包含测站名称、城市以及各种指标等子元素。

2.JSON格式

JSON(JavaScript Object Notation)格式是JavaScript的对象表示法,是轻量的数据交换格式,文件小,适用于网络数据传输。

JSON有两种形式:列表(数组)与对象。列表以“[”符号开始,以“]”符号结束,里面通常会包含对象集合(collection),每一组集合用逗号分隔,例如:


[collection, collection]

对象(Object)以“{”符号开始,以“}”符号结束,里面包含名称与值,形式如下:


{name:value}

如图5-22所示是一个JSON格式文件的例子。

图5-22

JSON不需要换行,所以看起来密密麻麻,如果将它写成下面的格式,就可以很清楚地看出每个集合里的内容:


[
{
"SiteName":"三林",
"City":"丙一市",
"PSI":"66",
...
},
{
"SiteName":"三川",
"City":"乙二市",
"PSI":"58",
...
}
....
]

XML是一种标记语言,程序需要解析标记,这会花费比较多的时间;而JSON格式文件小,非常容易解析。下面我们将实际操作,大家可以比较这两种格式的差别。

5.7.3 范例程序说明

本范例假设从一个开放数据平台取得“空气质量实时监测数据”的JSON与XML格式数据,取出“测站名称”“城市”“PM2.5浓度”“状态”与“发布时间”,分别存储为CSV文件并打印输出。

注意:下面程序中的网站地址都不是实际的,读取的数据字段也是假定的,但是程序的逻辑是没有问题的。大家在实际运用中可以替换成真实的网址,再根据实际读取的JSON与XML数据字段修改程序中的语句。

输入说明

从开放数据平台获取“空气质量实时监测数据”的JSON与XML链接URL。

输出范例

XML格式保存为pm_xml.csv文件,内容如图5-23所示,大家只要参考这个输出文件大致的样子就行,内容是虚构的,重点是看程序的整体结构。另外,JSON格式不保存,只将结果打印输出。

图5-23

制作步骤

XML格式文件内容的提取步骤如下:

步骤01 提取网页(URL)的内容。

步骤02 使用BeautifulSoup模块解析XML标记(或标签)。

步骤03 保存为CSV文件。

JSON格式文件内容的提取步骤如下:

步骤01 提取网页(URL)的内容。

步骤02 使用JSON模块解析JSON数据。

步骤03 打印输出。

5.7.4 程序代码说明

Python有多种模块可用于抓取网页的数据,这里我们使用urllib.request模块,以下程序是最基本的使用方式:


import urllib.request as ur
with ur.urlopen(od_url) as response:
    get_xml=response.read()

urllib.request模块的使用非常简单,只要将网址传入urlopen函数就会返回HttpResponse对象,接着可以使用read()方法将网页内容读取出来。

取出来的网页内容有一大串,我们要通过编程从里面找到需要的内容,也就是所谓的“爬虫(Crawler)”。

Python提供了许多爬虫模块,HTML与XML网页的结构都属于标记结构,适合使用BeautifulSoup模块来解析;而JSON格式直接使用JSON模块更方便。

下面我们来看看XML格式的解析方式,可以打开xml_parse.py范例文件来查看完整的程序代码。

1.BeautifulSoup 4模块

BeautifulSoup模块的使用方式如下:


from bs4 import BeautifulSoup
data = BeautifulSoup(get_xml,'xml')
SiteName = data.find_all('SiteName')

BeautifulSoup模块用来从HTML或XML格式文件中通过标记找出想要的数据,版本是Beautiful Soup 4.x,模块库已更名为bs4,所以使用前要先加载bs4模块。我们可以直接用from bs4 import BeautifulSoup来加载BeautifulSoup类。

BeautifulSoup常用的方法与属性如表5-7所示。

表5-7

范例程序中调用了find_all方法来搜索特定的标记,程序语句如下:


SiteName = data.find_all('SiteName')
City = data.find_all('City')
Status = data.find_all('Status')
pm25 = data.find_all('PM2.5')
PublishTime = data.find_all('PublishTime')

使用for循环可以提取所有的标记内容,程序语句如下:


for i in range(0, len(SiteName)):
    csv_str += "{},{},{},{},{}\n".\
                format(SiteName[i].get_text(),\
                    County[i].get_text(),pm25[i].\
                        get_text(),Status[i].get_text(),\
                            PublishTime[i].get_text())

取出的数据如果还有其他用途,可以将其保存为CSV文件,语法如下:


with open("pm_xml.csv", "w") as f:
    story=f.write(csv_str)    #写入文件

接着我们继续介绍JSON格式的解析方式,我们可以打开范例文件json_parse.py来查看完整的程序代码。

2.JSON模块

JSON模块在使用之前同样需要import json,然后使用loads()方法将JSON格式的字节(byte)数据译码成Python的列表(list)结构,使用方式如下:


import json
data = json.loads(s)

如此一来,就可以直接用Python的列表操作方式取出数据了,例如取出第一个元素的SiteName,只要如下表示即可:


data[0]["SiteName"]

因此,使用for循环就能轻松地取出所需要的标记内容。这个范例不再保存为CSV文件,而是直接打印输出格式化数据。

技巧

如果想要解析的不是JSON字符串而是JSON文件,可以调用load()方法,例如:


with open('data.json', 'r') as f:
    data = json.load(f)

以下为完整的xml_parse.py和json_parse.py程序代码,供大家参考。

【范例程序:xml_parse.py】OpenData数据的提取与应用


01        # -*- coding: utf-8 -*-
02        """
03        OpenData数据的提取与应用
04        XML格式
05        """
06        od_url="http://这里填入实际要使用的开放数据网的网址"
07
08        import urllib.request as ur
09
10        with ur.urlopen(od_url) as response:
11            get_xml=response.read()
12
13        from bs4 import BeautifulSoup
14
15        data = BeautifulSoup(get_xml,'xml')
16        SiteName = data.find_all('SiteName')
17        City = data.find_all('City')
18        Status = data.find_all('Status')
19        pm25 = data.find_all('PM2.5')
20        PublishTime = data.find_all('PublishTime')
21
22        csv_str = ""
23        for i in range(0, len(SiteName)):
24            csv_str += "{},{},{},{},{}\n".\
25                        format(SiteName[i].get_text(),\
26                               City[i].get_text(),\
27                                     pm25[i].get_text(),\
28                                     Status[i].get_text(),\
29                                           PublishTime[i].get_text())
30
31        with open("pm_xml.csv", "w") as f:
32            story=f.write(csv_str)    #写入文件
33
34        print("完成")

【范例程序:json_parse.py】 kimEht6DIgAqTRxiGJqDFG/fLm4AcP3V+ZrkT0E5mo5Hg8oxK2BaMSzFW3BZaDGV


01        # -*- coding: utf-8 -*-
02        """
03        OpenData数据的提取与应用
04        JSON格式
05        """
06        od_json="http://这里填入实际要使用的开放数据网的网址"
07
08        import urllib.request as ur
09        with ur.urlopen(od_json) as response:
10            s=response.read()
11
12        import json
13        data = json.loads(s)
14        csv_str=""
15        for i in range(0, len(data)):
16            csv_str += "{},{},{},{},{}\n".\
17                        format(data[i]["SiteName"],\
18                               data[i]["County"],data[i]["PM2.5"],\
19                                   data[i]["Status"],data[i]["PublishTime"])
20
21        print(csv_str)

点击中间区域
呼出菜单
上一章
目录
下一章
×