« 2005年06月 | メイン | 2005年08月 »

2005年07月26日

|append.gif このエントリーを含むはてなブックマーク | delicious.gif | この記事をクリップ!

GeoIPの続き

前回のネタの続き。

GeolPはインストールできても、ShapelibやMapServerあたりのインストールはめんどくさいと言う、皆様のためにこんなものを用意しました。

世界白地図作成CGI
(自宅サーバなので、見えなかったらすんません)

使い方


  1. 下にある geoip.pyダウンロードして、Apacheのアクセスログの国別集計を作成する。

  2. 世界白地図作成CGIのテキストフォームに国別集計の結果を貼付ける(1カラム目:国ID;2カラム目:集計数;3カラム目:ランク;区切り文字はスペースまたはタブ)

  3. 作成するshape file名を指定する (排他処理していないのでユニークになりそうな名前にしてください

  4. "draw"ボタンをおす

  5. 世界地図が表示されます。コピーするなりなんなりどうぞ

  6. おまけで世界地図を表示するために作ったShape fileもダウンロードできます

※国別集計のフォーマットさえ判ればApacheのログ集計以外にも白地図描画用に使えそうなので、なにか面白いアイデアがあれを頂ければ機能を追加してみたいと思います。

geoip.py


#!/usr/local/bin/python
import GeoIP
import sys
import string
import math
import re

maxRank = 5
ar = sys.argv[1:]
gi = GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE)
ip = {}
p = re.compile('¥d+¥.¥d+¥.¥d+¥.¥d+')

try:
   f = open(ar[0])
   for line in f.readlines(): 
      line = line[:-1]
      text = line.split(" ")
      host = text[0] 
      m = p.match(host)
      if m:
         name =  gi.country_name_by_addr(host)
      else:
         name =  gi.country_code_by_name(host)
      if ip.has_key(name):
         ip[name] = ip[name] + 1
      else:
         ip[name] =   1
   f.close()
except IOError:
   print "Can't find file:", ar[0]

max = len(ip)
ipv = ip.values()
ipv.sort()
lenip = {}
j = 0
for l in ipv:
   lenip[l] =    math.ceil((j * maxRank ) / max) +1
   j = j + 1

 for k in ip.keys():
    print k,'¥t',ip[k],'¥t',lenip[ip[k]]

投稿者 nishioka : 23:42 | コメント (0) | トラックバック

2005年07月23日

|append.gif このエントリーを含むはてなブックマーク | delicious.gif | この記事をクリップ!

GeoIP + Shapelib + MapServerで国別の主題図

GeoIP(Python) + Shapelib(Python) + MapServerでApache logの国別の主題図を作ってみました.

nishioka.sakura.ne.jpにおける先月のApache logから国別の主題図
(自宅サーバなので、見えなかったらすんません)

Apache logから国別の主題図作り方のメモ


  1. http://www.diva-gis.org/data/DataServer.htmから世界地図をゲット

  2. apache logからIPアドレスのリストを作成してGeoIPで国別の集計をする

  3. ShapeLibを使って世界地図の属性に2で作成した集計情報を追加する

  4. MapServerで3.で作った世界地図を表示する

ShapelibとGeoIPはPythonのモジュールを利用しました。
僕の環境(FreeBSD)では、MapServerはPackageからGeoIPはPortsから取得して、そしてShapelibとpyShapelibはソースからコンパイルして利用しました。
コンパイルには特にオプションは設定していませんので割愛します。

2と3を行うPythonのコードをさらしておきます、

ip2dbf.py

#!/usr/local/bin/python import GeoIP import sys import string import math import  dbflib import re ar = sys.argv[1:] gi = GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE) ip = {} p = re.compile('¥d+¥.¥d+¥.¥d+¥.¥d+')

try:
   basedbf = ar[1] 
except IndexError:
   basedbf = "cntry00.dbf"
try:
   savedbf = ar[2] 
except IndexError:
   savedbf = "new.dbf"

try:
   f = open(ar[0])
   for line in f.readlines(): 
      line = line[:-1]
      text = line.split(" ")
      host = text[0] 
      m = p.match(host)
      if m:
         name =  gi.country_name_by_addr(host)
      else:
         name =  gi.country_code_by_name(host)
      if ip.has_key(name):
         ip[name] = ip[name] + 1
      else:
         ip[name] =   1
   f.close()
except IOError:
   print "Can't find file:", x

max = len(ip)
ipv = ip.values()
ipv.sort()
lenip = {}
j = 0
for l in ipv:
   lenip[l] =    math.ceil((j * 5) / max) +1
   j = j + 1
   
newdbf = dbflib.create(savedbf)
#for k in ip.keys():
#   print k,'¥t',ip[k],'¥t',lenip[ip[k]]
try:
   dbf = dbflib.open(basedbf,"rb+")
   fieldcount  = dbf.field_count()
   for i in range(fieldcount):
      field = dbf.field_info(i)
      newdbf.add_field(field[1],field[0],field[2],field[3])
   newdbf.add_field("count",dbflib.FTInteger,6,0)
   newdbf.add_field("rank",dbflib.FTInteger,3,0)
   dbfcount = dbf.record_count()
   for i in range(dbfcount):
      line = dbf.read_record(i)
      na = line['ISO_2DIGIT']
      line['count'] = ip.get(na,0)
      line['rank'] = lenip.get(ip.get(na,0),0)
      newdbf.write_record(i,line)
#      print line , ' ', ip.get(na,0),' ',lenip.get(ip.get(na,0),0)
   f.close()
except IOError:
   print "Can't find file:", x

dbf.close()
newdbf.close()


使い方

python ip2dbf.py access_log input.dbf output.dbf

引数 1 : アクセスログファイル
引数 2 : 世界地図のdbfファイル
引数 3 : 新しいdbfファイル


python ip2dbf.py access_log cntry00.dbf tmp.dbf
cp cntry00.dbf cntry00.db.bk
mv tmp.dbf cntry00.dbf

1.で取得した 世界地図のshape fileの属性データ" cntry00.dbf"とアクセスログをもとに新しい属性データ"tmp.dbf"を作ります
1.で取得した 世界地図のshape fileの属性データ" cntry00.dbf"のバックアップを取ります
新しい属性データ"tmp.dbf"を世界地図のshape fileの属性データとして利用するために" cntry00.dbf"にリネームします


説明


  • このスクリプトは世界地図のDBFに主題図用のフィールドを追加します

  • shapeの構造は*.shp(図形ファイル),*.dbf(属性ファイル),*.sbx(図形索引ファイル)にで構成されています、このスクリプトはdbf(属性ファイル)のみを加工します。そのため、このスクリプトで作成したdbfファイルをShape fileとしてMapServerなどで利用するためには、スクリプトにて作成したdbfファイルを元のファイル名にリネームしてください

  • access_logは一レコード目にIPアドレスがあり、スペースで区切られている必要があります.

  • IPアドレスでもホスト名でもOKです。

  • 主題図用のフィールドとして、元のフィールドから"rank" と"count"をoutput.dbfを作成します

  • "rank"フィールドはアクセス数が多い順に5段階、"count"フィールドは今までアクセスの総計が入ります


  • pythonのスクリプトやらmapfileとかを詰め合わせたセット
    (世界地図も入れてますのでMapServerさえあれば動くと思います、再配布まずいかな?)

    投稿者 nishioka : 22:01 | コメント (0) | トラックバック

    |append.gif このエントリーを含むはてなブックマーク | delicious.gif | この記事をクリップ!

    大門夏祭り

    大門夏祭りに行ってきました。
    去年より出店の数が少なかったように感じました。
     夏祭りといったら、買い食いということですが、仕事帰りで荷物が重かったのともうおっさんなので食べ歩きは串カツだけで、他のお食事は座れる場所を選んび稲本でくずきりを喫茶シロウマで焼そばをいただきお腹一杯です。もちろんビールも呑みましたよ。
     あと、夏を乗り切れるように素盞男神社で輪くぐり神事に始めて挑戦しました。厄除けに頭に色つきのお神酒でペイントもしてもらったので、きっと今年は夏バテ知らずですな。

    それにしても、ネットに公式情報がないなぁ

    投稿者 nishioka : 07:46 | コメント (2) | トラックバック

    2005年07月18日

    |append.gif このエントリーを含むはてなブックマーク | delicious.gif | この記事をクリップ!

    FreeBSDに挑戦中

    ファイルサーバ用に買ったPCがやっと完成。
    本当はOpenBSDにしたかったけど、ハードウェアがサポートされていないようなのでFreeBSDにしてみました。
     FreeBSDは、いままでもUser権限でなら利用したことはあったけど、root権限を持って利用するのは初めてなので、BSD hacks―プロが使うテクニック&ツール100選を買って鋭意調査中です。
    ちなみに今日はMySQLのクラスタの場所の変更で一日近くつぶれました...

    サーバ構築の道のり

    1. ネットで、オーダーメイドのPCを注文
    2. 発注ミスで、予定日に届かない
    3. インストールしようとするも、引き出しに入れていた唯一のモニターである10年物のApple15"が壊れていることが判明、他にはノートPCしかないのでインストールできず放置
    4. とりあえず某所に持っていってインストールだけするも、またもや放置
  • この間一ヶ月
  • 家に持ち帰ってヘッドレスシステムとするべくシリアルケーブルでノートPCから利用することを検討する。ノートPCにRC-232C端子が無いので仕方なしにUSB<->RC-232C変換ケーブルを購入
  • RC-232Cにはいろいろなタイプがあり、先ほど買った変換ケーブルだけではシリアル通信ができないことを知る。今度はRC-232Cのクロスケーブルを購入
  • ようやく自宅に持って帰るが、家のノートPCからだとRC-232Cがぴくりとも反応せず。(某所ではテストUSB<->RC-232Cのシリアル通信はできました)ヘッドレスシステムの構築に失敗、sshのみが命綱になる。
  • ようやくファイルサーバとして動き出した。色気を出してテスト用にWebサーバにすべく動き出す
  • dyndhs.orgでDDNSサービスを申し込む(http://ws.podzone.net/)
  • 家庭用ルータのバーチャルサーバ機能が不安定(設定後10分くらいでポートフォワードをやってくれなくなる)<---いまここらへん
  • サーバを公開(予定)
  • バーチャルサーバ機能が使えないルータはcoregaのWLBAR-54GTという物です。なにか情報があれば教えてください、お願いします。

    先は長いよー

    投稿者 nishioka : 23:20 | コメント (0) | トラックバック

    2005年07月12日

    |append.gif このエントリーを含むはてなブックマーク | delicious.gif | この記事をクリップ!

    invGeocoder のRESTを作ってみました。

    InvGeocoder用のWebServiceにむけての第一段としてREST化してみました。

    WebServiceは入門書を斜め読みしただけ、RESTもWeb上のリソース読んだだけなのであんまりよく分かっていません。見当違いのことをしていたら申し訳ありません。

    WebServiceアドレス

    http://nishioka.sakura.ne.jp/google/ws.php

    引数のリスト










    パラメータ説明
    lat緯度の値10進緯度(ex 35.9955)または度分秒緯度(ex 37度0分36.5秒)
    lon経度の値10進経度(ex 135.9955)または度分秒経度(ex 137度0分36.5秒)
    px任意のX座標任意座標のX値を指定。ただし、sridの設定が必須
    py任意のY座標任意座標のY値を指定。ただし、sridの設定が必須
    srid投影法の識別子任意座標での検索を行う場合の投影法の識別子を指定。任意座標を利用する場合に必須.
    formatsimple or gxml出力の形式simle 住所情報を持つ適当なXMLとG-XMLを選択できます。G-XMLについてはいまのところテスト的な実装です
    version0.1WebServiceのVersionを指定します。Versionがあがった場合でも出力するXMLの内容の互換性を保つためにあります。


    example

    http://nishioka.sakura.ne.jp/google/ws.php?lon=137.243183&lat=35.091722&format=simple

    かえってくるXMLの説明(Simple)


    <?xml version='1.0' encoding='UTF-8' ?>
    <geometry>
    <version>0.1 </version>
    <point>
    <lat>35.09491 </lat>  <------ 住所(返却値)の緯度
    <lon>137.229332 </lon> <------ 住所(返却値)の経度
    <address>愛知県豊田市矢並町香沢253 </address> <------ 住所(返却値)
    <pref>愛知県 </pref>
    <city>豊田市 </city>
    <town>矢並町香沢 </town>
    <number>253 </number>
    <distance>1311.58281657</distance> <------ 検索位置(入力値)と住所(返却値)との距離(m)
    </point >
    </geometry >

    注意書き


    • WebServiceの利用に制限はありません(将来的にID管理くらいはしたい。)

    • サービスの提供期間はレンタルサーバの契約期間、または僕のやる気に依存します。

    • 負荷がかかるほど利用されるとは思いませんが、負荷が多いようなら何らかの対応をします。

    • サービスが止まってたらごめんなさい。

    • 次はSOAPを作りたい(未定)

    投稿者 nishioka : 22:31 | コメント (7) | トラックバック

    2005年07月07日

    |append.gif このエントリーを含むはてなブックマーク | delicious.gif | この記事をクリップ!

    Google Map APIから緯度経度のクリック点の取得

     いつのまにかWeb Map界隈はGoogle Maps API一色のようですが、案の定乗り遅れておりました。
    興味はあるもののなかなか時間が取れなかったのですが、以前のエントリーGeoCoderネタのコメントでbrady さんがGoogle Maps APIのサンプルを頂いたのですが、なんとそのスクリプトは他のエントリGoogle Mapsで地図の任意の位置の緯度経度の取得ができないものかと言う悩みの回答といなるサンプルを作っていただいていたようです。
    どうやらGoogle Maps APIの中には地図の任意のクリック点に対応する緯度経度を取得できる関数があるようです、これさえあれば、逆GoecoderのインターフェースにGoogle Mapsを簡単に利用することができそうですね。
    さっそくAJAXで、緯度経度から住所の取得を行うサンプルを作ってみました。ちゃんと検証したわけではありませんが、正しい緯度経度を返しているようです。

    http://nishioka.sakura.ne.jp/map/test.html

    Thanks you brady!!

    投稿者 nishioka : 23:18 | コメント (0) | トラックバック

    |append.gif このエントリーを含むはてなブックマーク | delicious.gif | この記事をクリップ!

    Google Codeの ajaxsltを試してみました。

     しこしこと作成しているこちらにAjaxとGoogle codeajaxsltを組み込んでみました。

    1.地図をクリックしたときにAJAXで住所を取得する。
    2.検索をGoogle Apiを選択した場合、AJAXで取得したXMLをajaxsltで展開。

    ってな流れです。
    正直XSLT使うほどのXMLでもなかったのでDOMで全部やっても良かったんですけどね。

    他にもWebサービス化に向けて緯度経度から住所を取得する部分をXML呼び出しに変更したりと細かいところを拡張・変更してますけど、こちらももう眠いので説明は省略。

    http://nishioka.sakura.ne.jp/google/map.php

    投稿者 nishioka : 00:31 | コメント (0) | トラックバック

    2005年07月02日

    |append.gif このエントリーを含むはてなブックマーク | delicious.gif | この記事をクリップ!

    運がいい。

    なんか最近非常に運が良いです。

    今日、日本PostgreSQLユーザ会 名古屋支部(NPUG)設立記念セミナーに参加したのですが、そこで、PostgreSQL CE Silverの受講券があたってしまった。
    いままでくじ運が無いことには定評があった私ですが、最近は情報処理の試験に受かった以外にもいろいろ良い事があって、その運のよさにちょっと戸惑い気味です、一生の運を使い果たしていたらどうしよう...

    問題の難易度を調べるべく、早速SRAさんのWebサイトでPostgreSQL CE Silver 7.4の模擬試験を受けたところ

    あなたの得点は 80点でした。10問中 8問正解です。
    という微妙な点数が出ました。

    6.5割で合格なのでなんとか参考書買わなくても受かりそうな気もしますが、PostgreSQLの特有の設問で間違えていますし、まだまだPostgreSQLのことがわかっていないので、これをいい機会と捕らえてPostgreSQLを精進すべく参考書でも買ってきます。折角なので受かりたいなぁ。

    追記
    試しにGoldのサンプル問題もやってみました。サッパリわかりませんでした(まぐれ当たりを含めて4割)。
    PostgreSQLを使いこなすためにはこれくらい必須なのか...先は長そうですが後学のためPosetgreSQL CE Goldを目指してみようかな。

    投稿者 nishioka : 18:53 | コメント (0) | トラックバック