美文网首页程序员大数据
教你从txt文件中提取json格式的省市区数据

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

作者: 天涯待归客 | 来源:发表于2017-03-17 18:26 被阅读3675次

    伟大的国家统计局为我们提供了省市区的信息[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格式的省市区数据

        本文链接:https://www.haomeiwen.com/subject/luuenttx.html