読者です 読者をやめる 読者になる 読者になる

Perl - Google に無線 LAN アクセスポイントの場所を聞く

勉強のため、 Google に無線 LAN アクセスポイントの MAC アドレスを 2 つを投げて、住所を得るスクリプトを Perl で書いてみた。 POST するデータをハッシュのリファレンスで送りたかったけど、それだとエラーがでたので(なぜ?)、文字列にしておいた。
元ネタは

#!/usr/bin/env perl
use strict;
use warnings;
use JSON;
use Data::Dumper;
use utf8;
use Encode;
use LWP::UserAgent;
$Data::Dumper::Indent = 1;
$Data::Dumper::Terse = 1;

my $encoder = find_encoding(
    $^O eq 'MSWin32' ? 'cp932' : 'utf8'
);

my @geo = verify_mac_addresses(@ARGV);

my $query = <<QUERY;
{
  "version":"1.1.0",
  "host":"maps.google.com",
  "request_address":true,
  "address_language":"ja_JP",
  "wifi_towers":
  [
    {
      "mac_address":"$geo[0]",
      "signal_strength":8,
      "age":0
    },
    {
      "mac_address":"$geo[1]",
      "signal_strength":8,
      "age":0
    }
  ]
}
QUERY
$query =~ s/\n//g;
$query =~ s/\s+//g;

my $response = LWP::UserAgent->new->post(
    'http://www.google.com/loc/json',
    Content => $query
);
die $response->status_line unless $response->is_success;

my $json = decode_json($response->content);
die "Return no location data.\n" if not exists $json->{location};

my $dump_json = Dumper $json;
$dump_json =~ s/\\x{([0-9a-fA-F]+)}/chr(hex($1))/ge;
print $encoder->encode($dump_json), "\n";

print $encoder->encode("latitude(緯度) and longitude(経度) are:"), "\n";
print "$json->{location}{latitude},$json->{location}{longitude}\n";

sub verify_mac_addresses {
    my @geo = @_;
    die "Specify 2 mac addresses.\n" if @geo != 2;
    my $regex = join("[:-]", ("([0-9a-fA-F]{2})") x 6);
    for (@geo) {
        unless (s/^$regex$/$1-$2-$3-$4-$5-$6/) {
            die "Specify 2 mac addresses.\n";
        }
    }
    return @geo;
}

以上を utf8 の google_loc.pl とでもして保存して MAC アドレス 2 つを引数に実行すると結果が帰ってくる。住所が登録されいないと自分の IP アドレスの登録住所が返ってきているような気がする。実行例は次。 2012.01.25 22:00 頃アクセスしたら登録されていない MAC アドレスを問い合わせると何も返ってこない仕様に変わってた。よって以下は 2012.01.24 での実行例。

$ google_loc.pl 00:11:22:33:44:55 AA:BB:CC:DD:EE:FF
{
  'location' => {
    'longitude' => '139.771861',
    'latitude' => '35.67065',
    'address' => {
      'country' => "日本",
      'city' => "中央区",
      'street_number' => "1",
      'street' => "1丁目",
      'country_code' => 'JP',
      'region' => "東京都"
    },
    'accuracy' => '166000'
  },
  'access_token' => 'xxxxxxxxxxxxxxxxxxxxxxxxxx'
}

latitude(緯度) and longitude(経度) are:
35.67065,139.771861

最終行の緯度、経度 (35.67065,139.771861) を Google Map で検索すればそこの地図が表示できる。
f:id:ks0608:20120125004904j:plain
ちなみに、自分の家にある 2 つのアクセスポイントの MAC アドレスで調べたら、しっかり住所が返ってきた。やめて。
_nomap を SSID に付けたら収集をやめるらしいが、ステルスモードにしてるのもやめるべきだと思う。