失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 纯真数据库 解析 php PHP解析纯真IP数据库(qqwry.dat)

纯真数据库 解析 php PHP解析纯真IP数据库(qqwry.dat)

时间:2019-12-26 09:01:43

相关推荐

纯真数据库 解析 php PHP解析纯真IP数据库(qqwry.dat)

这是一个 StructPHP 的教程帖,使用它 解析 qqwry.dat。关于 qqwry.dat 数据结构的分析,请参考:/article/17197_2.htm。,

StructPHP,仅有 20 多行代码,自我感觉不仅仅仅是对 unpack 和 pack 进行了封装,它是一种全新的编码方案。通过这种方法,可以简化 二进制转换的开发过程,使用代码更加易懂。

测试前需要先引入 StructPHP (/p/php-struct) 类,全部的代码如下:

header("Content-type:text/plain");

require 'struct.php';

// 修复数字格式,24位int

function hex_to_int24($hex) {

return unpack('L', pack('H8', $hex . '00'))[1];

}

// 二进制 转 字符串

function binstr_to_string($binstr) {

$arr = binstr_to_string_array($binstr);

return $arr[0];

}

// 二进制 转 字符串数组

function binstr_to_string_array($binstr) {

$arr = explode("\00", $binstr);

return $arr;

}

//qqwry.dat请到 纯真官网下载

$qqwry_data = file_get_contents('./qqwry.dat');

//文件头

$head_struct = array(

'start' => 'L', //第一条索引偏移

'end' => 'L', //最后一条索引偏移

);

$head_struct_len = 8;

//索引区记录定义

$index_struct = array(

'ip' => 'L', //IP地址(4个字节)

'pos' => 'H6', //地址记录偏移(3个字节,后边需补0)

);

$index_struct_len = 7;

//IP记录格式

$ip_struct = array(

'ip' => 'L', //IP地址

'type' => 'H2', //偏移类型

'pos' => 'H6', //偏移值

);

$ip_struct_len = 8;

//国家和地址定义

$area_struct = array(

'county_type' => 'H2', //国家偏移类型

'county_pos' => 'H6', //国家偏移

'address_type' => 'H2', //地址偏移类型

'address_pos' => 'H6', //地址偏移

);

$area_struct_len = 8;

//读取头

$head_binstr = substr($qqwry_data, 0, $head_struct_len);

$head_data = StructPHP::decode($head_struct, $head_binstr);

for ($index_pos = $head_data['start']; $index_pos < $head_data['end']; $index_pos += 7) {

//最终返回的数据

$data = array();

//索引数据

$index_binstr = substr($qqwry_data, $index_pos, $index_struct_len);

$index_data = StructPHP::decode($index_struct, $index_binstr);

$ip_pos = hex_to_int24($index_data['pos']);

$data['ip_start'] = long2ip($index_data['ip']);

$data['ip_pos'] = $ip_pos;

//IP数据提取

$ip_binstr = substr($qqwry_data, $ip_pos, $ip_struct_len);

$ip_data = StructPHP::decode($ip_struct, $ip_binstr);

$area_pos = hex_to_int24($ip_data['pos']);

$data['ip_end'] = long2ip($ip_data['ip']);

$data['area_type'] = $ip_data['type'];

$data['area_pos'] = $area_pos;

if (in_array($ip_data['type'], array('01', '02'))) {

//如果不是简单模式,解析 国家和地址定义

$area_binstr = substr($qqwry_data, $area_pos, $area_struct_len);

$area_data = StructPHP::decode($area_struct, $area_binstr);

}

switch ($ip_data['type']) {

case '01': //模式1, [国家+地区偏移]

$data['county_type'] = $area_data['county_type'];

switch ($area_data['county_type']) {

case '01':

//实际测试中,没有这类数据

throw new Exception("数据结构更改[area_type:01, county_type:01]");

break;

case '02':

//国家的处理方式都是一样的

$county_pos = hex_to_int24($area_data['county_pos']);

$data['county'] = binstr_to_string(substr($qqwry_data, $county_pos, 100));

switch ($area_data['address_type']) {

case '01':

//实际测试中,没有这类数据

throw new Exception("数据结构更改[area_type:01, county_type:02, address_type:01]");

break;

case '02':

/**

* 混和情况1:[地区偏移]

* |

* [国家偏移][地址偏移]

* | |

* [国家\0] [地址\0]

* /images/uploads//05/010202.gif

*/

$address_pos = hex_to_int24($area_data['address_pos']);

$data['address'] = binstr_to_string(substr($qqwry_data, $address_pos, 100));

break;

default:

/**

* 混和情况2:[地区偏移]

* |

* [国家偏移][地址\0]

* |

* [国家\0]

* /images/uploads//05/0102.gif

*/

$data['address'] = binstr_to_string(substr($qqwry_data, $area_pos + $area_struct_len, 100));

break;

}

break;

default:

/**

* 重定向模式1:[地区偏移]

* |

* [国家\0][地址\0]

* /images/uploads//05/0100.gif

*/

$data['county_type'] = '00'; //类型用00表示

$areas_arr = binstr_to_string_array(substr($qqwry_data, $area_pos, 100));

$data['county'] = $areas_arr[0];

$data['address'] = isset($areas_arr[1]) ? $areas_arr[1] : '';

break;

}

break;

case '02':

/**

* 重定向模式2:[地区偏移][地址\0]

* |

* [国家\0]

* /images/uploads//05/02.gif

*/

$data['county'] = binstr_to_string(substr($qqwry_data, $area_pos, 100));

$data['address'] = binstr_to_string(substr($qqwry_data, $ip_pos + $ip_struct_len, 100));

break;

default:

/**

* IP记录的最简单形式:[IP地址(4字节)][国家\0][地址\0]

* /images/uploads//05/00.gif

*/

$data['area_type'] = '00'; //类型用00表示

$areas_binstr = substr($qqwry_data, $ip_pos + $ip_struct_len, 100);

$areas_arr = binstr_to_string_array($areas_binstr);

$data['county'] = $areas_arr[0];

$data['address'] = isset($areas_arr[1]) ? $areas_arr[1] : '';

break;

}

print_r($data);

}

如果觉得《纯真数据库 解析 php PHP解析纯真IP数据库(qqwry.dat)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。