php ip定位簡單使用
關於ip定位的簡單使用
做微信公眾號很多地方需要定位, 當然公眾號的定位有很多種, wxjs獲取, 還有位置監聽, 粉絲進入公眾號會上報地理位置. 這些都會經常用到, 但是但是還是不能夠做到全部應用, 比如訂閱號就沒有使用定位許可權. 又或者粉絲不必進入公眾號就隨時可以進入公眾號這樣位置資訊也不準確, 所以這裡再介紹一種ip定位, 簡單實用.
- 獲取ip
/**
* 獲取ip
* @return string
*/
public function getip() {
static $ip = '';
$ip = $_SERVER['REMOTE_ADDR'];
if(isset($_SERVER['HTTP_CDN_SRC_IP'])) {
$ip = $_SERVER['HTTP_CDN_SRC_IP'];
} elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
foreach ($matches[0] AS $xip) {
if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {
$ip = $xip;
break;
}
}
}
return $ip;
}
- 建立一個網路請求 (簡單)
/**
* 執行CURL請求
* @author: xialei<xialeistudio@gmail.com>
* @param $url
* @param array $params
* @param bool $encode
* @param int $method
* @return mixed
*/
public function async($url, $params = array(), $encode = true, $method = 1)
{
$ch = curl_init();
if ($method == 1)
{
$url = $url . '?' . http_build_query($params);
$url = $encode ? $url : urldecode($url);
curl_setopt($ch, CURLOPT_URL, $url);
}
else
{
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
}
curl_setopt($ch, CURLOPT_REFERER, '百度地圖referer');
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$resp = curl_exec($ch);
curl_close($ch);
return $resp;
}
- 獲取位置資訊
/**
* ip定位
* @param string $ip
* @return array
* @throws Exception
*/
public function locationByIP($ip)
{
//檢查是否合法IP
if (!filter_var($ip, FILTER_VALIDATE_IP))
{
throw new Exception('ip地址不合法');
}
$params = array(
'ak' => '百度apikey',
'ip' => $ip,
'coor' => 'bd09ll'//百度地圖GPS座標
);
$api = 'http://api.map.baidu.com/location/ip';
$resp = $this->async($api, $params);
$data = json_decode($resp, true);
//有錯誤
if ($data['status'] != 0)
{
throw new Exception($data['message']);
}
//返回地址資訊
return array(
'address' => $data['content']['address'],
'province' => $data['content']['address_detail']['province'],
'city' => $data['content']['address_detail']['city'],
'district' => $data['content']['address_detail']['district'],
'street' => $data['content']['address_detail']['street'],
'street_number' => $data['content']['address_detail']['street_number'],
'city_code' => $data['content']['address_detail']['city_code'],
'lng' => $data['content']['point']['x'],
'lat' => $data['content']['point']['y']
);
}
使用
ip做個巨集定義方便使用define('CLIENT_IP', getip());
public function test()
{
print_r($this->locationByIP(CLIENT_IP));
}
- 另一種利用ip庫獲取位置的方法
/**
* 根據ip獲取省份省市
* @param string $ip
* @return string
*/
function convertip($ip) {
//IP資料檔案路徑
$dat_path = 'qqwry.dat';
//檢查IP地址
if(!preg_match("/^d{1,3}.d{1,3}.d{1,3}.d{1,3}$/", $ip)) {
return 'IP Address Error';
}
//開啟IP資料檔案
if(!$fd = @fopen($dat_path, 'rb')){
return 'IP date file not exists or access denied';
}
//分解IP進行運算,得出整形數
$ip = explode('.', $ip);
$ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];
//獲取IP資料索引開始和結束位置
$DataBegin = fread($fd, 4);
$DataEnd = fread($fd, 4);
$ipbegin = implode('', unpack('L', $DataBegin));
if($ipbegin < 0) $ipbegin += pow(2, 32);
$ipend = implode('', unpack('L', $DataEnd));
if($ipend < 0) $ipend += pow(2, 32);
$ipAllNum = ($ipend - $ipbegin) / 7 + 1;
$BeginNum = 0;
$EndNum = $ipAllNum;
//使用二分查詢法從索引記錄中搜尋匹配的IP記錄
while($ip1num>$ipNum || $ip2num<$ipNum) {
$Middle= intval(($EndNum + $BeginNum) / 2);
//偏移指標到索引位置讀取4個位元組
fseek($fd, $ipbegin + 7 * $Middle);
$ipData1 = fread($fd, 4);
if(strlen($ipData1) < 4) {
fclose($fd);
return 'System Error';
}
//提取出來的資料轉換成長整形,如果資料是負數則加上2的32次冪
$ip1num = implode('', unpack('L', $ipData1));
if($ip1num < 0) $ip1num += pow(2, 32);
//提取的長整型數大於我們IP地址則修改結束位置進行下一次迴圈
if($ip1num > $ipNum) {
$EndNum = $Middle;
continue;
}
//取完上一個索引後取下一個索引
$DataSeek = fread($fd, 3);
if(strlen($DataSeek) < 3) {
fclose($fd);
return 'System Error';
}
$DataSeek = implode('', unpack('L', $DataSeek.chr(0)));
fseek($fd, $DataSeek);
$ipData2 = fread($fd, 4);
if(strlen($ipData2) < 4) {
fclose($fd);
return 'System Error';
}
$ip2num = implode('', unpack('L', $ipData2));
if($ip2num < 0) $ip2num += pow(2, 32);
//沒找到提示未知
if($ip2num < $ipNum) {
if($Middle == $BeginNum) {
fclose($fd);
return 'Unknown';
}
$BeginNum = $Middle;
}
}
$ipFlag = fread($fd, 1);
if($ipFlag == chr(1)) {
$ipSeek = fread($fd, 3);
if(strlen($ipSeek) < 3) {
fclose($fd);
return 'System Error';
}
$ipSeek = implode('', unpack('L', $ipSeek.chr(0)));
fseek($fd, $ipSeek);
$ipFlag = fread($fd, 1);
}
if($ipFlag == chr(2)) {
$AddrSeek = fread($fd, 3);
if(strlen($AddrSeek) < 3) {
fclose($fd);
return 'System Error';
}
$ipFlag = fread($fd, 1);
if($ipFlag == chr(2)) {
$AddrSeek2 = fread($fd, 3);
if(strlen($AddrSeek2) < 3) {
fclose($fd);
return 'System Error';
}
$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
fseek($fd, $AddrSeek2);
} else {
fseek($fd, -1, SEEK_CUR);
}
while(($char = fread($fd, 1)) != chr(0))
$ipAddr2 .= $char;
$AddrSeek = implode('', unpack('L', $AddrSeek.chr(0)));
fseek($fd, $AddrSeek);
while(($char = fread($fd, 1)) != chr(0))
$ipAddr1 .= $char;
} else {
fseek($fd, -1, SEEK_CUR);
while(($char = fread($fd, 1)) != chr(0))
$ipAddr1 .= $char;
$ipFlag = fread($fd, 1);
if($ipFlag == chr(2)) {
$AddrSeek2 = fread($fd, 3);
if(strlen($AddrSeek2) < 3) {
fclose($fd);
return 'System Error';
}
$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
fseek($fd, $AddrSeek2);
} else {
fseek($fd, -1, SEEK_CUR);
}
while(($char = fread($fd, 1)) != chr(0)){
$ipAddr2 .= $char;
}
}
fclose($fd);
//最後做相應的替換操作後返回結果
if(preg_match('/http/i', $ipAddr2)) {
$ipAddr2 = '';
}
$ipaddr = "$ipAddr1 $ipAddr2";
$ipaddr = preg_replace('/CZ88.Net/is', '', $ipaddr);
$ipaddr = preg_replace('/^s*/is', '', $ipaddr);
$ipaddr = preg_replace('/s*$/is', '', $ipaddr);
if(preg_match('/http/i', $ipaddr) || $ipaddr == '') {
$ipaddr = 'Unknown';
}
$ipaddr = iconv('gbk', 'utf-8//IGNORE', $ipaddr); //轉換編碼,如果網頁的gbk可以刪除此行
return $ipaddr;
}
注意這裡依賴檔案 qqwry.dat 庫, 需要頻繁更新, 可在百度搜尋 qqwry.dat 及能找到.
- 一般用求到定位會用到求距離
/**
* 計算兩點地理座標之間的距離
* @param Decimal $longitude1 起點經度
* @param Decimal $latitude1 起點緯度
* @param Decimal $longitude2 終點經度
* @param Decimal $latitude2 終點緯度
* @param Int $unit 單位 1:米 2:公里
* @param Int $decimal 精度 保留小數位數
* @return Decimal
*/
public function getDistance($longitude1, $latitude1, $longitude2, $latitude2, $unit=2, $decimal=2){
$EARTH_RADIUS = 6370.996; // 地球半徑係數
$PI = 3.1415926;
$radLat1 = $latitude1 * $PI / 180.0;
$radLat2 = $latitude2 * $PI / 180.0;
$radLng1 = $longitude1 * $PI / 180.0;
$radLng2 = $longitude2 * $PI /180.0;
$a = $radLat1 - $radLat2;
$b = $radLng1 - $radLng2;
$distance = 2 * asin(sqrt(pow(sin($a/2),2) + cos($radLat1) * cos($radLat2) * pow(sin($b/2),2)));
$distance = $distance * $EARTH_RADIUS * 1000;
if($unit==2){
$distance = $distance / 1000;
}
return round($distance, $decimal);
}
關於微信的js定位文件已經很清楚了這裡不做例項了
相關文章
- Python代理IP爬蟲的簡單使用Python爬蟲
- PHP PDO 簡單教程PHP
- PHP + Laravel 的簡單應用教程 — ajax 的使用PHPLaravel
- php面試簡單整理PHP面試
- PHP socket 的簡單理解PHP
- 蘋果IP:如何換IP?換IP最簡單的方法分享蘋果
- PHP生成簡單二維碼PHP
- php 單獨使用DBPHP
- Ubuntu-kali配置動態ip(簡單)Ubuntu
- 關於 PHP 框架的簡單思考PHP框架
- laragon 簡單好用的 PHP 環境GoPHP
- 簡單的php連線mysql類PHPMySql
- EasyTpl - 簡單快速的 PHP 模板引擎PHP
- PHP 獲取使用者真實的ipPHP
- BootStrapValidate 簡單使用boot
- GCDAsyncSocket 簡單使用GC
- gorm 簡單使用GoORM
- JPTabBar簡單使用tabBar
- Drozer簡單使用
- jq 簡單使用
- git簡單使用Git
- OpenFeign簡單使用
- LinqPad簡單使用
- Badger簡單使用
- 簡單使用 rocketmqMQ
- kvm簡單使用
- Quartz 簡單使用quartz
- kustomize簡單使用
- apijson簡單使用APIJSON
- Github 簡單使用Github
- mogilefs簡單使用
- 簡單使用autossh
- 根據IP定位地理位置
- 通過qq進行ip定位
- 使用docker-compsoe構建一個簡單nginx+php環境DockerNginxPHP
- 圖形介面的TCP/IP簡單通訊TCP
- Kdevelop的簡單使用和簡單除錯dev除錯
- prometheus 簡單使用及簡單 middleware 開發Prometheus
- PHP設計模式(一)簡單工廠模式 (Simple Factory For PHP)PHP設計模式