python3でのstdin,out,errのencodingの変更

暑くてとろけております。
涼しいはずの北海道で全国最高気温(と最低気温)とは・・・。

python3でのopen

python3からopenの仕様が変更となり、text modeの場合(mode=rやwだけで開いた場合)には、encoding付きでopenするようになっています。

返されるオブジェクトもfileオブジェクトではなくTextIOWrapper, BufferedReaderまたはBufferedWriterとなっています。


[code]
 >>> f = open(‘sample.csv’, ‘r’)
>>> f
<_io.TextIOWrapper name=’sample.csv’ mode=’r’ encoding=’UTF-8′>
>>> f.close()

>>> f = open(‘sample.csv’, ‘w’)
>>> f
<_io.TextIOWrapper name=’sample.csv’ mode=’w’ encoding=’UTF-8′>
>>> f.close()

>>> f = open(‘sample.csv’, ‘a’)
>>> f
<_io.TextIOWrapper name=’sample.csv’ mode=’a’ encoding=’UTF-8′>
>>> f.close()

>>> f = open(‘sample.csv’, ‘r+’)
>>> f
<_io.TextIOWrapper name=’sample.csv’ mode=’r+’ encoding=’UTF-8′>
>>> f.close()

>>> f = open(‘sample.csv’, ‘w+’)
>>> f
<_io.TextIOWrapper name=’sample.csv’ mode=’w+’ encoding=’UTF-8′>
>>> f.close()

>>> f = open(‘sample.csv’, ‘rb’)
>>> f
<_io.BufferedReader name=’sample.csv’>
>>> f.close()

>>> f = open(‘sample.csv’, ‘wb’)
>>> f
<_io.BufferedWriter name=’sample.csv’>
>>> f.close()
[/code]

python3の標準入出力のencodingを切り替える

上述のとおりstdin, stdoutにencodingが付いているわけですが、これのデフォルトのencodingは環境に依存しています。

私の環境ではUTF-8がデフォルトのencodingとして設定しているので、何も指定しない状態ではUTF-8でstdinを読もうとします。

例えば、SJISのファイルをcatしてstdinから読み込むとどうなるかというと、

sample1.py

[python]
 from __future__ import print_function
import sys
print(sys.stdin.read())
[/python]

実行

[code]
 cat sample.csv | python3 sample1.py

Traceback (most recent call last):
File "sample1.py", line 2, in <module>
print(sys.stdin.read())
File "/usr/local/Cellar/python3/3.4.0_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/codecs.py", line 313, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0x82 in position 3: invalid start byte
[/code]

SJISの文字列を渡した場合、Decodeできなかったと怒られます。

ちなみにpython2で同じことをすると文字化けしました。

[code]

1, �ق��ق�
2, �ӂ��ӂ�

[/code]

python2の場合、この問題を解決するために次のようにしていました。

sample2.py::

[python]
 from __future__ import print_function
import sys
import codecs

_stdin = codecs.getreader(‘sjis’)(sys.stdin)
print(_stdin.read())
[/python]

これを実行すると::

[code]
 cat sample.csv | python sample2.py
1, ほげほげ
2, ふがふが
[/code]

となります。
SJISをデコードして読み取ることができています。

これをpython3で実行すると::

[code]
 cat sample.csv | python3 sample2.py
Traceback (most recent call last):
File "sample2.py", line 6, in <module>
print(_stdin.read())
File "/usr/local/Cellar/python3/3.4.0_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/codecs.py", line 313, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0x82 in position 3: invalid start byte
[/code]

残念ながら使えません・・・。

そこで、思い出すのが、冒頭に書いていたfileが_io.TextIOWrapperに変わったということです。
text modeで開いた時はすでにTextIOWrapperオブジェクトになっているので、.bufferにアクセスして、それをcodecs.getreaderします。

sample3.py::

[python]
 import sys
import codecs

_stdin = codecs.getreader(‘sjis’)(sys.stdin.buffer)
print(_stdin.read())
[/python]

これで文字化けせずに読むことができるようになります。
しかし、調べて見ると他のやり方がもあるようです。

sample4.py::

[python]
 import sys
import io

_stdin = io.TextIOWrapper(sys.stdin.buffer, encoding=’sjis’)
print(_stdin.read())

[/python]

sample5.py::

[python]
 import sys
_stdin = open(sys.stdin.fileno(), ‘r’, encoding=’sjis’)
print(_stdin.read())
[/python]

どれも正常に動作しています。

となると、今度は結局どれを使えばいいの?となります。
私はgetreaderやらTextIOWrapperという単語を見るよりも、openでstdinをsjisで開き直す、という方がさっぱりしていて良いなと思ってます。

・・・ということで寝られるかと思ったら、何やら怪しい挙動が・・・

sample6.py::

[python]
 import sys
import codecs

_stdin = codecs.getreader(‘sjis’)(sys.stdin.buffer)
_stdout = codecs.getwriter(‘utf-8’)(sys.stdout.buffer)

for line in _stdin:
print(‘!!!’, file=sys.__stdout__)
print(‘???’, file=sys.__stderr__)
_stdout.write(line)
[/python]

実行すると::

[code]
 !!!
???
1, ほげほげ
!!!
???
2, ふがふが
[/code]

sample7.py::

[python]
 import sys
import io

_stdin = io.TextIOWrapper(sys.stdin.buffer, encoding=’sjis’)
_stdout = io.TextIOWrapper(sys.stdout.buffer, encoding=’utf-8′)

for line in _stdin:
print(‘!!!’, file=sys.__stdout__)
print(‘???’, file=sys.__stderr__)
_stdout.write(line)
[/python]

実行すると::

[code]
 !!!
???
!!!
???
1, ほげほげ
2, ふがふが
[/code]

あれ???

sample8.py::

[python]
 import sys
_stdin = open(sys.stdin.fileno(), ‘r’, encoding=’sjis’)
_stdout = open(sys.stdout.fileno(), ‘w’, encoding=’utf-8′)

for line in _stdin:
print(‘!!!’, file=sys.__stdout__)
print(‘???’, file=sys.__stderr__)
_stdout.write(line)
[/python]

実行すると::

[code]
 !!!
???
1, ほげほげ
!!!
???
2, ふがふが
[/code]

なぜかTextIOWrapperのとき、出力順序が違っています。
なんとなくですが、TextIOWrapperを作りなおしている時に、元のバッファとは違うところを使っている、とかでしょうか?

sample7a.py::

[python]
 import sys
import io

_stdin = io.TextIOWrapper(sys.stdin.buffer, encoding=’sjis’)
_stdout = io.TextIOWrapper(sys.stdout.buffer, encoding=’utf-8′)

for line in _stdin:
print(‘!!!’, file=sys.__stdout__)
print(‘???’, file=sys.__stderr__)
_stdout.write(line)
_stdout.flush()
[/python]

実行すると::

!!!
???
1, ほげほげ
!!!
???
2, ふがふが

それっぽい結果がでました。これ以上の深追いはやめておきましょう・・・。

まとめ

どうしてもpython側でstd(in|out|err)の文字コードを吸収(変換)したいなら、今回書いた方法のどれかで変換すればよさそうです。

ただ、pythonでの文字コード変換が必須ではなく、コマンドラインで処理するスクリプトの場合には、iconvやnkfを使った方がpythonのコードもシンプルになります。

sample_simple.py::

[python]
import sys
print(sys.stdin.read())
[/python]

これをこう::

[code] cat sample.csv | iconv -f SJIS -t UTF-8 | python3 sample_simple.py
[/code]

というわけで、頑張った割に、最終的にはpythonで文字コード変換しない方が良い気がしてきました。
お疲れ様でした。。。

追記

 ずっと見てなかったcomp.lang.pythonのメールに何故か目を通してみたら、ちょうど関連する話がありました。

Reading from sys.stdin reads the whole file in – Google Groups

  • バッファリングしているのでflushする必要がある。
  • python -u sample.py のように-uをしていするとバッファリングされない
  • 環境変数 PYTHONUNBUFFERED を設定するとバッファリングされない
  • python3.3から print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False) のflushをTrueにすればすぐflushするみたい
  • python2でバッファリングなしでstdinの行ごとの処理をすると遅いし変なことしないとだめなのでオススメしない。python3を使おう。

参考

アプリケーション開始前の初期化段階では呼び出すことができません。

.Net MVC で認証をちょっと変更しようとMembershipProviderを作ってたらエラー。

アプリケーション開始前の初期化段階では呼び出すことができません。

ふむふむ・・・・・・・・・・・

結局わからず、日本語を適当に英語にして検索してstackoverflow様。

ASP.NET: This method cannot be called during the application's pre-start initialization stage – Stack Overflow

[code language=”xml”]
<add key="enableSimpleMembership" value="false"/>
<add key="autoFormsAuthentication" value="false"/>
[/code]

PDFから取得した時刻表テキストから、使いやすいデータを抽出する

気温の変化の激しさに負け、風邪をひいて喉が痛いです。
週末を風邪でぐったり過ごすと損した気分です!

さて、地道に作成しているPebbleの札幌東豊線の時刻表アプリ、を動かすために必要なデータを作るためにチマチマ進めている PDFからテキストを取得する PyPDF2 の続きです。

ソース

planset/tohosendata です。

やはりこういった電車の時刻表はオープンデータ化してほしいですね。
どこかにあるのかなー?

テキストから時刻表を抽出する

前回、PDFからテキストを取得することができました。

[code]
WeekdaysSaturdays/Sundays/Holidays6 01020293846546 01020293847557 2 91419232731353943475155597 311192632384450568 3 711151923273135394347528 2 8142026334047549 0 7152230374451599 2 91724313845525910 61320273542495610 71421283542495611 31118253239465411 31118253239465412 1 81522303744515812 1 81522303744515813 61320273441495613 61320273441495614 31017253239465314 31017253239465315 1 81522303744525915 1 81522293644515816 6132128354146525716 51220273441485617 3 813182329344045515617 31017243139465318 1 6121723283439455218 0 71522293643515919 0 816243240485619 715243240485620 412202937455320 412202937455321 1 917253341495721 1 917253341495722 5132230405022 5132230405023 0102030405023 010203040500 00 0Last Trains for Transfers from This Station.For MiyanosawaFor FukuzumiFor Shin sapporoTransfer at OdoriTransfer at SapporoTransfer at OdoriTransfer at Odori
[/code]

ここからうまい具合に抽出しますが、詳細は省略。

正規表現でざっくり分けて、あとは1時刻ずつ読む感じです(うまく行ってる気がしません)。

苦労した点は、pdfをテキストに変換をすると、
同じ行が2回続いて出力されるPDFがあることです・・・。
PDFの作りの問題なのか、pypdf2の使い方の問題なのか・・・。

栄町分を出力してみるとこんな感じです。時刻表が正しいかはまだ確認していません。

[code]
“1”: {
“fukuzumi”: {
“holiday”: {
“23”: [
0,
10,
20,
30,
40,
50
],
“22”: [
5,
13,
22,
30,
40,
50
],
(省略)
},
“weekday”: {
“23”: [
0,
10,
20,
30,
40,
50
],
“22”: [
5,
13,
22,
30,
40,
50
],
(省略)
}
(省略)
[/code]

ここまでくればもうおっけーです。

あとは、django用のdbに取り込んで時刻検索して返してあげています。

まとめ

これで時刻表のデータが揃ったので、あとは電車に乗りながら動作確認です。
栄町<>さっぽろ間しか乗ることがないので、福住のデータは一生テストされませんけどね!

Wordのページの最初の行

すごくどうでもよいことなのですが、Wordで何かの文章を書いているとき、ページの一番最初の行を空行にしています。
(基本は印刷レイアウトで編集しています)

WS000605

こうしておくと、何か挿入したくなったときに、カーソルを先頭行に移してENTERをを押せば簡単にスペースを作れます。

WS000606

しかし、このままだと印刷したときは、上の空白が多めになってしまいます。
そこで、できれば以下の様に先頭行にヘッダを置いておきたいです。

WS000607

しかし、この状態で先頭行以前に改行を入れようとすると、

WS000608

こうなってしまいます。

めんどくさいです(・w・;

何かいい方法はないのだろうか。

VS2012 から VS2013へ移行した時のTypeScript

VisualStudio2013 Update2では最初からTypeScriptが使えるようになってました。がんばれTypeScript。

TypeScriptがビルドされない

しかし、VS2012の時につくったプロジェクトをVS2013で開いただけでは、プロジェクトのプロパティを開いてもTypeScriptの項目がでてきません。
保存時にビルドもしてくれないし、ビルド時もビルドしてくれません。ようするにTypeScriptが使えません。

対処方法

GUIから設定できそうな気もしますが、以下をプロジェクトファイルに追加したらTypeScriptの設定ができました。

[code]
<Import Project="$(VSToolsPath)\TypeScript\Microsoft.TypeScript.targets" Condition="Exists(‘$(VSToolsPath)\TypeScript\Microsoft.TypeScript.targets’)" />
[/code]

ビルド時にtsc.exeのエラーが出る

移動 -> ”tsc.exe”はコード 1 を伴って終了しました。 | planset blog

Visual Studio 2012からの発行ができない

ASP.NET、MVC、AngularJSで色々と書いていて、それじゃ発行してみるかー、と発行してみたら、

The “ImportParametersFile” task failed unexpectedly. の日本語版

のエラーがでて発行できません。

現象は Azure SDK 2.3 – can't deploy と同じだと思うのですが、Azure SDKをアンインストールしたり、VS2012を修復したり、Microsoft.Web.XmlTransforms.dllを持ってきたりしても発行できませんでした。

結局、Visual Studio 2013だと大丈夫という書き込みがあったのと、2012を使わないといけない制約もなかったので、2013に乗り換えちゃいました。

そのうちアップデートか対処法がわかったら、VS2012の方でも発行できるようにしよう・・・

PDFからテキストを取得する PyPDF2

昨日の札幌は風が強かったです。うちのゴミ箱のフタが飛んでいきました。

さて、地道に作成しているPebbleの札幌東豊線の時刻表アプリなのですが、それになりに動くようになって、平日の栄町駅だけは使えるようになりました。

位置によって最寄りの駅に切り替わることも確認できたので、あとは時刻表データを作るだけです。

いつもスマホで時刻表を見るときは [札幌市営]東豊線の時刻表 – えきから時刻表 を使っているのですが、データだけ抜くのは忍びないので、市が出している何かを参考にすることにしました。

地下鉄路線図・時刻表/札幌市

しかし見渡した限り全部PDFです。おーのー!

ただ、このPDFはテキスト情報が含まれているPDFなので、
この文字を使えば、簡単に時刻表(の文字列)をゲットできて楽ができるかもしれない!!!

本題:pythonでPDFからテキスト情報を取得しよう

pythonからPDFを扱うにはPyPDF2を使います。

mstamy2/PyPDF2

インストール

[code]
pip install pypdf2
[/code]

PDFからテキストを取得する

[python]
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os

import PyPDF2

def get_pdf_text(path):
"""PDFファイルからテキスト情報を抜き出す"""
text = ""
pdf = PyPDF2.PdfFileReader(open(path, "rb"))
for i in range(0, pdf.getNumPages()):
text += pdf.getPage(i).extractText() + "\n"
text = " ".join(text.replace(u"\xa0", " ").strip().split())
return text

if __name__ == ‘__main__’:
print(get_pdf_text(‘hogehoge.pdf’))

[/python]

実行してみる

これを東豊線の栄町駅PDFに対して実行してみます。

[code]
WeekdaysSaturdays/Sundays/Holidays6 01020293846546 01020293847557 2 91419232731353943475155597 311192632384450568 3 711151923273135394347528 2 8142026334047549 0 7152230374451599 2 91724313845525910 61320273542495610 71421283542495611 31118253239465411 31118253239465412 1 81522303744515812 1 81522303744515813 61320273441495613 61320273441495614 31017253239465314 31017253239465315 1 81522303744525915 1 81522293644515816 6132128354146525716 51220273441485617 3 813182329344045515617 31017243139465318 1 6121723283439455218 0 71522293643515919 0 816243240485619 715243240485620 412202937455320 412202937455321 1 917253341495721 1 917253341495722 5132230405022 5132230405023 0102030405023 010203040500 00 0Last Trains for Transfers from This Station.For MiyanosawaFor FukuzumiFor Shin sapporoTransfer at OdoriTransfer at SapporoTransfer at OdoriTransfer at Odori
[/code]

おおおお! テキストになった!!!

けど、これの解析はどうやろう。めんどくさい\(^o^)/
(ちなみにPDFリーダーで開いて、CTRL-Aでテキストを全選択してテキストをコピペしたほうが、もうちょっと読みやすいテキストで取得できます)

つづく。

第2回Sapporo.vimに参加してみた vim-ipython

こんにちは!

気分爽快! と、調子に乗って7分丈のシャツにしたらすごい寒かったです。

さて、2014/5/25に第2回 Sapporo.vim に参加させてもらいました。
特に何かしたいことはなかったんですが、Vimの勉強会があるなんて都会っぽいなーと思いつつ参加しました。

とはいえ、せっかく参加したのでvimで何かできるようにしたいと思い考えたところ、前回のpython sapporoで中村さんがemacsを使って行っていた「バッファ(?)からipython側に関数をロードして実行する」ということをvimでできるようにすることにしました。

終始もくもくしながらipythonのドキュメントを見てました(vimは・・・)。
結果、ivanov/vim-ipython を使うだけで十分ということがわかりました!プラグインバンザイヽ(^o^)丿

では、ipython自体を使いこなせていないのでイマイチな説明ですが、vim-ipythonについて書いてみます。

 

準備

まずは、プラグインをインストールします。NeoBundleの使い方はぐぐってください・x・

[code]
NeoBundle ‘ivanov/vim-ipython’
[/code]

次にterminalを開いてipythonを起動します。このとき、ipython consoleで起動します。

[code]
ipython console
[/code]

そうすると、~/.ipython/profile_default/security 配下にkernel-****.jsonというファイルができるので、****のところを覚えます。
これはipython kernelでもOKです。ipython kernelを実行すると画面上にpidファイル名が表示されるのでより楽ですが、その場合、対話型インタフェースを使いたいときは、別途[code]ipython console –existing[/code] で接続します。

次にterminalからhoge.pyを開きます(ファイルはなくてもいいよ)。

[code]vim hoge.py[/code]

そこでIPythonコマンドを実行します。

[code]:IPython ****(さっき覚えてた数字)[/code]

これで準備完了!

 

バッファの内容をipythonに投げてみる

vim-ipythonのデフォルトのキーマップは次のようになっています。

map <buffer> <silent> <F5> <Plug>(IPython-RunFile)
map <buffer> <silent> <S-F5> <Plug>(IPython-RunLine)
map <buffer> <silent> <F9> <Plug>(IPython-RunLines)
map <buffer> <silent> <LocalLeader>d <Plug>(IPython-OpenPyDoc)
map <buffer> <silent> <LocalLeader>s <Plug>(IPython-UpdateShell)
map <buffer> <silent> <S-F9> <Plug>(IPython-ToggleReselect)

なんとなくRunFile、RunLine、RunLinesあたりがいい感じになりそうです。

vim hoge.py でvimを開いたら、
[code]
def func1():
return ‘func1’
[/code]
という関数を書いてみます。

書いたら行選択で2行選択して、<F9>を押します。

(私の環境ではF9がうまく行かなかっったりしたので、別のキーに割り当てました。)

こうすることで関数部分だけをipython側で実行させることができます。
うまくいくと実行結果が表示されます。ipython consoleで起動したipythonの方で、func1() を実行してみると実行できることがわかります。

これがやりたかったやつです。できてよかった。

しかし、vimで :IPython を実行するとき、~/.ipython/profile_default/security/のファイルを見てpidを覚えて入力するというのは面倒です。

もうちょっと楽にipythonに接続する

pidを指定しないで接続できれば記憶力の乏しい私でも使いやすいので、その方法を探してみたところ、IPythonのfind_connection_file関数に * を渡してやると一番新しく起動したipythonの設定ファイルのパスを返してくれるということがわかりました。

というわけで、vim-ipythonのソースをちょっと変更します。
[code]
diff –git a/ftplugin/python/ipy.vim b/ftplugin/python/ipy.vim
index 5c88db7..2f081a1 100644
— a/ftplugin/python/ipy.vim
+++ b/ftplugin/python/ipy.vim
@@ -116,6 +116,8 @@ def km_from_string(s=”):
such as ‘–shell=47378 –iopub=39859 –stdin=36778 –hb=52668’ for IPython 0.11
or just ‘kernel-12345.json’ for IPython 0.12
"""
+    if s.strip() == ”:
+        s = ‘*’
from os.path import join as pjoin
try:
import IPython
[/code]

これで、:IPython したときに何も引数がなければ、一番新しく起動したipythonに接続できるようになりました。かなり楽になりました。

しかし、実はこのプラグイン ftplugin となっていてpythonでしか動作しません。気軽に vim を生起動して、pythonコードを適当に書いて、ファイルに保存しないで実行! なんてことができないのです。

ファイル名を指定しないでvimを起動した時にも使えるようにする

:set filetype=pythonとすればいいのですが、ここはばっさりとプラグインのftpluginディレクトリをpluginに変えてみたり、.vimrcに set filetype=python とガツンと書いてもいいです。

これで気軽にvimを起動して、ipythonに渡せるようになりまし・・・

いや、まだipythonが別のterminalで動いている、というの気に食わないです。

 

ipythonもvimの中で

といっても、VimShellで動かすだけです。

nmap <silent><space>is <Esc>:sp<CR><Esc><C-w><C-w><Esc>:VimShell<CR><Esc><C-w><C-w>:VimShellSendString ipython console<CR>

長ったらしいキーマップを作ってみます。もうやる気が減ってきたのでかなり適当です。

というわけで、こうなりました。

中村さんがやってたのはこんな感じ・・・だったっけ・・・。emacsを使えないのでわからない/(^o^)\
vim-ipython

正直なところ、VimShellでipythonするより、tmuxでsplitしてipythonを動かした方が使いやすい気がします。

しかし、すごくいい感じでもないですが、自分のケースとしては必要十分です。
hoge.py, a.py, b.py といった「とりあえず実行させたかっただけの謎ファイル」が量産されなくなりそうだし、
誰かにコードを書いて見せるときもかなりやりやすくなりそう!

第1回OpenStreetMapハッカソン

Code for Sapporo主催の第1回OpenStreetMapハッカソンに参加してきました。

 

第1回OpenStreetMapハッカソン – Code for Sapporo | Doorkeeper

 

最近、ここ2〜3年で緯度経度や地図を使うプログラムを作ること、または作りたいと思うことが多いです。

GISというようなすごいものではなく、もっともっともっともっと軽いものなのですが、GoogleMapを利用しようとするとライセンス的に難しくて使えず、でもお客さんからするとGoogleMapみたいのがいいってところですね(黒〜グレーゾーンでやってる人は多いのだろうけど・・・)。

そのため、以前からOpenStreetMapは気にはなっていました。
ただ、ポスグレはあまり知らないしGISのベース知識もないので、いろいろと後回しになっていました。

今回は良い機会ということでハッカソンに参加させてもらいました。

 

一番の発見

まず、OpenStreetMapは「サーバーにインストールして地図サーバーのベースにするためのオープンソース・ソフトウェア」だと思っていました。
もちろんそういった面もあるのでしょうが、そもそもGoogleMap的なサービスもあるのだと知りました。
基本中の基本なんでしょうけど、一番の収穫です(*´ω`*) 

 

ハッカソン

今回のハッカソンでは、午前中に古川さんがOpenStreetMapについての概要や活用事例についてお話され、午後からはアイディアソンチームとハッカソンチームに別れ作業をしました。

私はハッカソングループに参加しました。
そもそもOpenStreetMapを触ったこともないので、まずはユーザー登録からです。
サービス自体はわかりやすくてユーザー登録してからチュートリアルにしたがって編集の仕方を覚えれば、結構簡単にエリアを追加していけます。
(いきなり間違った名称を設定してしまい、焦って削除しましたが、画面から消えなくて焦りましたw )

ハッカソンチームの内容ですが、そもそもみんなOpenStreetMapについて詳しいわけでもなかったので、グループの1人が個人で作成されたという MamaPapaMaps の札幌のデータを使って、同じようなものをOpenStreetMap側で作ってみることになりました。

ただ、いきなりOpenStreetMapに入れてしまうと確認や編集が大変だということで、MapBoxというサービスを利用してプロトタイプを作ることにしました。
MapBoxでは、背景の地図としてOpenStreetMapを利用して、MapBoxで持っているポイントデータをレイヤーをのせるような形で表示できます。(仕組みは調べていませんが、GoogleMapsAPIを利用して地図上にJavaScriptでポイントをデータを追加するような感じですかね?)

MapBoxではgeoJSON, csvなどからデータを取り込むことができます。CSVで取り込めるのは私のような地図素人には助かります。
また取り込んだデータは、mapBoxの画面上ではtitleとdescriptionしか表示されませんが、OpenStreetMapで使うタグ情報(例えば、amenity=kindergarden)も取り込むことができます。これらは画面上は見えないけど、MapBox内部では保持しているようで、geoJSONやKMLとして出力した時にはそれらの情報も一緒に出力されます。

今回は、札幌の保育所データをCSVに変換してもらい、OpenStreetMapで使用したいタグ情報をCSVに入れ込み、データを取り込みました。

できたのはこんな感じです。

札幌保育所マップ

 

データを取り込んで、MapBoxで表示するだけであれば割と簡単ですが、これを更にOpenStreetMapに取り込んで、札幌の幼稚園を検索! ということをするにはいくつか課題があります。

  • 元データが、例えば札幌市のHPに乗っていた場合、それをOpenStreetMapに載せても大丈夫かという確認が必要となる。
    今回のデータは国土数値情報(?)のデータ(?)みたいなので大丈夫っていってたような気がします。
    http://nlftp.mlit.go.jp/ksj/ これかな?? 
  • 住所から緯度経度を調査するとき、GoogleMapなんかは使っちゃだめ。
    オープンなものとして、CSV Geocoding Service というサービスを使って住所から緯度経度を取得する必要がある。 
  • 住所からの緯度経度を取得したとしても、正確な位置がずれる。というか、町までしかない住所だと特に大幅にずれる。
    その場合、地図を目で見て位置を合わせる必要があるが、そのときに位置をGoogleMapで確認して特定してはだめ。
  • OpenStreetMapに保育所を取り込んだとすると、検索するためのタグが必要になるが、現在利用できるタグとしては、amenity=kindergardenしかない。幼稚園、保育園、認可、非認可、営業時間などがない。
    (まだDraftだが、amenity=childecare2.0というタグがあり、これが使えるようになるとこの問題はクリアできる)
  • あとはそもそもOpenStreetMapへの一括取り込み方法を知らない(JOSMというツールを使うとよいと聞いた)

 

 

結局のところ、OpenStreetMapに新たに場所を特定して落としこむには、国が公開しているオープンデータを利用するか、草の根的にぽちぽちする以外は権利上むずかしいって印象でした。そりゃそうだよね。
地図を綺麗にするのはどうなんでしょ。災害があった地域をみんなで地図を書き足して綺麗にした、とかいってたけどそれは何をみてやったのだろう。

 

ひとまず、ちょっとわかったので、次は自前でOpenStreetMap鯖をつくろう。ポスグレポスグレー。

 

Azure Storage Emulator + UseDevelopmentStorage=trueで400 httpエラーになる。

storage client libraryのバージョンが新しいと、Storage Emultatorの開発ストレージ(CloudStorageAccount.DevelopmentStorageAccountとか、ConnectionStringがUseDevelopmentStorage=trueで使えるやつ)との通信がエラーになる。

Windows azure storage DevelopmentStorageAccount CloudTable.CreateIfNotExists() always get 400 http error

対処法としては、バージョンダウンさせるか、Windows Azure Storage Emulator 2.2.1 Preview versionを使う。
今回はPreviewVersionを使って動作確認しました。手動コピーしないとだめなのでちょっと面倒ですけどね。

Download Windows Azure Storage Emulator 2.2.1 Preview from Official Microsoft Download Center