phonedata 0.3.0.2108
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +34 -0
- data/LICENSE +21 -0
- data/README.md +107 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/ph2loc +10 -0
- data/bin/setup +8 -0
- data/data/phone.dat +0 -0
- data/lib/phonedata/version.rb +3 -0
- data/lib/phonedata.rb +120 -0
- data/phonedata.gemspec +30 -0
- metadata +75 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f424f4aa4248920eacc5be569e3e3e1334f009e68366181743dd216f149017a1
|
4
|
+
data.tar.gz: 6b4bde990e0e74d7c6bbd8a82b4a370fb596c17ad23e70bba2630b7b3be349f6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: '012939eb410fca4cdb52ac74c2665fec3b0433eee5cafe8c3e0b8a1e676d2ff2f301875a3e9a5eac3e97357f087ed17b0a6ca5fa4b653175ed25165ebdd55d32'
|
7
|
+
data.tar.gz: eda28fe8d1285af92d0d21ce4619d6781656f3194eab9d534bca59f660087838631b8b00a50e2a32c5a2284b4ec439848876de90bf9d0511bce9fd781cb297f2
|
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
phonedata (0.1.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.5.0)
|
10
|
+
rake (12.3.3)
|
11
|
+
rspec (3.11.0)
|
12
|
+
rspec-core (~> 3.11.0)
|
13
|
+
rspec-expectations (~> 3.11.0)
|
14
|
+
rspec-mocks (~> 3.11.0)
|
15
|
+
rspec-core (3.11.0)
|
16
|
+
rspec-support (~> 3.11.0)
|
17
|
+
rspec-expectations (3.11.0)
|
18
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
19
|
+
rspec-support (~> 3.11.0)
|
20
|
+
rspec-mocks (3.11.0)
|
21
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
22
|
+
rspec-support (~> 3.11.0)
|
23
|
+
rspec-support (3.11.0)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
ruby
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
phonedata!
|
30
|
+
rake (~> 12.0)
|
31
|
+
rspec (~> 3.2)
|
32
|
+
|
33
|
+
BUNDLED WITH
|
34
|
+
2.1.4
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2022 无限前进
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# Phonedata
|
2
|
+
|
3
|
+
## 手机号码归属地信息库、手机号归属地查询
|
4
|
+
|
5
|
+
参考 https://github.com/xluohome/phonedata 基于 ruby 实现
|
6
|
+
|
7
|
+
- 归属地信息库文件大小:4,098,913 字节
|
8
|
+
- 归属地信息库最后更新:2021 年 08 月
|
9
|
+
- 手机号段记录条数:454336
|
10
|
+
|
11
|
+
### phone.dat 文件格式
|
12
|
+
|
13
|
+
| 4 bytes | <- phone.dat 版本号(如:1701即17年1月份)
|
14
|
+
------------
|
15
|
+
| 4 bytes | <- 第一个索引的偏移
|
16
|
+
-----------------------
|
17
|
+
| offset - 8 | <- 记录区
|
18
|
+
-----------------------
|
19
|
+
| index | <- 索引区
|
20
|
+
-----------------------
|
21
|
+
|
22
|
+
1. 头部为 8 个字节,版本号为 4 个字节,第一个索引的偏移为 4 个字节;
|
23
|
+
2. 记录区 中每条记录的格式为"<省份>|<城市>|<邮编>|<长途区号>\0"。 每条记录以'\0'结束;
|
24
|
+
3. 索引区 中每条记录的格式为"<手机号前七位><记录区的偏移><卡类型>",每个索引的长度为 9 个字节;
|
25
|
+
|
26
|
+
## 版本说明
|
27
|
+
|
28
|
+
项目采用 x.y.z.aaaa 的命名方式,在语义化版本的基础上加入了数据源更新版本
|
29
|
+
|
30
|
+
比如 0.3.0.2108 则代表是这个版本使用了 21 年 8 月的数据源,数据源的更新会导致语义化版本的升级,但是程序本身的升级(bugfix,new feature)不会导致数据源版本升级
|
31
|
+
|
32
|
+
比如 0.3.1.2108 代表 fix 了一个 bug,但数据源没变
|
33
|
+
|
34
|
+
## Installation
|
35
|
+
|
36
|
+
Add this line to your application's Gemfile:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
gem 'phonedata'
|
40
|
+
```
|
41
|
+
|
42
|
+
And then execute:
|
43
|
+
|
44
|
+
$ bundle install
|
45
|
+
|
46
|
+
Or install it yourself as:
|
47
|
+
|
48
|
+
$ gem install phonedata
|
49
|
+
|
50
|
+
## Usage
|
51
|
+
|
52
|
+
程序调用
|
53
|
+
|
54
|
+
```
|
55
|
+
require 'phonedata'
|
56
|
+
|
57
|
+
Phonedata.find("18755339810")
|
58
|
+
|
59
|
+
# #<struct Phonedata::Result
|
60
|
+
# phone="18755339810",
|
61
|
+
# province="安徽",
|
62
|
+
# city="芜湖",
|
63
|
+
# zipcode="241000",
|
64
|
+
# areazone="0553",
|
65
|
+
# card_type="中国移动">
|
66
|
+
```
|
67
|
+
|
68
|
+
方法清单
|
69
|
+
|
70
|
+
```
|
71
|
+
irb(main):002:0> Phonedata.methods(false)
|
72
|
+
=> [:find, :total_record, :first_record_offset, :find_from_cli, :file_version]
|
73
|
+
```
|
74
|
+
|
75
|
+
命令行调用
|
76
|
+
|
77
|
+
```
|
78
|
+
ph2loc 18755339810
|
79
|
+
```
|
80
|
+
|
81
|
+
返回
|
82
|
+
|
83
|
+
```
|
84
|
+
18755339810 安徽 芜湖 241000 241000 0553 中国移动
|
85
|
+
```
|
86
|
+
|
87
|
+
同时可以使用 Phonedata::Pd 这个单例类,将文件加载和查询放在了不同的环节,如果是服务端程序调用可以提前实例化一下,将文件加载到内存
|
88
|
+
|
89
|
+
```
|
90
|
+
irb(main):004:0> Phonedata::Pd.instance_methods(false)
|
91
|
+
=> [:find, :file_version, :total_record, :first_record_offset]
|
92
|
+
|
93
|
+
```
|
94
|
+
|
95
|
+
## Development
|
96
|
+
|
97
|
+
源码文件就一个,实现很简单
|
98
|
+
|
99
|
+
使用 rspec 跑单元测试
|
100
|
+
|
101
|
+
```
|
102
|
+
bundle exec rspec spec
|
103
|
+
```
|
104
|
+
|
105
|
+
## 感谢
|
106
|
+
|
107
|
+
感谢 https://github.com/xluohome 提供了原始库和数据文件
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "phonedata"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/ph2loc
ADDED
data/bin/setup
ADDED
data/data/phone.dat
ADDED
Binary file
|
data/lib/phonedata.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require "phonedata/version"
|
3
|
+
|
4
|
+
module Phonedata
|
5
|
+
class Error < StandardError; end
|
6
|
+
|
7
|
+
|
8
|
+
def self.find(phone_num)
|
9
|
+
return Pd.instance.find(phone_num)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.find_from_cli(phone_num)
|
13
|
+
result = self.find(phone_num)
|
14
|
+
result.to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.file_version
|
18
|
+
return Pd.instance.file_version
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.total_record
|
22
|
+
return Pd.instance.total_record
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.first_record_offset
|
26
|
+
return Pd.instance.first_record_offset
|
27
|
+
end
|
28
|
+
|
29
|
+
INT_LEN = 4
|
30
|
+
CHAR_LEN = 1
|
31
|
+
HEAD_LENGTH = 8
|
32
|
+
PHONE_INDEX_LENGTH = 9
|
33
|
+
PHONE_DAT = "phone.dat"
|
34
|
+
|
35
|
+
DICT = %w[nil 中国移动 中国联通 中国电信 中国电信虚拟运营商 中国联通虚拟运营商 中国移动虚拟运营商]
|
36
|
+
|
37
|
+
Result = Struct.new(:phone, :province, :city, :zipcode, :areazone, :card_type) do
|
38
|
+
def to_s
|
39
|
+
"#{phone} #{province} #{city} #{zipcode} #{zipcode} #{areazone} #{card_type}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
class Pd
|
43
|
+
include ::Singleton
|
44
|
+
|
45
|
+
def initialize(dat_file_path = nil)
|
46
|
+
df = dat_file_path
|
47
|
+
if df.nil?
|
48
|
+
dir = ENV['PHONE_DATA_DIR'] || File.join(File.dirname(__FILE__), "../data")
|
49
|
+
df = File.join("#{dir}/#{PHONE_DAT}")
|
50
|
+
end
|
51
|
+
f= File.open(df)
|
52
|
+
@bytes_content = f.read.bytes
|
53
|
+
end
|
54
|
+
|
55
|
+
def find(phone_num)
|
56
|
+
if phone_num.size < 7 || phone_num.size > 11
|
57
|
+
raise ArgumentError, " illegal phone length "
|
58
|
+
end
|
59
|
+
searched_phone = phone_num[0...7].to_i
|
60
|
+
#binary search
|
61
|
+
min = 0
|
62
|
+
max = total_record
|
63
|
+
while min <= max
|
64
|
+
mid = (min + max) / 2
|
65
|
+
current_offset = (first_record_offset + mid * PHONE_INDEX_LENGTH)
|
66
|
+
if current_offset >= _total_len
|
67
|
+
break
|
68
|
+
end
|
69
|
+
#
|
70
|
+
record_offset_start_idx = current_offset+INT_LEN
|
71
|
+
card_type_start_idx = current_offset+INT_LEN*2
|
72
|
+
#
|
73
|
+
cur_phone_seg = _get4(@bytes_content[current_offset...record_offset_start_idx])
|
74
|
+
record_offset = _get4(@bytes_content[record_offset_start_idx...card_type_start_idx])
|
75
|
+
card_type = @bytes_content[card_type_start_idx]
|
76
|
+
#
|
77
|
+
if searched_phone > cur_phone_seg
|
78
|
+
min = mid + 1
|
79
|
+
elsif searched_phone < cur_phone_seg
|
80
|
+
max = mid - 1
|
81
|
+
else
|
82
|
+
sub_arr = @bytes_content[record_offset...first_record_offset]
|
83
|
+
full_data_arr = sub_arr[0...sub_arr.index(0)]
|
84
|
+
full_data_str = full_data_arr.pack("C*").force_encoding('UTF-8')
|
85
|
+
result = full_data_str.split("|")
|
86
|
+
|
87
|
+
return Result.new(phone_num, result[0], result[1], result[2], result[3], DICT[card_type])
|
88
|
+
end
|
89
|
+
#
|
90
|
+
end
|
91
|
+
return Result.new(phone_num, nil, nil, nil, nil, nil)
|
92
|
+
end
|
93
|
+
|
94
|
+
def file_version
|
95
|
+
@bytes_content[0...INT_LEN].pack("C*")
|
96
|
+
end
|
97
|
+
|
98
|
+
def first_record_offset
|
99
|
+
arr = @bytes_content[INT_LEN...HEAD_LENGTH]
|
100
|
+
_get4(arr)
|
101
|
+
end
|
102
|
+
|
103
|
+
def total_record
|
104
|
+
(_total_len - first_record_offset) / PHONE_INDEX_LENGTH
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
def _total_len
|
109
|
+
@bytes_content.size
|
110
|
+
end
|
111
|
+
|
112
|
+
def _get4(byte_arr)
|
113
|
+
if byte_arr.size < 4
|
114
|
+
0
|
115
|
+
else
|
116
|
+
byte_arr[0] | byte_arr[1] << 8 | byte_arr[2] << 16 | byte_arr[3] << 24
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
data/phonedata.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'lib/phonedata/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "phonedata"
|
5
|
+
spec.version = Phonedata::VERSION
|
6
|
+
spec.license = "MIT"
|
7
|
+
spec.authors = ["Forwaard"]
|
8
|
+
spec.email = ["forwaard@163.com"]
|
9
|
+
|
10
|
+
spec.summary = "query the attribution of Chinese mobile phone numbers."
|
11
|
+
spec.description = "query the attribution of Chinese mobile phone numbers.中国手机号码归属地信息库、手机号归属地查询。"
|
12
|
+
spec.homepage = "https://github.com/FORWAARD/phonedata-ruby"
|
13
|
+
|
14
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
15
|
+
|
16
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
18
|
+
spec.metadata["changelog_uri"] = "https://github.com/FORWAARD/phonedata-ruby/blob/main/CHANGELOG.md"
|
19
|
+
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
21
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
23
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
|
+
end
|
25
|
+
|
26
|
+
spec.executables = ["ph2loc"]
|
27
|
+
spec.require_paths = ["lib"]
|
28
|
+
|
29
|
+
spec.add_development_dependency "rspec", "~> 3.2"
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: phonedata
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0.2108
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Forwaard
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-02-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.2'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.2'
|
27
|
+
description: query the attribution of Chinese mobile phone numbers.中国手机号码归属地信息库、手机号归属地查询。
|
28
|
+
email:
|
29
|
+
- forwaard@163.com
|
30
|
+
executables:
|
31
|
+
- ph2loc
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- ".gitignore"
|
36
|
+
- CHANGELOG.md
|
37
|
+
- Gemfile
|
38
|
+
- Gemfile.lock
|
39
|
+
- LICENSE
|
40
|
+
- README.md
|
41
|
+
- Rakefile
|
42
|
+
- bin/console
|
43
|
+
- bin/ph2loc
|
44
|
+
- bin/setup
|
45
|
+
- data/phone.dat
|
46
|
+
- lib/phonedata.rb
|
47
|
+
- lib/phonedata/version.rb
|
48
|
+
- phonedata.gemspec
|
49
|
+
homepage: https://github.com/FORWAARD/phonedata-ruby
|
50
|
+
licenses:
|
51
|
+
- MIT
|
52
|
+
metadata:
|
53
|
+
homepage_uri: https://github.com/FORWAARD/phonedata-ruby
|
54
|
+
source_code_uri: https://github.com/FORWAARD/phonedata-ruby
|
55
|
+
changelog_uri: https://github.com/FORWAARD/phonedata-ruby/blob/main/CHANGELOG.md
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 2.3.0
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubygems_version: 3.1.6
|
72
|
+
signing_key:
|
73
|
+
specification_version: 4
|
74
|
+
summary: query the attribution of Chinese mobile phone numbers.
|
75
|
+
test_files: []
|