1
This commit is contained in:
@@ -2,12 +2,11 @@ package ascription_place
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/xluohome/phonedata"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAscriptionPlace(t *testing.T) {
|
||||
p, err := phonedata.Find("18744776542")
|
||||
p, err := Find("18744776542")
|
||||
fmt.Println(p)
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
BIN
platformapi/tiktok_shop/ascription_place/phone.dat
Normal file
BIN
platformapi/tiktok_shop/ascription_place/phone.dat
Normal file
Binary file not shown.
184
platformapi/tiktok_shop/ascription_place/phonedata.go
Normal file
184
platformapi/tiktok_shop/ascription_place/phonedata.go
Normal file
@@ -0,0 +1,184 @@
|
||||
package ascription_place
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
CMCC byte = iota + 0x01 //中国移动
|
||||
CUCC //中国联通
|
||||
CTCC //中国电信
|
||||
CTCC_v //电信虚拟运营商
|
||||
CUCC_v //联通虚拟运营商
|
||||
CMCC_v //移动虚拟运营商
|
||||
INT_LEN = 4
|
||||
CHAR_LEN = 1
|
||||
HEAD_LENGTH = 8
|
||||
PHONE_INDEX_LENGTH = 9
|
||||
PHONE_DAT = "phone.dat"
|
||||
)
|
||||
|
||||
type PhoneRecord struct {
|
||||
PhoneNum string
|
||||
Province string
|
||||
City string
|
||||
ZipCode string
|
||||
AreaZone string
|
||||
CardType string
|
||||
}
|
||||
|
||||
var (
|
||||
content []byte
|
||||
CardTypemap = map[byte]string{
|
||||
CMCC: "中国移动",
|
||||
CUCC: "中国联通",
|
||||
CTCC: "中国电信",
|
||||
CTCC_v: "中国电信虚拟运营商",
|
||||
CUCC_v: "中国联通虚拟运营商",
|
||||
CMCC_v: "中国移动虚拟运营商",
|
||||
}
|
||||
total_len, firstoffset int32
|
||||
)
|
||||
|
||||
func init() {
|
||||
dir := os.Getenv("PHONE_DATA_DIR")
|
||||
if dir == "" {
|
||||
_, fulleFilename, _, _ := runtime.Caller(0)
|
||||
dir = path.Dir(fulleFilename)
|
||||
}
|
||||
var err error
|
||||
content, err = ioutil.ReadFile(path.Join(dir, PHONE_DAT))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
total_len = int32(len(content))
|
||||
firstoffset = get4(content[INT_LEN : INT_LEN*2])
|
||||
}
|
||||
|
||||
func Debug() {
|
||||
fmt.Println(version())
|
||||
fmt.Println(totalRecord())
|
||||
fmt.Println(firstRecordOffset())
|
||||
}
|
||||
|
||||
func (pr PhoneRecord) String() string {
|
||||
return fmt.Sprintf("PhoneNum: %s\nAreaZone: %s\nCardType: %s\nCity: %s\nZipCode: %s\nProvince: %s\n", pr.PhoneNum, pr.AreaZone, pr.CardType, pr.City, pr.ZipCode, pr.Province)
|
||||
}
|
||||
|
||||
func get4(b []byte) int32 {
|
||||
if len(b) < 4 {
|
||||
return 0
|
||||
}
|
||||
return int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24
|
||||
}
|
||||
|
||||
func getN(s string) (uint32, error) {
|
||||
var n, cutoff, maxVal uint32
|
||||
i := 0
|
||||
base := 10
|
||||
cutoff = (1<<32-1)/10 + 1
|
||||
maxVal = 1<<uint(32) - 1
|
||||
for ; i < len(s); i++ {
|
||||
var v byte
|
||||
d := s[i]
|
||||
switch {
|
||||
case '0' <= d && d <= '9':
|
||||
v = d - '0'
|
||||
case 'a' <= d && d <= 'z':
|
||||
v = d - 'a' + 10
|
||||
case 'A' <= d && d <= 'Z':
|
||||
v = d - 'A' + 10
|
||||
default:
|
||||
return 0, errors.New("invalid syntax")
|
||||
}
|
||||
if v >= byte(base) {
|
||||
return 0, errors.New("invalid syntax")
|
||||
}
|
||||
|
||||
if n >= cutoff {
|
||||
// n*base overflows
|
||||
n = (1<<32 - 1)
|
||||
return n, errors.New("value out of range")
|
||||
}
|
||||
n *= uint32(base)
|
||||
|
||||
n1 := n + uint32(v)
|
||||
if n1 < n || n1 > maxVal {
|
||||
// n+v overflows
|
||||
n = (1<<32 - 1)
|
||||
return n, errors.New("value out of range")
|
||||
}
|
||||
n = n1
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func version() string {
|
||||
return string(content[0:INT_LEN])
|
||||
}
|
||||
|
||||
func totalRecord() int32 {
|
||||
return (int32(len(content)) - firstRecordOffset()) / PHONE_INDEX_LENGTH
|
||||
}
|
||||
|
||||
func firstRecordOffset() int32 {
|
||||
return get4(content[INT_LEN : INT_LEN*2])
|
||||
}
|
||||
|
||||
// 二分法查询phone数据
|
||||
func Find(phone_num string) (pr *PhoneRecord, err error) {
|
||||
if len(phone_num) < 7 || len(phone_num) > 11 {
|
||||
return nil, errors.New("illegal phone length")
|
||||
}
|
||||
|
||||
var left int32
|
||||
phone_seven_int, err := getN(phone_num[0:7])
|
||||
if err != nil {
|
||||
return nil, errors.New("illegal phone number")
|
||||
}
|
||||
phone_seven_int32 := int32(phone_seven_int)
|
||||
right := (total_len - firstoffset) / PHONE_INDEX_LENGTH
|
||||
for {
|
||||
if left > right {
|
||||
break
|
||||
}
|
||||
mid := (left + right) / 2
|
||||
offset := firstoffset + mid*PHONE_INDEX_LENGTH
|
||||
if offset >= total_len {
|
||||
break
|
||||
}
|
||||
cur_phone := get4(content[offset : offset+INT_LEN])
|
||||
record_offset := get4(content[offset+INT_LEN : offset+INT_LEN*2])
|
||||
card_type := content[offset+INT_LEN*2 : offset+INT_LEN*2+CHAR_LEN][0]
|
||||
switch {
|
||||
case cur_phone > phone_seven_int32:
|
||||
right = mid - 1
|
||||
case cur_phone < phone_seven_int32:
|
||||
left = mid + 1
|
||||
default:
|
||||
cbyte := content[record_offset:]
|
||||
end_offset := int32(bytes.Index(cbyte, []byte("\000")))
|
||||
data := bytes.Split(cbyte[:end_offset], []byte("|"))
|
||||
card_str, ok := CardTypemap[card_type]
|
||||
if !ok {
|
||||
card_str = "未知电信运营商"
|
||||
}
|
||||
pr = &PhoneRecord{
|
||||
PhoneNum: phone_num,
|
||||
Province: string(data[0]),
|
||||
City: string(data[1]),
|
||||
ZipCode: string(data[2]),
|
||||
AreaZone: string(data[3]),
|
||||
CardType: card_str,
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
return nil, errors.New("phone's data not found")
|
||||
}
|
||||
Reference in New Issue
Block a user