教你从txt文件中提取json格式的省市区数据

伟大的国家统计局为我们提供了省市区的信息[1],可惜不是json格式的,并不能真正用起来。为了得到我们所需要格式化的数据,笔者开发了一个将txt格式的省市区转化为json格式的python脚本。(结尾有小惊喜哦 _

操作系统:ubuntu mate[2],python版本:python3.4,编辑器:pluma。

国家统计局网站上的省市区信息,代码中都没有层级结构,用BeautifulSoup[3]解析也是浪费时间,笔者直接把它复制粘贴到了city.txt中。

下面开始开发脚本:

定义模型

省市区本身就是三个现成的对象,不难想到:

# province of china
class Province:
    def __init__(self, code, name):
        self.code = code
        self.name = name

# city of province
class City:
    def __init__(self, code, name):
        self.code = code
        self.name = name

# coutry of city
class Country:
    def __init__(self, code, name):
        self.code = code
        self.name = name

对于省市而言,它们还有各自的下属行政区,所以要加上一个sub属性来把它们的下属囊括进来。

class Province:
    def __init__(self, code, name):
        # ...
        self.sub = []

class City:
    def __init__(self, code, name):
        # ...
        self.sub = []

这样,我们的省市区模型就算初步定义完成了。

创建方法

有了模型还不够,只有加上合适的方法,才能显示出面向对象的优势。
我们需要一个返回对象的方法 __repr__(),这是一个常见的方法,只要我们提供对象的名称,就能返回必要的对象信息,便于开发和调试。

class Province:
    # ...
    def __repr__(self):
        return '''{"code":%r ,"name": %r, "sub":%r}\n''' % (self.code, self.name, self.sub)

class City:
    # ...
    def __repr__(self):
        return '''{"code":%r ,"name": %r, "sub":%r}\n''' % (self.code, self.name, self.sub)

class Country:
    # ...
    def __repr__(self):
        return '''{"code":%r, "name": %r}\n''' % (self.code, self.name)

当所有的省级行政区构建完成时,输出这个对象的字符串形式就是最终的json数据。为了保证json的格式,我们的 __repr__() 方法是自定义的,输出的结果既没有类的名称,也没有 用<> 括起来。

为了构建一个完整的省市级行政区,我们还需要一种归属的方法,将下属市和区加到sub数组里。可以用数组的 append() 方法来实现:

class Province:
    # ...
    def consist(self, city):
        self.sub.append(city)

class City:
    # ...
    def consist(self, country):
        self.sub.append(country)

此外,还需要一个函数来判断行政区的等级。简单观察一下city.txt,就不难找到这个规律。

所有的省级行政区的代码结尾都是 0000,所有的地级市的代码结尾都是 00,其它都是区县级的行政区划。

举个栗子:江苏的代码是:320000,南京的代码是:320100,秦淮区的代码是:320104。

所以,笔者写了一个根据结尾的0来判定级别的方法:

# judge the type by code
def zero(n):
    i = 1
    if n <= 0:
        return 0
    while n % i == 0:
        i *= 10
    return i/10

解析文本

接下来,就按行读取city.txt中的数据,简单粗暴见效快。

def get_data(filename):
    arr = []
    # open the city.txt
    with open(filename, "r", encoding="utf-8") as read:
        print("file has been open.")
        for line in read:
            arr.append(line.strip())
    print("reading finished")
    return arr

这里唯一值得注意的是:city.txt的编码是什么,打开文件指定的编码就是什么。这里的编码是:utf-8。

输出json

还是要观察city.txt,除了省级行政区是顶行的,其它的都有数量不等的空格。get_data() 方法得到的实际上是一个数组,其中的元素是类似这样110100 市辖区。从中我们也可以看到空格的存在。空格的utf-8编码是 \u3000,使用 strip("\u3000") 来除去首尾的空格。然后将数字保存为code,有效字符保存为name。然后根据 zero() 方法返回的结果构建相应的对象。最后将省级的对象输出就得到了省市区json数据。

最后,揭晓这个小惊喜:源代码和抓取到的json数据可以到我的 github 上获取。链接:https://github.com/zhancongc/city_parse

附录

  1. 统计局网址:http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/201703/t20170310_1471429.html
  2. 本程序在ubuntu mate下运行正常,输出正常;window 10下运行,输出的中文会乱码,原因尚不明确。
  3. Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库。它能够通过你喜欢的转换器实现惯用的文档导航、查找、修改文档的方式。

你可能感兴趣的:(教你从txt文件中提取json格式的省市区数据)