教你從txt文件中提取json格式的省市區(qū)數(shù)據(jù)

偉大的國(guó)家統(tǒng)計(jì)局為我們提供了省市區(qū)的信息[1],可惜不是json格式的方灾,并不能真正用起來(lái)牛哺。為了得到我們所需要格式化的數(shù)據(jù),筆者開發(fā)了一個(gè)將txt格式的省市區(qū)轉(zhuǎn)化為json格式的python腳本议忽。(結(jié)尾有小驚喜哦 _

操作系統(tǒng):ubuntu mate[2],python版本:python3.4十减,編輯器:pluma栈幸。

國(guó)家統(tǒng)計(jì)局網(wǎng)站上的省市區(qū)信息愤估,代碼中都沒(méi)有層級(jí)結(jié)構(gòu),用BeautifulSoup[3]解析也是浪費(fèi)時(shí)間速址,筆者直接把它復(fù)制粘貼到了city.txt中玩焰。

下面開始開發(fā)腳本:

定義模型

省市區(qū)本身就是三個(gè)現(xiàn)成的對(duì)象,不難想到:

# 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

對(duì)于省市而言芍锚,它們還有各自的下屬行政區(qū)昔园,所以要加上一個(gè)sub屬性來(lái)把它們的下屬囊括進(jìn)來(lái)。

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

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

這樣并炮,我們的省市區(qū)模型就算初步定義完成了默刚。

創(chuàng)建方法

有了模型還不夠,只有加上合適的方法渣触,才能顯示出面向?qū)ο蟮膬?yōu)勢(shì)羡棵。
我們需要一個(gè)返回對(duì)象的方法 __repr__(),這是一個(gè)常見的方法嗅钻,只要我們提供對(duì)象的名稱皂冰,就能返回必要的對(duì)象信息,便于開發(fā)和調(diào)試养篓。

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)

當(dāng)所有的省級(jí)行政區(qū)構(gòu)建完成時(shí)秃流,輸出這個(gè)對(duì)象的字符串形式就是最終的json數(shù)據(jù)。為了保證json的格式柳弄,我們的 __repr__() 方法是自定義的舶胀,輸出的結(jié)果既沒(méi)有類的名稱,也沒(méi)有 用<> 括起來(lái)碧注。

為了構(gòu)建一個(gè)完整的省市級(jí)行政區(qū)嚣伐,我們還需要一種歸屬的方法,將下屬市和區(qū)加到sub數(shù)組里萍丐⌒耍可以用數(shù)組的 append() 方法來(lái)實(shí)現(xiàn):

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

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

此外,還需要一個(gè)函數(shù)來(lái)判斷行政區(qū)的等級(jí)逝变。簡(jiǎn)單觀察一下city.txt基茵,就不難找到這個(gè)規(guī)律。

所有的省級(jí)行政區(qū)的代碼結(jié)尾都是 0000壳影,所有的地級(jí)市的代碼結(jié)尾都是 00拱层,其它都是區(qū)縣級(jí)的行政區(qū)劃。

舉個(gè)栗子:江蘇的代碼是:320000宴咧,南京的代碼是:320100根灯,秦淮區(qū)的代碼是:320104。

所以,筆者寫了一個(gè)根據(jù)結(jié)尾的0來(lái)判定級(jí)別的方法:

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

解析文本

接下來(lái)箱吕,就按行讀取city.txt中的數(shù)據(jù)芥驳,簡(jiǎn)單粗暴見效快。

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怎栽,除了省級(jí)行政區(qū)是頂行的,其它的都有數(shù)量不等的空格宿饱。get_data() 方法得到的實(shí)際上是一個(gè)數(shù)組熏瞄,其中的元素是類似這樣110100 市轄區(qū)。從中我們也可以看到空格的存在谬以∏恳空格的utf-8編碼是 \u3000,使用 strip("\u3000") 來(lái)除去首尾的空格为黎。然后將數(shù)字保存為code邮丰,有效字符保存為name。然后根據(jù) zero() 方法返回的結(jié)果構(gòu)建相應(yīng)的對(duì)象铭乾。最后將省級(jí)的對(duì)象輸出就得到了省市區(qū)json數(shù)據(jù)剪廉。

最后,揭曉這個(gè)小驚喜:源代碼和抓取到的json數(shù)據(jù)可以到我的 github 上獲取炕檩。鏈接:https://github.com/zhancongc/city_parse

附錄

  1. 統(tǒng)計(jì)局網(wǎng)址:http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/201703/t20170310_1471429.html
  2. 本程序在ubuntu mate下運(yùn)行正常斗蒋,輸出正常;window 10下運(yùn)行笛质,輸出的中文會(huì)亂碼泉沾,原因尚不明確。
  3. Beautiful Soup 是一個(gè)可以從HTML或XML文件中提取數(shù)據(jù)的Python庫(kù)妇押。它能夠通過(guò)你喜歡的轉(zhuǎn)換器實(shí)現(xiàn)慣用的文檔導(dǎo)航跷究、查找、修改文檔的方式舆吮。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末揭朝,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子色冀,更是在濱河造成了極大的恐慌潭袱,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,423評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锋恬,死亡現(xiàn)場(chǎng)離奇詭異屯换,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,147評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門彤悔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)嘉抓,“玉大人,你說(shuō)我怎么就攤上這事晕窑∫制” “怎么了?”我有些...
    開封第一講書人閱讀 157,019評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵杨赤,是天一觀的道長(zhǎng)敞斋。 經(jīng)常有香客問(wèn)我,道長(zhǎng)疾牲,這世上最難降的妖魔是什么植捎? 我笑而不...
    開封第一講書人閱讀 56,443評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮阳柔,結(jié)果婚禮上焰枢,老公的妹妹穿的比我還像新娘。我一直安慰自己舌剂,他們只是感情好济锄,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,535評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著架诞,像睡著了一般拟淮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谴忧,一...
    開封第一講書人閱讀 49,798評(píng)論 1 290
  • 那天很泊,我揣著相機(jī)與錄音,去河邊找鬼沾谓。 笑死委造,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的均驶。 我是一名探鬼主播昏兆,決...
    沈念sama閱讀 38,941評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼妇穴!你這毒婦竟也來(lái)了爬虱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,704評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤腾它,失蹤者是張志新(化名)和其女友劉穎跑筝,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞒滴,經(jīng)...
    沈念sama閱讀 44,152評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡曲梗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,494評(píng)論 2 327
  • 正文 我和宋清朗相戀三年赞警,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片虏两。...
    茶點(diǎn)故事閱讀 38,629評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡愧旦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出定罢,到底是詐尸還是另有隱情笤虫,我是刑警寧澤,帶...
    沈念sama閱讀 34,295評(píng)論 4 329
  • 正文 年R本政府宣布祖凫,位于F島的核電站耕皮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蝙场。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,901評(píng)論 3 313
  • 文/蒙蒙 一粱年、第九天 我趴在偏房一處隱蔽的房頂上張望售滤。 院中可真熱鬧,春花似錦台诗、人聲如沸完箩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)弊知。三九已至,卻和暖如春粱快,著一層夾襖步出監(jiān)牢的瞬間秩彤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,978評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工事哭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留漫雷,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,333評(píng)論 2 360
  • 正文 我出身青樓鳍咱,卻偏偏與公主長(zhǎng)得像降盹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谤辜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,499評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容