Module: MangoChinaCity

Extended by:
Configure
Defined in:
lib/mango_china_city.rb,
lib/mango_china_city/version.rb,
lib/mango_china_city/configure.rb,
lib/generators/mango_china_city/install_generator.rb

Defined Under Namespace

Modules: Configure, Generators

Constant Summary collapse

VERSION =
"0.1.3"

Instance Attribute Summary

Attributes included from Configure

#redis

Class Method Summary collapse

Methods included from Configure

configure

Class Method Details

.build_cacheObject

获取数据库地区并缓存到redis



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/mango_china_city.rb', line 118

def build_cache
  provinces_ = Province.not_deleted.to_a
  cities_ = City.not_deleted.to_a
  districts_ = District.not_deleted.to_a

  cities = {}
  districts = {}
  redis.set("province_cache", provinces_.map{|e| { name: e.name, code: e.code }}.to_json)

  provinces_.each do |province|
    puts "正在缓存\e[0;32;49m<#{province.name}>\e[0m所有数据..."
    cities.merge!( { province.code => cities_.select{|e| e.province_id == province.id}.map{|e| { name: e.name, code: e.code }} } )

    cities_.each do |city|
      districts.merge!( { city.code => districts_.select{|e| e.city_id == city.id }.map{|e| { name: e.name, code: e.code }} } )
    end
    puts "缓存\e[0;32;49m<#{province.name}>\e[0m完成!\n\n"
  end
  redis.set("city_cache", cities.to_json)
  redis.set("district_cache", districts.to_json)
end

.get(code) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/mango_china_city.rb', line 101

def get(code)
  code = code.to_s
  result = nil
  if redis.present? && redis.keys.include?("province_cache")
    result = (JSON.parse( redis.get("province_cache") ).find{|e| e["code"] == code}["name"] rescue nil)
    result = (JSON.parse( redis.get("city_cache") ).values.flatten.find{|e| e["code"] == code}["name"] rescue nil) if result.nil?
    result = (JSON.parse( redis.get("district_cache") ).values.flatten.find{|e| e["code"] == code}["name"] rescue nil ) if result.nil?
  else
    result = Province.find_by(code: code).try(:name)
    result = City.find_by(code: code).try(:name) if result.nil?
    result = District.find_by(code: code).try(:name) if result.nil?
  end

  return result.to_s
end

.import_data(json) ⇒ Object

省市区信息写入数据库



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
# File 'lib/mango_china_city.rb', line 58

def import_data(json)
  data_province = Province.all.to_a
  data_city = City.all.to_a
  data_district = District.all.to_a

  Province.transaction do
    json[:province].each do |province|
      province_ = Province.find_or_create_by(name: province[:name], code: province[:code])
      data_province.delete_if{|e| e.code == province_.code}

      province[:city].each do |city|
        city_ = City.find_or_create_by(province: province_, name: city[:name], code: city[:code])
        data_city.delete_if{|e| e.code == city_.code }

        city[:district].each do |district|
          district_ = District.find_or_create_by(province: province_, city: city_, name: district[:name], code: district[:code])
          data_district.delete_if{|e| e.code == district_.code }
        end
      end
    end

    # 软删除更新地区
    [data_province, data_city, data_district].flatten.each{|e| e.destroy}

    # 重建缓存
    build_cache if redis.present?
  end
end

.list(code = nil) ⇒ Object

获取省市区



88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/mango_china_city.rb', line 88

def list(code = nil)
  code = code.to_s if code.present?
  if redis.present? && redis.keys.include?("province_cache")
    return JSON.parse( redis.get("province_cache") ).each(&:deep_symbolize_keys!)  if code.nil?
    return JSON.parse( redis.get("city_cache") )[code].each(&:deep_symbolize_keys!) if code.size == 2
    return JSON.parse( redis.get("district_cache") )[code].each(&:deep_symbolize_keys!) if code.size != 2
  else # 数据库查询
    return Province.all.map{|e| {name: e.name, code: e.code}}  if code.nil?
    return City.where(province: Province.find_by(code: code)).map{|e| { name: e.name, code: e.code } } if code.size == 2
    return District.where(city: City.find_by(code: code)).map{|e| { name: e.name, code: e.code }} if code.size != 2
  end
end

.sync_data(gen_file = false) ⇒ Object

国家统计局同步数据



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/mango_china_city.rb', line 12

def sync_data(gen_file=false)
  json = { province: [] }
  base_url = "http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2020/"

  province_res = convert_utf8(
    (RestClient::Request.execute(method: :get, url: "#{base_url}index.html", timeout: 1).body rescue retry)
  )
  province_res.match(/<td>.+<\/td>/).to_s.gsub(/<br\/>|<\/td>|<td>/,'').split("</a>").each do |province|
    # p_url省详情的页面地址, code 省code
    p_url, code = province.match(/(\d+).html/).to_a
    province_ = { name: province.match(/[\u4e00-\u9fa5]+/).to_s, code: "#{code}", city: []}
    puts "正在同步#{province.match(/[\u4e00-\u9fa5]+/).to_s}"
    # 获取省下的市
    city_res = convert_utf8(
      (RestClient::Request.execute(method: :get, url: "#{base_url}#{p_url}", timeout: 1).body rescue retry)
    )

    city_res.gsub(/\r|\n/,'').match(/<a href=.+<\/a>/).to_s.split("</tr>").each do |city|
      c_url, c_code = city.match(/(\d+).html/).to_a
      city_ = { name: city.match(/[\u4e00-\u9fa5]+/).to_s, code: "#{c_code}", district: [] }
      puts "正在同步#{province.match(/[\u4e00-\u9fa5]+/).to_s}::#{city.match(/[\u4e00-\u9fa5]+/).to_s}"
      # 获取市下的区
      district_res = convert_utf8(
        (RestClient::Request.execute(method: :get, url: "#{base_url}#{code}/#{c_url}", timeout: 1).body rescue retry)
      )
      district_res.gsub(/\r|\n/,'').match(/<a href=.+<\/a>/).to_s.split("</tr>").each do |district|
        d_url, d_code = district.match(/(\d+).html/).to_a
        city_[:district] << { name: district.match(/[\u4e00-\u9fa5]+/).to_s, code: d_code }
        puts "正在同步#{province.match(/[\u4e00-\u9fa5]+/).to_s}::#{city.match(/[\u4e00-\u9fa5]+/).to_s}::#{district.match(/[\u4e00-\u9fa5]+/).to_s}"
      end
      province_[:city] << city_
    end

    json[:province] << province_
  end

  # 生成文件
  File.open("#{Rails.root}/db/areas.json", 'w+') do |f|
    f.write(json.to_json)
  end if gen_file
  puts '生在写入数据库...'
  import_data(json)
  puts '写入完成,同步数据结束!'
end