Skip to content

ねたみまん

Webサイト運営の裏側で必要な技術、テクニック、マーケティング、考え方などのメモを記事にしたサイトです

Archive

Category: SQLite3

昨日の「Djangoで郵便番号を一気に取り込む」を参考に自分で作っていた方のスクリプトを改変したものが以下です。

こちらはcsvもsplitとstripで処理。半角カナは使わないので取り込むのをあきらめています。

郵便局の郵便番号辞書はこのスプリクトと同じディレクトリ(フォルダ)においてあります。

取り込む時間は約56秒。前は終わるまで待てなかったので、かなりのスピードアップです。

モデルの定義 プロジェクト/ziplist/models.py

# -*- coding: utf-8 -*-
from django.db import models

# Create your models here.

class Ziplist(models.Model):
    cityno = models.CharField(u'全国地方公共団体コード', max_length = 10)
    oldzip = models.CharField(u'旧郵便番号', max_length=5)
    zipcode = models.CharField(u'郵便番号', max_length=7)
    pref = models.CharField(u'都道府県', max_length=20)
    city = models.CharField(u'市区町村名', max_length=100)
    town = models.CharField(u'町域名', max_length= 100)
    two_code = models.BooleanField(u'一町域が二以上の郵便番号で表される場合の表示')
    banchi = models.BooleanField(u'小字毎に番地が起番されている町域の表示')
    chome =models.BooleanField(u'丁目を有する町域の場合の表示')
    two_town = models.BooleanField(u'一つの郵便番号で二以上の町域を表す場合の表示')

    def __unicode__(self):
        return self.zipcode + ' ' + self.pref + self.city + self.town

    class Meta:
        db_table = 'ziplist'

郵便番号取り込みスクリプト import_zipcode.py :shell(コマンドプロンプト)で実行用。プロダクションディレクトリに置いてある

# -*- coding: utf-8 -*-
from django.core.management import setup_environ
try:
    import settings # Assumed to be in the same directory.
except ImportError:
    import sys
    sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
    sys.exit(1)

setup_environ(settings)

import codecs, time
from django.db import transaction
from ziplist.models import Ziplist

@transaction.commit_manually
def import_zipcode():
    fin = codecs.open('KEN_ALL.CSV', 'r', 'cp932')
    li = 1
    start = time.clock()

    for line in fin:
        datas = line.split(',')
        for idx in range(len(datas)):
            datas[idx] = datas[idx].strip('" ')
        zip = Ziplist()
        zip.cityno = datas[0]
        zip.oldzip = datas[1]
        zip.zipcode = datas[2]
        zip.pref = datas[6]
        zip.city = datas[7]
        zip.town = datas[8]
        zip.tow_code = '1' == datas[9]
        zip.banchi = '1' == datas[10]
        zip.chome  = '1' == datas[11]
        zip.tow_town = '1' == datas[12]
        zip.save()

        li+=1
        if li%1000 == 0:
            print '%d: %.2f' % (li, time.clock() - start)

    transaction.commit()
    print 'end: %.2f' % (time.clock() - start)

    fin.close

import_zipcode()

取り込んだ結果を Django のShellで試してみる

C:\_work\python\zipcode>manage.py shell
Python 2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from ziplist.models import Ziplist
>>> adds = Ziplist.objects.filter(zipcode__startswith = '102')
>>> len(adds)
15
>>> for add in adds:
...     print add.__unicode__().encode('cp932')
...
1020072 東京都千代田区飯田橋
1020082 東京都千代田区一番町
1020094 東京都千代田区紀尾井町
1020091 東京都千代田区北の丸公園
1020074 東京都千代田区九段南
1020073 東京都千代田区九段北
1020083 東京都千代田区麹町
1020076 東京都千代田区五番町
1020075 東京都千代田区三番町
1020084 東京都千代田区二番町
1020092 東京都千代田区隼町
1020093 東京都千代田区平河町
1020071 東京都千代田区富士見
1020081 東京都千代田区四番町
1020085 東京都千代田区六番町
>>>

\は日本語環境では¥です。なぜかWordPressに貼り付けると半角円記号はバックスラッシュになってしまいます??

Djangoで前方一致検索するときは モデル名.objects.filter( フィールド名__startswith = “検索値”) と書く。

詳しくは Django ドキュメント クエリを生成する フィールドの照合を参照してください。

顧客管理で住所の入力は出来るだけカンタンにしたい。

ということで、郵便番号辞書は必須。

郵便番号を読み込むプログラムを試してみた。
始めは自分で作ってたんだけど、読み込みに時間がかかるのでまたもやネットを探してみた。

TSUYUKI.MAKOTO にあった記事を元に、ワントランザクションでのプログラムにしてみた。

データモデル

from django.db import models

# Create your models here.

class ZipCode(models.Model):
zipcode = models.CharField(‘Zip Code’, max_length=7, db_index=True)
prefecture_kana = models.CharField(‘Prefecture Kana’, max_length=20)
city_kana = models.CharField(‘City Kana’, max_length=100)
town_kana = models.CharField(‘Town Kana’, max_length=100)
prefecture = models.CharField(‘Prefecture’, max_length=20)
city = models.CharField(‘City’, max_length=100)
town = models.CharField(‘Town’, max_length=100)

def __unicode__(self):
return ‘%s: %s %s %s’ % (self.zipcode, self.prefecture, self.city, self.town)

読み込みようプログラム

import sys, os, csv, time
from django.core.management import setup_environ
try:
import settings # Assumed to be in the same directory.
except ImportError:
import sys
sys.stderr.write(“Error: Can’t find the file ‘settings.py’ in the directory containing %r. It appears you’ve customized things.\nYou’ll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it’s causing an ImportError somehow.)\n” % __file__)
sys.exit(1)

setup_environ(settings)

from django.conf import settings
from django.db import IntegrityError, transaction
from zipcode.models import ZipCode

try:
import zenhan
except ImportError:
print ”’You need zenhan.py .
Download zenhan.py and install it.

http://matatabi.homeip.net/blog/setomits/877

”’
sys.exit()

#
#from django.db import connection
#cursor = connection.cursor()
#cursor.execute(‘PRAGMA temp_store = MEMORY;’)
#cursor.execute(‘PRAGMA synchronous=OFF’)

from django.core.management import call_command
call_command(‘syncdb’)

reader = csv.reader(open(‘KEN_ALL.CSV’, ‘rb’))

@transaction.commit_manually
def import_zip(reader):
counter = 0
start = time.clock()
for data in reader:
try:
zipcode = ZipCode(zipcode=data[2],
prefecture_kana=zenhan.h2z(unicode(data[3], ‘shift_jis’), zenhan.KANA),
city_kana=zenhan.h2z(unicode(data[4], ‘shift_jis’), zenhan.KANA),
town_kana=zenhan.h2z(unicode(data[5], ‘shift_jis’), zenhan.KANA),
prefecture=unicode(data[6], ‘shift_jis’),
city=unicode(data[7], ‘shift_jis’),
town=unicode(data[8], ‘shift_jis’))
zipcode.save()
except IntegrityError: pass
counter += 1
if counter%1000 == 0:
print ‘%d: %.2f’ % (counter, time.clock() – start)

transaction.commit()
print ‘end: %.2f’ % (time.clock() – start)

import_zip(reader)

トランザクションをマニュアルにするには

from django.db import transaction

でdjango.dbのトランザクションをロードしておいて
@transaction.comit_manually
def トランザクションをマニュアル処理する関数の定義

としなければならない。
@transaction.commit_manually の意味が始めはよく分からなくて(後ろに続く関数が引数になっていると分かっていなくて)、SyntaxErrorが出ていたのでかなり悩んだ。

ワントランザクションにすると、延々と終わらなかった約12万件の郵便番号データが 59.51秒(約1分)で読み込み完了した。

データベースはwindowsXP上のsqlite3.6.16

<追記>

ソースコードがインデントされていない・・・orz

Python はインデントで構造を作っているので、これは問題だなー。

ソースコードをWebに載せる方法を考えなくては。

とりあえず、このソースコードはインデントされていないので、注意