Class: IpLocatorCn::QQWry

Inherits:
Object
  • Object
show all
Defined in:
lib/ip_locator_cn/qqwry.rb,
lib/ip_locator_cn/qqwry/isp.rb,
lib/ip_locator_cn/qqwry/provinces.rb,
lib/ip_locator_cn/qqwry/city_directly.rb

Constant Summary collapse

IP_ENTRY_BYTES =
7
ISP =
%w[
  联通
  移动
  铁通
  电信
  长城
  聚友
].freeze
PROVINCES =
%w[
  北京
  天津
  重庆
  上海
  河北
  山西
  辽宁
  吉林
  黑龙江
  江苏
  浙江
  安徽
  福建
  江西
  山东
  河南
  湖北
  湖南
  广东
  海南
  四川
  贵州
  云南
  陕西
  甘肃
  青海
  台湾
  内蒙古
  广西
  宁夏
  新疆
  西藏
  香港
  澳门
].freeze
CITY_DIRECTLY =
%w[
  北京
  天津
  重庆
  上海
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dat_path: nil, live_dat: false, debug: false) ⇒ QQWry

Returns a new instance of QQWry.



11
12
13
14
15
16
17
18
19
20
# File 'lib/ip_locator_cn/qqwry.rb', line 11

def initialize(dat_path: nil, live_dat: false, debug: false)
  @debug = debug
  if live_dat
    live_load_dat
    parse_dat_info
  elsif dat_path
    @io = File.open(dat_path, 'rb')
    parse_dat_info
  end
end

Instance Attribute Details

#debugObject (readonly)

Returns the value of attribute debug.



9
10
11
# File 'lib/ip_locator_cn/qqwry.rb', line 9

def debug
  @debug
end

#first_ip_posObject (readonly)

Returns the value of attribute first_ip_pos.



9
10
11
# File 'lib/ip_locator_cn/qqwry.rb', line 9

def first_ip_pos
  @first_ip_pos
end

#last_ip_posObject (readonly)

Returns the value of attribute last_ip_pos.



9
10
11
# File 'lib/ip_locator_cn/qqwry.rb', line 9

def last_ip_pos
  @last_ip_pos
end

#total_ipsObject (readonly)

Returns the value of attribute total_ips.



9
10
11
# File 'lib/ip_locator_cn/qqwry.rb', line 9

def total_ips
  @total_ips
end

Instance Method Details

#extract_location(str) ⇒ Object

提取 四川省成都市高新区 => 中国 四川 成都市 高新区



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/ip_locator_cn/qqwry.rb', line 111

def extract_location(str)
  collection = {}
  seperator_sheng = ''
  seperator_shi = ''
  seperator_xian = ''
  seperator_qu = ''
  is_city_directly = false

  # 省份
  if str.include?(seperator_sheng)
    collection[:province], str = str.split(seperator_sheng, 2)
  else
    province = (PROVINCES + CITY_DIRECTLY).find { |x| str.start_with?(x) }
    if province
      collection[:province] = province
      is_city_directly = CITY_DIRECTLY.include?(province)
      str = str[province.length..-1]
      str = str[1..-1] if str.start_with?(seperator_shi) # 上海市浦东区 => [上海, 市浦东区] => [上海, 浦东区]
    end
  end

  return { country: str } unless collection.key?(:province)

  # 市
  if str.include?(seperator_shi)
    collection[:city], str = str.split(seperator_shi, 2)
    collection[:city] += seperator_shi
  end

  # 县
  if str.include?(seperator_xian)
    collection[:county], str = str.split(seperator_xian, 2)
    collection[:county] += seperator_xian
  end

  # 区
  if !collection.key?(:county) && str.include?(seperator_qu)
    collection[:county], str = str.split(seperator_qu, 2)
    collection[:county] += seperator_qu
    if is_city_directly
      collection[:city] = collection[:county]
      collection.delete(:county)
    end
  end

  collection[:country] = '中国'
  collection
end

#location_from_ip(ip) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/ip_locator_cn/qqwry.rb', line 53

def location_from_ip(ip)
  info = {}
  pos = locate_ip_pos(ip)
  log "pos is #{pos}"
  # 用户IP所在范围的开始地址
  seek(pos)
  begin_ip = long2ip(read_ip)
  log "begin_ip is #{begin_ip}"
  # 用户IP所在范围的结束地址
  offset = getlong3
  seek(offset)
  endip = long2ip(read_ip)
  log "endip is #{endip}"
  log "offset is #{offset}"
  byte = read(1) # 标志字节
  case byte.ord
  when 1
    # 标志字节为1,表示国家和区域信息都被同时重定向
    country_offset = getlong3 # 重定向地址
    seek(country_offset)
    byte = read(1) # 标志字节
    case byte.ord
    when 2
      seek(getlong3)
      info[:country] = getstring
      seek(country_offset + 4)
      info[:area] = getarea
    else
      info[:country] = getstring(byte)
      info[:area] = getarea
    end
  when 2
    # 标志字节为2,表示国家信息被重定向
    seek(getlong3)
    info[:country] = getstring
    seek(offset + 8)
    info[:area] = getarea
  else
    info[:country] = getstring(byte)
    info[:area] = getarea
  end

  info[:country] = encoding_convert(info[:country])
  info[:area] = encoding_convert(info[:area])

  log "country is #{info[:country]}"
  log "area is #{info[:area]}"

  if info[:country] == ' CZ88.NET' || info[:country] == '纯真网络'
    info[:country] = 'Unknown'
  end

  info[:area] = '' if info[:area] == ' CZ88.NET'

  info
end

#resolve(ip) ⇒ Object

return: <Hash> result result 输入的ip result 国家 如 中国 result 省份信息 如 河北省 result 市区 如 邢台市 result 郡县 如 威县 result 运营商 如 联通 result 最完整的信息 如 中国河北省邢台市威县新科网吧(北外街) result 解析之前的原始信息 result 解析之前的原始信息



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/ip_locator_cn/qqwry.rb', line 32

def resolve(ip)
  location = location_from_ip(ip)
  extract_location(location[:country]).tap do |result|
    result[:ip] = ip
    result[:country] ||= ''
    result[:province] ||= ''
    result[:city] ||= ''
    result[:county] ||= ''
    result[:isp] = get_isp(location[:area]) || ''
    result[:area] = [
      result[:country],
      result[:province],
      result[:city],
      result[:county],
      location[:area]
    ].join
    result[:origin_country] = location[:country]
    result[:origin_area] = location[:area]
  end
end