<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Комментарии: Как определить по IP-адресу город посетителя (GEO IP)</title>
	<atom:link href="http://nickspring.ru/archives/31/feed" rel="self" type="application/rss+xml" />
	<link>http://nickspring.ru/archives/31</link>
	<description>заметки о SEO, интернет-маркетинге и веб-программировании</description>
	<lastBuildDate>Mon, 01 Aug 2011 04:40:40 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.4</generator>
	<item>
		<title>Автор: Dain</title>
		<link>http://nickspring.ru/archives/31/comment-page-1#comment-42289</link>
		<dc:creator>Dain</dc:creator>
		<pubDate>Tue, 05 Jul 2011 21:07:03 +0000</pubDate>
		<guid isPermaLink="false">http://nickspring.ru/archives/31#comment-42289</guid>
		<description>проверка табуляции: \tраз-два, \tраз-два...</description>
		<content:encoded><![CDATA[<p>проверка табуляции: \tраз-два, \tраз-два&#8230;</p>
]]></content:encoded>
	</item>
	<item>
		<title>Автор: Dain</title>
		<link>http://nickspring.ru/archives/31/comment-page-1#comment-42288</link>
		<dc:creator>Dain</dc:creator>
		<pubDate>Tue, 05 Jul 2011 21:06:03 +0000</pubDate>
		<guid isPermaLink="false">http://nickspring.ru/archives/31#comment-42288</guid>
		<description>\t (проверка табуляции)</description>
		<content:encoded><![CDATA[<p>\t (проверка табуляции)</p>
]]></content:encoded>
	</item>
	<item>
		<title>Автор: Dain</title>
		<link>http://nickspring.ru/archives/31/comment-page-1#comment-42287</link>
		<dc:creator>Dain</dc:creator>
		<pubDate>Tue, 05 Jul 2011 21:05:13 +0000</pubDate>
		<guid isPermaLink="false">http://nickspring.ru/archives/31#comment-42287</guid>
		<description>Т.к. на данный момент на IpGeoBase нет непосредственно sql-дампа, обновляемого регулярно, а есть .txt-файлы, то вот моё решение:

1). берем отсюда http://ipgeobase.ru/cgi-bin/Archive.cgi актуальный архив (я брал geo_files.tar.gz, датированный 05-07-2011, что не может не радовать), распаковываем, имеем 2 файла:

- cidr_optim.txt. В нем строки, состоящие из: 
    - ip-адрес &quot;от&quot; (в int&#039;е), 
    - ip-адрес &quot;до&quot; (в int&#039;е), 
    - интервал ip-адресов (в IPv4-формате), 
    - зона, 
    - id города; 
все разделено табуляцией;

- cities.txt. В нем строки, состоящие из: 
    - id города, 
    - название города, 
    - название региона, 
    - название округа, 
    - широта, 
    - долгота; 
и тут все разделено табуляцией;

2). создаем в mysql&#039;е две таблицы:

CREATE TABLE `geo_ips` (
  `ip_from` int(10) unsigned NOT NULL,
  `ip_to` int(10) unsigned NOT NULL,
  `zone` varchar(2) NOT NULL,
  `city_id` smallint(6) DEFAULT NULL,
  KEY `city_id` (`city_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- мне нафиг был не нужен столбец &quot;интервал ip-адресов в IPv4&quot;, так что без него обошлось
-- P.S.: обратите внимание на KEY `city_id` (`city_id`) - ибо в результате записей в таблице будет около 130 000, а это малость многовато. Этот индекс нужен чтоб у вас потом ничё не тупило при джойне обеих таблиц по id-города

CREATE TABLE `geo_cities` (
  `id` smallint(6) NOT NULL,
  `city_title` varchar(255) NOT NULL,
  `region_title` varchar(255) NOT NULL,
  `district_title` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- а тут мне нафиг были не нужны столбцы &quot;широта&quot; и &quot;долгота&quot;, так что обошлось и без них. Ну и cool

3). пишем скрипт-парсер. Вот что я наШкодил:

&lt;?php
// тут недурственно бы подключиться к базе; если не знаете, как, то дальше лучше не читать...

// очистим имеющиеся таблицы; полезно, если будете этот скрипт юзать регулярно, скармливая ему новые файлы (данные-то у IpGeoBase обновляются, так-то!)
mysql_query(&#039;TRUNCATE TABLE `geo_cities`&#039;);
mysql_query(&#039;TRUNCATE TABLE `geo_ips`&#039;);

// теперь заполним одну таблицу (какую - не принципиально)
$strings = file(&#039;cidr_optim.txt&#039;); // долго не парясь, всасываем файл построчно в массив
$strings_count = sizeof($strings);
$rows_inserted = 0;
for ($i = 0; $i &lt; $strings_count; $i++) {
        // ну и побежали...
	$cols = explode(&quot;\t&quot;, $strings[$i]);
        // а вот тут пришлось сделать тупо построчные инсерты, отдельно для каждой записи, ибо одним запросом 130 000 элементов моё двигло впихивать категорически отказалось :(
	$sql = &#039;INSERT INTO `geo_ips` (`ip_from`, `ip_to`, `zone`, `city_id`) VALUES (&#039;.(int) $cols[0].&#039;, &#039;.(int) $cols[1].&#039;, &quot;&#039;.$cols[3].&#039;&quot;, &#039;.( is_numeric(trim($cols[4])) ? (int) $cols[4] : &#039;null&#039; ).&#039;)&#039;; // у многих записей в ip-таблице нет городов, вместо них стоят прочерки, которые нам какбэ нах не упали, т.к. нам потом JOIN&#039;ы юзать; пустое значение тоже не подойдет; остается null
	if ( !mysql_query($sql) ) {
		echo &#039;ERROR (inserting row #&#039;.$i.&#039;): &#039;.mysql_errno().&#039; - &#039;.mysql_error().&#039;&#039;;
	} else {
		$rows_inserted++;
	}
}
echo &#039;rows inserted (geo_ips): &#039;.$rows_inserted.&#039;&#039;; // ну это так, для наглядности :)

// теперь заполним, соответственно, другую таблицу
$strings = file(&#039;cities.txt&#039;);
$strings_count = sizeof($strings);
$rows_inserted = 0;
for ($i = 0; $i &lt; $strings_count; $i++) {
	$cols = mysql_real_escape_string($strings[$i]);
	$cols = explode(&quot;\t&quot;, $cols);
	$sql = &#039;INSERT INTO `geo_cities` (`id`, `city_title`, `region_title`, `district_title`) VALUES (&#039;.(int) $cols[0].&#039;, &quot;&#039;.$cols[1].&#039;&quot;, &quot;&#039;.$cols[2].&#039;&quot;, &quot;&#039;.$cols[3].&#039;&quot;)&#039;;
	if ( !mysql_query($sql) ) {
		echo &#039;ERROR (inserting row #&#039;.$i.&#039;): &#039;.mysql_errno().&#039; - &#039;.mysql_error().&#039;&#039;;
	} else {
		$rows_inserted++;
	}
}
echo &#039;rows inserted (geo_cities): &#039;.$rows_inserted.&#039;&#039;;

// узё
// у меня скрипт срабатывает примерно за 20 секунд; многовато, но что делать...
?&gt;

4). изначально у меня задача получать название города посетителя, так что в итоге у меня получился вот такой вот запрос:

&lt;?php
$user_ip = sprintf(&quot;%u\n&quot;, ip2long($_SERVER[&#039;REMOTE_ADDR&#039;]));

$sql = &#039;
	SELECT 
		`gc`.`city_title`, 
		`gc`.`region_title` 
	FROM `geo_cities` AS `gc`
	INNER JOIN `geo_ips` AS `gi`
		ON `gi`.`city_id` = `gc`.`id`
	WHERE `gi`.`ip_from` = &#039;.$user_ip;

// ...
// ну дальше уж сами ;)
?&gt;</description>
		<content:encoded><![CDATA[<p>Т.к. на данный момент на IpGeoBase нет непосредственно sql-дампа, обновляемого регулярно, а есть .txt-файлы, то вот моё решение:</p>
<p>1). берем отсюда <a href="http://ipgeobase.ru/cgi-bin/Archive.cgi" rel="nofollow">ipgeobase.ru/cgi-bin/Archive.cgi</a> актуальный архив (я брал geo_files.tar.gz, датированный 05-07-2011, что не может не радовать), распаковываем, имеем 2 файла:</p>
<p>- cidr_optim.txt. В нем строки, состоящие из:<br />
    &#8211; ip-адрес &laquo;от&raquo; (в int&#8217;е),<br />
    &#8211; ip-адрес &laquo;до&raquo; (в int&#8217;е),<br />
    &#8211; интервал ip-адресов (в IPv4-формате),<br />
    &#8211; зона,<br />
    &#8211; id города;<br />
все разделено табуляцией;</p>
<p>- cities.txt. В нем строки, состоящие из:<br />
    &#8211; id города,<br />
    &#8211; название города,<br />
    &#8211; название региона,<br />
    &#8211; название округа,<br />
    &#8211; широта,<br />
    &#8211; долгота;<br />
и тут все разделено табуляцией;</p>
<p>2). создаем в mysql&#8217;е две таблицы:</p>
<p>CREATE TABLE `geo_ips` (<br />
  `ip_from` int(10) unsigned NOT NULL,<br />
  `ip_to` int(10) unsigned NOT NULL,<br />
  `zone` varchar(2) NOT NULL,<br />
  `city_id` smallint(6) DEFAULT NULL,<br />
  KEY `city_id` (`city_id`)<br />
) ENGINE=MyISAM DEFAULT CHARSET=utf8;</p>
<p>&#8211; мне нафиг был не нужен столбец &laquo;интервал ip-адресов в IPv4&#8243;, так что без него обошлось<br />
&#8211; P.S.: обратите внимание на KEY `city_id` (`city_id`) &#8211; ибо в результате записей в таблице будет около 130 000, а это малость многовато. Этот индекс нужен чтоб у вас потом ничё не тупило при джойне обеих таблиц по id-города</p>
<p>CREATE TABLE `geo_cities` (<br />
  `id` smallint(6) NOT NULL,<br />
  `city_title` varchar(255) NOT NULL,<br />
  `region_title` varchar(255) NOT NULL,<br />
  `district_title` varchar(255) NOT NULL,<br />
  PRIMARY KEY (`id`)<br />
) ENGINE=MyISAM DEFAULT CHARSET=utf8;</p>
<p>&#8211; а тут мне нафиг были не нужны столбцы &laquo;широта&raquo; и &laquo;долгота&raquo;, так что обошлось и без них. Ну и cool</p>
<p>3). пишем скрипт-парсер. Вот что я наШкодил:</p>
<p>&lt;?php<br />
// тут недурственно бы подключиться к базе; если не знаете, как, то дальше лучше не читать&#8230;</p>
<p>// очистим имеющиеся таблицы; полезно, если будете этот скрипт юзать регулярно, скармливая ему новые файлы (данные-то у IpGeoBase обновляются, так-то!)<br />
mysql_query(&#039;TRUNCATE TABLE `geo_cities`&#039;);<br />
mysql_query(&#039;TRUNCATE TABLE `geo_ips`&#039;);</p>
<p>// теперь заполним одну таблицу (какую &#8211; не принципиально)<br />
$strings = file(&#039;cidr_optim.txt&#039;); // долго не парясь, всасываем файл построчно в массив<br />
$strings_count = sizeof($strings);<br />
$rows_inserted = 0;<br />
for ($i = 0; $i &lt; $strings_count; $i++) {<br />
        // ну и побежали&#8230;<br />
	$cols = explode(&quot;\t&quot;, $strings[$i]);<br />
        // а вот тут пришлось сделать тупо построчные инсерты, отдельно для каждой записи, ибо одним запросом 130 000 элементов моё двигло впихивать категорически отказалось <img src='http://nickspring.ru/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /><br />
	$sql = &#039;INSERT INTO `geo_ips` (`ip_from`, `ip_to`, `zone`, `city_id`) VALUES (&#039;.(int) $cols[0].&#039;, &#039;.(int) $cols[1].&#039;, &quot;&#039;.$cols[3].&#039;&quot;, &#039;.( is_numeric(trim($cols[4])) ? (int) $cols[4] : &#039;null&#039; ).&#039;)&#039;; // у многих записей в ip-таблице нет городов, вместо них стоят прочерки, которые нам какбэ нах не упали, т.к. нам потом JOIN&#039;ы юзать; пустое значение тоже не подойдет; остается null<br />
	if ( !mysql_query($sql) ) {<br />
		echo &#039;ERROR (inserting row #&#039;.$i.&#039;): &#039;.mysql_errno().&#039; &#8211; &#039;.mysql_error().&#039;&#8217;;<br />
	} else {<br />
		$rows_inserted++;<br />
	}<br />
}<br />
echo &#8216;rows inserted (geo_ips): &#8216;.$rows_inserted.&raquo;; // ну это так, для наглядности <img src='http://nickspring.ru/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>// теперь заполним, соответственно, другую таблицу<br />
$strings = file(&#8216;cities.txt&#8217;);<br />
$strings_count = sizeof($strings);<br />
$rows_inserted = 0;<br />
for ($i = 0; $i &lt; $strings_count; $i++) {<br />
	$cols = mysql_real_escape_string($strings[$i]);<br />
	$cols = explode(&quot;\t&quot;, $cols);<br />
	$sql = &#039;INSERT INTO `geo_cities` (`id`, `city_title`, `region_title`, `district_title`) VALUES (&#039;.(int) $cols[0].&#039;, &quot;&#039;.$cols[1].&#039;&quot;, &quot;&#039;.$cols[2].&#039;&quot;, &quot;&#039;.$cols[3].&#039;&quot;)&#039;;<br />
	if ( !mysql_query($sql) ) {<br />
		echo &#039;ERROR (inserting row #&#039;.$i.&#039;): &#039;.mysql_errno().&#039; &#8211; &#039;.mysql_error().&#039;&#8217;;<br />
	} else {<br />
		$rows_inserted++;<br />
	}<br />
}<br />
echo &#8216;rows inserted (geo_cities): &#8216;.$rows_inserted.&raquo;;</p>
<p>// узё<br />
// у меня скрипт срабатывает примерно за 20 секунд; многовато, но что делать&#8230;<br />
?&gt;</p>
<p>4). изначально у меня задача получать название города посетителя, так что в итоге у меня получился вот такой вот запрос:</p>
<p>&lt;?php<br />
$user_ip = sprintf(&quot;%u\n&quot;, ip2long($_SERVER[&#039;REMOTE_ADDR&#039;]));</p>
<p>$sql = &#039;<br />
	SELECT<br />
		`gc`.`city_title`,<br />
		`gc`.`region_title`<br />
	FROM `geo_cities` AS `gc`<br />
	INNER JOIN `geo_ips` AS `gi`<br />
		ON `gi`.`city_id` = `gc`.`id`<br />
	WHERE `gi`.`ip_from` = &#8216;.$user_ip;</p>
<p>// &#8230;<br />
// ну дальше уж сами <img src='http://nickspring.ru/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /><br />
?&gt;</p>
]]></content:encoded>
	</item>
	<item>
		<title>Автор: sverel</title>
		<link>http://nickspring.ru/archives/31/comment-page-1#comment-38599</link>
		<dc:creator>sverel</dc:creator>
		<pubDate>Wed, 13 Apr 2011 13:12:49 +0000</pubDate>
		<guid isPermaLink="false">http://nickspring.ru/archives/31#comment-38599</guid>
		<description>Упс. ошибся по поводу дельты - не до конца разобрался. Тем не менее, запрос всё же оптимизировал так:

$ip = sprintf(&#039;%u&#039;, ip2long($ip));
$query = &#039;SELECT * FROM `geo` WHERE &#039;. $ip .&#039; BETWEEN `ip_from` AND `ip_to` ORDER BY (`ip_to`-`ip_from`) ASC LIMIT 1&#039;;</description>
		<content:encoded><![CDATA[<p>Упс. ошибся по поводу дельты &#8211; не до конца разобрался. Тем не менее, запрос всё же оптимизировал так:</p>
<p>$ip = sprintf(&#8216;%u&#8217;, ip2long($ip));<br />
$query = &#8216;SELECT * FROM `geo` WHERE &#8216;. $ip .&#8217; BETWEEN `ip_from` AND `ip_to` ORDER BY (`ip_to`-`ip_from`) ASC LIMIT 1&#8242;;</p>
]]></content:encoded>
	</item>
	<item>
		<title>Автор: sverel</title>
		<link>http://nickspring.ru/archives/31/comment-page-1#comment-38529</link>
		<dc:creator>sverel</dc:creator>
		<pubDate>Mon, 11 Apr 2011 09:51:55 +0000</pubDate>
		<guid isPermaLink="false">http://nickspring.ru/archives/31#comment-38529</guid>
		<description>Очевидно же, что вместо (ip2-ip1) лучше создать столбец `delta` и во время загрузки дампа его один раз вычислить. Иначе MySQL будет вычислять его по всей таблице при каждом запросе!!! А в таблице на данный момент 150к записей. По `delta` можно будет создать индекс и запрос превратится в совершенно примитивный.</description>
		<content:encoded><![CDATA[<p>Очевидно же, что вместо (ip2-ip1) лучше создать столбец `delta` и во время загрузки дампа его один раз вычислить. Иначе MySQL будет вычислять его по всей таблице при каждом запросе!!! А в таблице на данный момент 150к записей. По `delta` можно будет создать индекс и запрос превратится в совершенно примитивный.</p>
]]></content:encoded>
	</item>
	<item>
		<title>Автор: Бесплатное создание сайтов</title>
		<link>http://nickspring.ru/archives/31/comment-page-1#comment-35574</link>
		<dc:creator>Бесплатное создание сайтов</dc:creator>
		<pubDate>Tue, 18 Jan 2011 00:16:13 +0000</pubDate>
		<guid isPermaLink="false">http://nickspring.ru/archives/31#comment-35574</guid>
		<description>Необходимо выдернуть ip областей и вставить в тот скрипт - минуя города (сократить)</description>
		<content:encoded><![CDATA[<p>Необходимо выдернуть ip областей и вставить в тот скрипт &#8211; минуя города (сократить)</p>
]]></content:encoded>
	</item>
	<item>
		<title>Автор: дядька лама</title>
		<link>http://nickspring.ru/archives/31/comment-page-1#comment-35130</link>
		<dc:creator>дядька лама</dc:creator>
		<pubDate>Thu, 06 Jan 2011 19:35:26 +0000</pubDate>
		<guid isPermaLink="false">http://nickspring.ru/archives/31#comment-35130</guid>
		<description>Листал дамп, смущает, что регионы перекосячены для областей. Как выковыривать из дампа именно область а не город ???
У меня есть база с регионами в порядке как на автомобильных номерах. Как бы их слепить воедино, кто даст умный совет?</description>
		<content:encoded><![CDATA[<p>Листал дамп, смущает, что регионы перекосячены для областей. Как выковыривать из дампа именно область а не город ???<br />
У меня есть база с регионами в порядке как на автомобильных номерах. Как бы их слепить воедино, кто даст умный совет?</p>
]]></content:encoded>
	</item>
	<item>
		<title>Автор: дядя вася</title>
		<link>http://nickspring.ru/archives/31/comment-page-1#comment-27683</link>
		<dc:creator>дядя вася</dc:creator>
		<pubDate>Sun, 23 Aug 2009 18:52:00 +0000</pubDate>
		<guid isPermaLink="false">http://nickspring.ru/archives/31#comment-27683</guid>
		<description>попробовал поставить параметр в запрос, и перестало работать.. данные неверные пишет ...можа я чего низнамо.</description>
		<content:encoded><![CDATA[<p>попробовал поставить параметр в запрос, и перестало работать.. данные неверные пишет &#8230;можа я чего низнамо.</p>
]]></content:encoded>
	</item>
	<item>
		<title>Автор: дядя вася</title>
		<link>http://nickspring.ru/archives/31/comment-page-1#comment-27681</link>
		<dc:creator>дядя вася</dc:creator>
		<pubDate>Sun, 23 Aug 2009 18:46:34 +0000</pubDate>
		<guid isPermaLink="false">http://nickspring.ru/archives/31#comment-27681</guid>
		<description>А нахрена в конце запроса $dblink???</description>
		<content:encoded><![CDATA[<p>А нахрена в конце запроса $dblink???</p>
]]></content:encoded>
	</item>
	<item>
		<title>Автор: SEO Блог &#8211; оптимизация, раскрутка сайта. &#187; Сервисы статистики на стороне интернет-магазинов</title>
		<link>http://nickspring.ru/archives/31/comment-page-1#comment-25210</link>
		<dc:creator>SEO Блог &#8211; оптимизация, раскрутка сайта. &#187; Сервисы статистики на стороне интернет-магазинов</dc:creator>
		<pubDate>Sat, 18 Jul 2009 12:19:52 +0000</pubDate>
		<guid isPermaLink="false">http://nickspring.ru/archives/31#comment-25210</guid>
		<description>[...] Как сделать определение страны/города по ip &#8211; здесь. [...]</description>
		<content:encoded><![CDATA[<p>[...] Как сделать определение страны/города по ip &#8211; здесь. [...]</p>
]]></content:encoded>
	</item>
</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.227 seconds -->

