背景
ある時点で、訪問者の地理的位置を示す写真をサイトに掛けることができる古いサービスを偶然見つけました。 多くの異なるものがあります。
awstatsデータで十分なので、このこと自体はあまり役に立ちません。
しかし、訪問者に、彼がランダムな
さらに、予想どおり、彼はトピックに頭を投げましたが、どのように彼らはそれをし、それを理解し、落ち着いたように見えました...
しかし、頭痛は手に休みを与えないので、今度は面白い実験で意味のない実験を紹介します。
![画像](https://habrastorage.org/getpro/habr/post_images/d13/0aa/97e/d130aa97e15485c82a3f2eee40466963.png)
これは、IPシュニックの可能なすべての座標の選択です(丸められた整数から)。
これは
注意してください、著者は言葉の意味でのコーダーではないので、コプロコードにショックを受けた人は去ってください。
データを取得する場所から、これがすべて有名なGeoIPであることがすぐに明らかになりました。これは、GeoLiteCityには座標などの重要な重要な要素があるため、何度も役立ちました。
#geoiplookup -f /usr/local/share/GeoIP/GeoLiteCity.dat 90.155.128.74
GeoIP City Edition, Rev 1: RU, 48, Moscow, N/A, 55.752201, 37.615601, 0, 0
確かに、彼女は私がブトヴォからアレクサンドル庭園に移動したと信じています。 しかし、何も、私たちはそのような精度を必要としません。
GeoLiteCity.datファイルを調べると、バイナリツリーに非常によく似ていることがわかりました。残念ながら、まだ喫煙していないので、すばやく簡単に解析する方法がわかります。
最初に考えられたのは、データベースに一意の座標を入力する際に、考えられるすべてのIPアドレスを列挙するオプションです。
256 ^ 4 = 4294967296マイナスバックアップ、ローカルなど それでも同じように、それは時間の見積もりにつながります。 半年で終了、これは良いです。
パズルへの積極的なアプローチの後、GeoIPにはデータを保存する他のオプションがあるように思われ、CSVビンゴ形式がロシア民主主義の父を救ったことを思い出しました。
サンプルファイル:
5751,"US","NY","Albany","12209",42.6390,-73.7890,532,518
5752,"US","NY","Hillsdale","12529",42.2164,-73.5413,532,518
5753,"US","NY","Albany","12225",42.6706,-73.7791,532,518
合計310070エントリ。
30万点すべての画像を生成することはコーシャーではないため、CSVファイルを解析してデータベース内の一意の丸い位置を入力するスクリプトを作成し、データベースから選択して画像を描画します。
丸みを帯びたので、高精度は必要なかったので、長さと緯度のポイントは十分でした。
3600 x 1800のサイズのようなことをしたい場合、
ツールの選択。
MySQL-すでに立って、すでに手元にあります。 そこに4つの列(x、y、kol、2つで十分ですが、最も集中したエントリがどこにあるかを確認するために追加した最後のテーブル)で1つのテーブルが作成されます
Perl -CSVパーサーを作成し、データベースに入力するために、また、手元にあるコミュニケーターからSSHを介してjoeに書き込む方が便利です。 Perlistsの専門家は、コードをあまり見ないでください。
実際、GDライブラリを備えたPHPは、実際の画像を生成します。 なんで? phpからGDライブラリを操作したすばらしい経験。
したがって、 最後のCSVファイルをダウンロードします 。
データベースとテーブルを作成します。
CREATE DATABASE IF NOT EXISTS `geo`;
CREATE TABLE IF NOT EXISTS `all` (
`x` int(3) NOT NULL,
`y` int(3) NOT NULL,
`kol` int(64) NOT NULL
);
パーサーを作成します。
#!/ usr / local / bin / perl
Mysqlを使用します。
「start \ n」を出力します。
my $ host = "localhost";
my $ database = "geo";
私の$ user = "geo";
私の$ table = "all";
私の$ password = "ololoparolko";
my $ db = Mysql-> Connect($ホスト、$データベース、$ユーザー、$パスワード);
$ sql = "SELECT * FROM` $ table`";
$ sth = $ db->クエリ($ sql);
arr = $ sth-> FetchRow;
私の$ vsego = 0;
私の$ unik = 0;
私の$ ok = 0;
#ファイルを開き、データを配列に入れて処理します。
オープン(GL、「/ home / klef / geo / GeoLiteCity-Location.csv」);
@ geo_arr =;
閉じる(GL);
$ max = $#geo_arr;
for($ i = 0; $ i <= $#geo_arr; $ i ++){
$ vsego ++;
@ geo_a = split( "、"、$ geo_arr [$ i]);
if($#geo_a> 6){
$ ok ++;
$ x = sprintf( "%。0f"、$ geo_a [5]);
$ y = sprintf( "%。0f"、$ geo_a [6]);
#そのような座標があるかどうかを探す
$ sql = "SELECT * FROM` $ table` WHERE x = $ x AND y = $ y";
$ sth = $ db->クエリ($ sql);
arr = $ sth-> FetchRow;
if($#arr> = 0){
#ありますか? カウンターを完全に変更する
$ nov_s = $ arr [3] +1;
$ sql =“ UPDATE` $ database`.` $ table` SET `kol` = '$ nov_s' WHERE` $ table`.`x` = $ x AND` $ table`.`y` = $ y AND` $ table`.`kol` = $ arr [3] LIMIT 1;”
$ db->クエリ($ sql);
} else {
#いいえ、何もありません、修正可能です
$ sql = "INSERT INTO` $ database`.` $ table`(` x`、 `y`、` kol`)VALUES( '$ x'、 '$ y'、 '1'); ";
$ db->クエリ($ sql);
「新規」を印刷します。
$ unik ++;
}
}
}
#これは、最終的に、どれだけ喜んで示すためです
$ vsego_p = sprintf( "%。2f"、$ vsego * 100 / $ max);
$ ok_p = sprintf( "%。2f"、$ ok * 100 / $ max);
$ unik_p = sprintf( "%。2f"、$ unik * 100 / $ max);
$ itog = "\ nObrabotano:$ vsego_p%($ vsego)\ nNormalnih:$ ok_p%($ ok)\ nUnikalnih:$ unik_p%($ unik)\ n";
$ itogを印刷します。
「END \ n」を印刷します。
そして 、処理時間の主な問題は、大量のデータがあったということではなく、愚かで美しい解決策がないために順番に整理されていたことです。
画像を生成するためのphpスクリプト:
#!/ usr / local / bin / php
<?php
$ host = "localhost:3306";
$ user = "geo";
$ data = "geo";
$ pass = "もう一度ビット";
//画像を保存する場所
$ patch = "/ data / web / geo.ip.png";
$ z = 0;
//画像と色を作成します
$ img = imagecreatetruecolor(600、400);
$ ink = imagecolorallocate($ img、0、255、0);
//データベースにアクセスしてデータを選択します
$ db = mysql_connect($ホスト、$ユーザー、$パス)またはdie( "Bolt MySQL„);
$ db_sel = mysql_select_db($ data、$ db)またはdie(“ Bolt BD„);
$ sql = mysql_query( "SELECT * FROM` all`;")またはdie( "Bolt zapros");
$ num_rows = mysql_num_rows($ sql)またはdie( "Bolt Num Stroki");
$ vib = mysql_num_rows($ sql)またはdie( "Bolt Stroki");
for($ i = 1; $ i <= $ num_rows; $ i ++){
$ tmp = mysql_fetch_array($ sql);
$ y = $ tmp ['x'];
$ x = $ tmp ['y'];
//希望の座標でポイントを配置します
imagesetpixel($ img、300 + $ x、200- $ y、$インク);
}
mysql_close($ db);
//最後にマークを付けてファイルを保存します
ImageString($ img、2、10、5、 "Geo IP:" .date( "YM j H:i")。 "Kolvo:"。$ Num_rows。 "、$ Ink);
imagetruecolortopalette($ img、true、255);
imagepng($ img、$パッチ);
imagedestroy($ img);
?>
パーサーの結果:
ファイルごとに合計310072行
一意の座標(丸めあり)8226、わずか2.65%
テーブルのサイズは384キロバイトです:)
処理時間:
データベースを埋めるために:約数時間。
ミリ秒単位の通路での絵の形成について。
psは後で再処理されましたが、小数点以下第1位に丸められ、 ファイルの合計解像度は3600〜1800です。
目的のデスクトップ解像度にサイズ変更すると、良い壁紙が得られます。
ppsは後でサイズ36000 x 18000(それぞれ小数点以下2桁に丸める)のファイルを生成しようとしましたが、この解決策でGDと組み合わせたphpが少し引き裂かれ、理由や理由がわからなくなった理由を理解しました。