最新手机号段归属地数据库 (2024年03月版)507807行

最新手机号段归属地数据库

 简单介绍

最新手机号段归属地数据库(2024年03月发行版) 507807 行
基于:最新手机号段归属地数据库
名称:手机号码归属地查询 dat 高效率查询
压缩:原版txt为30M,生成这种dat结构为1.1M
性能:每秒解析1500w+ ,简洁高效
创建:qqzeng-ip

 

 号段分配

公众移动通信网网号分配情况

 号段划分

开发参考

手机归属地查询 c#  java php 解析dat  内存优化版
快速内存数据库Redis版   以及 导入数据库 mysql mssql 脚本

 

查询演示

    微信小程序 号段归属地查询

 

最新 手机号段数据库 号码归属地数据库 移动号段 联通号段 电信号段 虚拟运营商

权威 全面 准确 规范

字段包括 省份 城市 运营商 邮编 区号 等信息,对于数据分析、号码归属地查询等非常有帮助

 

更新历史

2024-03-01 507807条记录   xlsx+txt+csv+mysql+mssql   dat
2024-02-01 507481条记录
2024-01-01 507145条记录
2023-12-01 506633条记录
2023-11-01 506236条记录
2023-10-01 505323条记录
2022-09-01 503112条记录
2022-07-01 502304条记录
2022-06-01 502304条记录
2022-05-01 502304条记录
2022-04-01 502088条记录
2022-03-01 497494条记录
2022-02-01 496782条记录
2022-01-01 496136条记录
2022-12-01 496136条记录
2022-11-01 493145条记录 
2022-10-01 493145条记录 
2022-09-01 492961条记录 
2022-08-01 492088条记录 
2022-07-01 489210条记录
2022-06-01 486922条记录
2022-05-01 485234条记录
2022-04-01 483528条记录
2022-03-01 482191条记录
2022-02-01 481615条记录
2022-01-01 481399条记录
2021-12-01 479711条记录
2021-11-01 478420条记录
2021-10-01 476737条记录
2021-09-01 475442条记录
2021-08-01 474888条记录
2021-07-01 474468条记录
2021-06-01 473721条记录
2021-05-01 473691条记录
2021-04-01 473267条记录 
2021-03-01 472529条记录
2021-02-01 472019条记录 
2021-01-01 471402条记录
2020-12-01 465883条记录 
2020-11-01 464737条记录 
2020-10-01 463471条记录
2020-09-01 459519条记录 
2020-08-15 458461条记录 
2020-08-01 458084条记录
2020-07-15 458020条记录
2020-07-01 457441条记录
2020-06-15 455731条记录
2020-06-01 454802条记录
2020-05-01 450433条记录
2020-04-01 450175条记录
2020-03-01 447897条记录
2020-01-01 442612条记录
2019-12-01 441831条记录
2019-11-01 439265条记录
2019-10-01 439025条记录
2019-09-01 438615条记录
2019-08-01 437124条记录
2019-07-01 436804条记录
2019-06-01 430826条记录
2019-05-01 429052条记录
2019-04-01 424014条记录
2019-03-01 423850条记录
2019-02-01 423766条记录
2019-01-01 421973条记录
2018-12-01 415967条记录
2018-11-01 415806条记录 
2018-10-01 415311条记录 
2018-09-01 413015条记录
2018-08-01 411856条记录
2018-07-01 410765条记录
2018-06-01 405385条记录
2018-05-01 398209条记录
2018-04-01 387892条记录
2018-03-01 382140条记录

…………
2017-07-01 363952条记录
2017-06-01 362386条记录
2017-05-01 359938条记录
…………
2013-04-01 279680条记录
2013-03-01 276893条记录
2013-02-01 275967条记录
2013-01-01 274995条记录
2012-12-01 274832条记录
…………

 

号段划分

移动号段:
134 135 136 137 138 139 147 148 150 151 152 157 158 159 172 178 182 183 184 187 188 195 198
联通号段:
130 131 132 145 146 155 156 166 167 171 175 176 185 186 196
电信号段:
133 149 153 173 174 177 180 181 189 190 191 193 199
虚拟运营商:
162 165 167 170 171
广电:
192

 

字段样例


 

号段归属地格式详解

超高性能 qqzeng-phone-3.0.dat

编码:UTF8 字节序:Little-Endian

返回多个字段信息(如:广东|深圳|518000|0755|440300|移动)

------------------------ 文件结构 ---------------------------

//文件头 20字节 4-4-4-4-4
[前缀数量][号段数量][内容区长度][运营商区长度][版本:20211201]

//内容区 长度无限制
[地区信息][地区信息]……唯一不重复

//运营商区 长度无限制
[运营商][运营商]……唯一不重复


//前缀区 7字节(1-4-2)
[号段前三位][索引区start索引][索引区个数]

//索引区 4字节(2-2)
[号段后四位][地区索引+运营商索引(不足补0)]

------------------------ 文件结构 ---------------------------

优势:压缩形式将数据存储在内存中,通过减少将相同数据读取到内存的次数来减少I/O.
较高的压缩率通过使用更小的内存中空间提高查询性能。
解析出来一次性加载到二维数组中,查询性能提高1倍!

压缩:原版txt为23M,生成dat结构为1.8M,上一版为3.2M

性能:每秒解析1000w+

对比:相比其他dat更简洁更高效

创建:qqzeng-phone 于 2021-12-12

 

3.0和2.0性能比较


新版 3.0 内存版:
查询 qqzeng-phone-3.0.dat 1500万 ->1.531秒 每秒979.7517962116265万次
查询 qqzeng-phone-3.0.dat 914万 ->0.821秒 每秒1113.2764920828258万次
查询 qqzeng-phone-3.0.dat 1424万 ->1.375秒 每秒1035.6363636363637万次
查询 qqzeng-phone-3.0.dat 584万 ->0.516秒 每秒1131.7829457364342万次
查询 qqzeng-phone-3.0.dat 1468万 ->1.29秒 每秒1137.984496124031万次
查询 qqzeng-phone-3.0.dat 1216万 ->1.061秒 每秒1146.0885956644674万次
查询 qqzeng-phone-3.0.dat 754万 ->0.673秒 每秒1120.3566121842496万次
查询 qqzeng-phone-3.0.dat 988万 ->0.871秒 每秒1134.3283582089553万次
查询 qqzeng-phone-3.0.dat 1534万 ->1.33秒 每秒1153.3834586466164万次
查询 qqzeng-phone-3.0.dat 832万 ->0.797秒 每秒1043.914680050188万次
查询 qqzeng-phone-3.0.dat 1340万 ->1.185秒 每秒1130.801687763713万次
查询 qqzeng-phone-3.0.dat 924万 ->0.807秒 每秒1144.981412639405万次
查询 qqzeng-phone-3.0.dat 848万 ->0.741秒 每秒1144.399460188934万次
查询 qqzeng-phone-3.0.dat 1526万 ->1.331秒 每秒1146.5063861758076万次
查询 qqzeng-phone-3.0.dat 808万 ->0.698秒 每秒1157.593123209169万次
查询 qqzeng-phone-3.0.dat 594万 ->0.522秒 每秒1137.9310344827586万次

旧版 2.0 内存版:
查询 qqzeng-phone.dat 1398万 ->2.932秒 每秒476.80763983628924万次
查询 qqzeng-phone.dat 1558万 ->3.037秒 每秒513.0062561738558万次
查询 qqzeng-phone.dat 822万 ->1.586秒 每秒518.2849936948297万次
查询 qqzeng-phone.dat 576万 ->1.112秒 每秒517.9856115107913万次
查询 qqzeng-phone.dat 452万 ->0.926秒 每秒488.12095032397406万次
查询 qqzeng-phone.dat 1204万 ->2.499秒 每秒481.7927170868347万次
查询 qqzeng-phone.dat 340万 ->0.713秒 每秒476.8583450210379万次
查询 qqzeng-phone.dat 352万 ->0.716秒 每秒491.6201117318436万次
查询 qqzeng-phone.dat 948万 ->1.822秒 每秒520.3073545554336万次
查询 qqzeng-phone.dat 514万 ->0.987秒 每秒520.7700101317123万次
查询 qqzeng-phone.dat 928万 ->1.783秒 每秒520.4711160964666万次
查询 qqzeng-phone.dat 1598万 ->3.108秒 每秒514.1570141570141万次
查询 qqzeng-phone.dat 446万 ->0.862秒 每秒517.4013921113689万次
查询 qqzeng-phone.dat 466万 ->0.896秒 每秒520.0892857142857万次
查询 qqzeng-phone.dat 1024万 ->1.964秒 每秒521.3849287169043万次
查询 qqzeng-phone.dat 1550万 ->2.974秒 每秒521.1835911230665万次

 

  

开发代码

  internal class PhoneSearchBest
    {
        private static readonly Lazy<PhoneSearchBest> lazy = new Lazy<PhoneSearchBest>(() => new PhoneSearchBest());
        public static PhoneSearchBest Instance { get { return lazy.Value; } }
        private PhoneSearchBest()
        {
            LoadDat();

        }

        private byte[] data;
        private long[,] phone2D;
        private string[] addrArr;
        private string[] ispArr;

        /// <summary>
        /// 初始化二进制dat数据
        /// </summary>
        /// <param name="dataPath"></param>
        /// 


        private void LoadDat()
        {

            var datPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"qqzeng-phone-3.0.dat");

            data = File.ReadAllBytes(datPath);

            var PrefSize = BitConverter.ToUInt32(data, 0);          

            var descLength = BitConverter.ToUInt32(data, 8);
            var ispLength = BitConverter.ToUInt32(data, 12);

            var PhoneSize = BitConverter.ToUInt32(data, 4);
            var verNum = BitConverter.ToUInt32(data, 16);

            var headLength = 20;
            int startIndex = (int)(headLength + descLength + ispLength);

            //内容数组        
            string descString = Encoding.UTF8.GetString(data, headLength, (int)descLength);
            addrArr = descString.Split('&');

            //运营商数组        
            string ispString = Encoding.UTF8.GetString(data, headLength + (int)descLength, (int)ispLength);
            ispArr = ispString.Split('&');


            phone2D = new long[200, 10000];
            for (var m = 0; m < PrefSize; m++)
            {
                int i = m * 7 + startIndex;
                int pref = data[i];
                int index = (int)BitConverter.ToUInt32(data, i + 1);
                int length = BitConverter.ToUInt16(data, i + 5);

                for (int n = 0; n < length; n++)
                {
                    int p = (int)(startIndex + PrefSize * 7 + (n + index) * 4);
                    var suff = BitConverter.ToUInt16(data, p);
                    var addrispIndex = BitConverter.ToUInt16(data, p + 2);
                    phone2D[pref, suff] = addrispIndex;
                }

            }



        }





        public string Query(string phone)
        {
            var prefix = Convert.ToInt32(phone.Substring(0, 3));//前缀
            var suffix = Convert.ToInt32(phone.Substring(3, 4));//后缀
            var addrispIndex = phone2D[prefix, suffix];
            if (addrispIndex == 0)
            {
                return "";
            }
            return addrArr[addrispIndex / 100] + "|" + ispArr[addrispIndex % 100];

        }

       


    }

    /*
    (调用例子):    
   string result = PhoneSearchBest.Instance.Query("号段|号码");
   --> result="省份|城市|区号|邮编|行政区划代码|运营商"
    */

 

 

 

  1 //名称:手机号码归属地查询 dat高效率查询  内存优化版
  2 //压缩:原版txt为22M,生成这种dat结构为2.66M 
  3 //性能:每秒解析300万+号段或者号码,简洁高效 
  4 //环境:CPU i7-7700K +内存16GB
  5 //创建:qqzeng-ip 
  6 
  7 
  8 using System;
  9 using System.Collections.Generic;
 10 using System.IO;
 11 using System.Text;
 12 using System.Threading;
 13 
 14 namespace qqzeng_phone_dat
 15 {
 16 
 17     public class PhoneSearchFast
 18     {
 19         private static readonly Lazy<PhoneSearchFast> lazy = new Lazy<PhoneSearchFast>(() => new PhoneSearchFast());
 20         public static PhoneSearchFast Instance { get { return lazy.Value; } }
 21         private PhoneSearchFast()
 22         {
 23             LoadDat();
 24             Watch();
 25         }
 26 
 27         private string datPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"qqzeng-phone.dat");
 28         private DateTime lastRead = DateTime.MinValue;
 29         private long[,] prefmap = new long[200, 2];//  000-199
 30 
 31 
 32         private long[,] phonemap;
 33 
 34         private byte[] data;
 35 
 36         private long[] phoneArr;
 37         private string[] addrArr;
 38         private string[] ispArr;
 39 
 40         /// <summary>
 41         /// 初始化二进制dat数据
 42         /// </summary>
 43         /// <param name="dataPath"></param>
 44         /// 
 45 
 46 
 47         private void LoadDat()
 48         {
 49             data = File.ReadAllBytes(datPath);
 50 
 51             long PrefSize = BytesToLong(data[0], data[1], data[2], data[3]);
 52             long RecordSize = BytesToLong(data[4], data[5], data[6], data[7]);
 53 
 54             long descLength = BytesToLong(data[8], data[9], data[10], data[11]);
 55             long ispLength = BytesToLong(data[12], data[13], data[14], data[15]);
 56 
 57             //内容数组
 58             int descOffset = (int)(16 + PrefSize * 9 + RecordSize * 7);
 59             string descString = Encoding.UTF8.GetString(data, descOffset, (int)descLength);
 60             addrArr = descString.Split('&');
 61 
 62             //运营商数组
 63             int ispOffset = (int)(16 + PrefSize * 9 + RecordSize * 7 + descLength);
 64             string ispString = Encoding.UTF8.GetString(data, ispOffset, (int)ispLength);
 65             ispArr = ispString.Split('&');
 66 
 67 
 68 
 69             //前缀区
 70             int m = 0;
 71             for (var k = 0; k < PrefSize; k++)
 72             {
 73                 int i = k * 9 + 16;
 74                 int n = data[i];
 75                 prefmap[n, 0] = BytesToLong(data[i + 1], data[i + 2], data[i + 3], data[i + 4]);
 76                 prefmap[n, 1] = BytesToLong(data[i + 5], data[i + 6], data[i + 7], data[i + 8]);
 77                 if (m < n)
 78                 {
 79                     for (; m < n; m++)
 80                     {
 81                         prefmap[m, 0] = 0; prefmap[m, 1] = 0;
 82                     }
 83                     m++;
 84                 }
 85                 else
 86                 {
 87                     m++;
 88                 }
 89             }
 90 
 91             //索引区
 92             phoneArr = new long[RecordSize];
 93             phonemap = new long[RecordSize, 2];
 94             for (int i = 0; i < RecordSize; i++)
 95             {
 96                 long p = 16 + PrefSize * 9 + (i * 7);
 97                 phoneArr[i] = BytesToLong(data[p], data[1 + p], data[2 + p], data[3 + p]);
 98                 phonemap[i, 0] = data[4 + p] + ((data[5 + p]) << 8);
 99                 phonemap[i, 1] = data[6 + p];
100             }
101 
102 
103 
104         }
105         private void Watch()
106         {
107             FileInfo fi = new FileInfo(datPath);
108             FileSystemWatcher watcher = new FileSystemWatcher(fi.DirectoryName)
109             {
110                 IncludeSubdirectories = false,
111                 NotifyFilter = NotifyFilters.LastWrite,
112                 Filter = "qqzeng-phone.dat",
113             };
114 
115             watcher.Changed += (s, e) =>
116             {
117 
118                 var lastWriteTime = File.GetLastWriteTime(datPath);
119 
120                 if (lastWriteTime > lastRead)
121                 {
122                     //延时 解决 正由另一进程使用,因此该进程无法访问此文件
123                     Thread.Sleep(1000);
124 
125                     LoadDat();
126                     lastRead = lastWriteTime;
127                 }
128             };
129             watcher.EnableRaisingEvents = true;
130         }
131 
132 
133 
134 
135         /// <summary>
136         /// 号段查询
137         /// </summary>
138         /// <param name="phone">7位或者11位</param>
139         /// <returns></returns>
140         public string Query(string phone)
141         {
142             long pref;
143             long val = PhoneToInt(phone, out pref);
144             long low = prefmap[pref, 0], high = prefmap[pref, 1];
145             if (high == 0)
146             {
147                 return "";
148             }
149             long cur = low == high ? low : BinarySearch(low, high, val);
150             if (cur != -1)
151             {
152 
153                 return addrArr[phonemap[cur, 0]] + "|" + ispArr[phonemap[cur, 1]];
154             }
155             else
156             {
157                 return "";
158             }
159 
160 
161 
162 
163 
164 
165         }
166         /// <summary>
167         /// 二分算法
168         /// </summary>
169         private int BinarySearch(long low, long high, long key)
170         {
171             if (low > high)
172                 return -1;
173             else
174             {
175                 long mid = (low + high) / 2;
176                 long phoneNum = phoneArr[mid];
177                 if (phoneNum == key)
178                     return (int)mid;
179                 else if (phoneNum > key)
180                     return BinarySearch(low, mid - 1, key);
181                 else
182                     return BinarySearch(mid + 1, high, key);
183             }
184         }
185 
186 
187 
188         private long PhoneToInt(string phone, out long prefix)
189         {
190             //最高性能
191             char ch;
192             long currentValue = 0;
193             long prefval = 0;
194             unsafe
195             {
196                 fixed (char* name = phone)
197                 {
198                     for (int current = 0; current < 7; current++)
199                     {
200                         ch = name[current];
201                         int digitValue = ch - '0';
202                         currentValue = (currentValue * 10) + digitValue;
203                         if (current == 2)
204                         {
205                             prefval = currentValue;
206                         }
207                     }
208                 }
209                 prefix = prefval;
210                 return currentValue;
211             }
212 
213 
214             //prefix = Convert.ToUInt32(phone.Substring(0,3));
215             //return Convert.ToUInt32(phone.Substring(0, 7)); ;
216         }
217 
218 
219 
220         /// <summary>
221         /// 字节转整形 小节序 
222         /// </summary>     
223         private uint BytesToLong(byte a, byte b, byte c, byte d)
224         {
225             return (uint)(a | (b << 8) | (c << 16) | (d << 24));
226         }
227 
228 
229 
230     }
231 
232     /*
233     (调用例子):    
234     string result = PhoneSearchFast.Instance.Query("号段|号码");
235    --> result="省份|城市|区号|邮编|行政区划代码|运营商"
236     */
237 }
2.0 内存版 每秒500w+

 

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace qqzeng_phone_dat
{
    public class PhoneSearch
    {

        private Dictionary<uint, PrefixIndex> prefixDict;
        private byte[] indexBuffer;
        private byte[] data;
        long firstPhoneOffset;//索引区第一条流位置
        long lastPhoneOffset;//索引区最后一条流位置
        long prefixStartOffset;//前缀区第一条的流位置
        long prefixEndOffset;//前缀区最后一条的流位置
        long phoneCount;       //号段段数量
        long prefixCount;  //前缀数量

        /// <summary>
        /// 初始化二进制dat数据
        /// </summary>
        /// <param name="dataPath"></param>
        public PhoneSearch(string dataPath)
        {
            using (FileStream fs = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                data = new byte[fs.Length];
                fs.Read(data, 0, data.Length);
            }

            firstPhoneOffset = BytesToLong(data[0], data[1], data[2], data[3]);
            lastPhoneOffset = BytesToLong(data[4], data[5], data[6], data[7]);
            prefixStartOffset = BytesToLong(data[8], data[9], data[10], data[11]);
            prefixEndOffset = BytesToLong(data[12], data[13], data[14], data[15]);



            phoneCount = (lastPhoneOffset - firstPhoneOffset) / 8 + 1; //索引区块每组 8字节          
            prefixCount = (prefixEndOffset - prefixStartOffset) / 9 + 1; //前缀区块每组 9字节

            //初始化前缀对应索引区区间
            indexBuffer = new byte[prefixCount * 9];
            Array.Copy(data, prefixStartOffset, indexBuffer, 0, prefixCount * 9);
            prefixDict = new Dictionary<uint, PrefixIndex>();
            for (var k = 0; k < prefixCount; k++)
            {
                int i = k * 9;
                uint prefix = (uint)indexBuffer[i];
                long start_index = BytesToLong(indexBuffer[i + 1], indexBuffer[i + 2], indexBuffer[i + 3], indexBuffer[i + 4]);
                long end_index = BytesToLong(indexBuffer[i + 5], indexBuffer[i + 6], indexBuffer[i + 7], indexBuffer[i + 8]);
                prefixDict.Add(prefix, new PrefixIndex() { prefix = prefix, start_index = start_index, end_index = end_index });
            }

        }

        public static uint PhoneToInt(string phone, out uint prefix)
        {
            prefix = Convert.ToUInt32(phone.Substring(0, 3));
            return Convert.ToUInt32(phone.Substring(0, 7)); ;
        }

        /// <summary>
        /// 号段查询
        /// </summary>
        /// <param name="phone">7位或者11位</param>
        /// <returns></returns>
        public string Query(string phone)
        {
            uint phone_prefix_value;
            uint intPhone = PhoneToInt(phone, out phone_prefix_value);
            uint high = 0;
            uint low = 0;

            uint local_offset = 0;
            uint local_length = 0;


            if (prefixDict.ContainsKey(phone_prefix_value))
            {
                low = (uint)prefixDict[phone_prefix_value].start_index;
                high = (uint)prefixDict[phone_prefix_value].end_index;
            }
            else
            {
                return "";
            }

            uint my_index = low == high ? low : BinarySearch(low, high, intPhone);

            GetIndex(my_index, out local_offset, out local_length);

            return GetLocal(local_offset, local_length);


        }
        /// <summary>
        /// 二分算法
        /// </summary>
        public uint BinarySearch(uint low, uint high, uint k)
        {
            uint M = 0;
            while (low <= high)
            {
                uint mid = (low + high) / 2;

                uint phoneNum = GetIntPhone(mid);

                if (phoneNum >= k)
                {

                    M = mid;
                    if (mid == 0)
                    {
                        break;   //防止溢出
                    }
                    high = mid - 1;
                }
                else
                    low = mid + 1;
            }
            return M;
        }
        /// <summary>
        /// 在索引区解析
        /// </summary>
        /// <param name="left">ip第left个索引</param>
        /// <param name="startip">返回开始ip的数值</param>
        /// <param name="endip">返回结束ip的数值</param>
        /// <param name="local_offset">返回地址信息的流位置</param>
        /// <param name="local_length">返回地址信息的流长度</param>
        private void GetIndex(uint left, out uint local_offset, out uint local_length)
        {
            long left_offset = firstPhoneOffset + (left * 8);
            local_offset = (uint)data[4 + left_offset] + (((uint)data[5 + left_offset]) << 8) + (((uint)data[6 + left_offset]) << 16);
            local_length = (uint)data[7 + left_offset];
        }


        /// <summary>
        /// 返回归属地信息
        /// </summary>
        /// <param name="local_offset">地址信息的流位置</param>
        /// <param name="local_length">地址信息的流长度</param>
        /// <returns></returns>
        private string GetLocal(uint local_offset, uint local_length)
        {
            byte[] buf = new byte[local_length];
            Array.Copy(data, local_offset, buf, 0, local_length);
            return Encoding.UTF8.GetString(buf, 0, (int)local_length);

            // return Encoding.GetEncoding("GB2312").GetString(buf, 0, (int)local_length);

        }

        private uint GetIntPhone(uint left)
        {
            long left_offset = firstPhoneOffset + (left * 8);
            return BytesToLong(data[0 + left_offset], data[1 + left_offset], data[2 + left_offset], data[3 + left_offset]);

        }


        /// <summary>
        /// 字节转整形 小节序 
        /// </summary>     
        private uint BytesToLong(byte a, byte b, byte c, byte d)
        {
            return ((uint)a << 0) | ((uint)b << 8) | ((uint)c << 16) | ((uint)d << 24);
        }



    }

    /*
    (调用例子):
    PhoneSearch finder = new PhoneSearch("qqzeng-phone.dat");
    string result = finder.Query("号段或者号码");
   --> result="省份|城市|运营商|区号|邮编|行政区划代码"
    */
}
普通版 每秒200w+

 

开发:https://github.com/zengzhan/qqzeng-ip

 

posted @ 2017-05-24 12:09  曾祥展  阅读(208150)  评论(0编辑  收藏  举报