base_scraper_service 0.1.0
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/lib/base_scraper_service/agent_object.rb +28 -0
- data/lib/base_scraper_service/base.rb +94 -0
- data/lib/base_scraper_service/base_scraper.rb +90 -0
- data/lib/base_scraper_service/location_service.rb +348 -0
- data/lib/base_scraper_service/user_agent.rb +6946 -0
- data/lib/base_scraper_service.rb +4 -0
- metadata +257 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 69eb49ba30aa10adba230399397bc900df7f46b10da8c5ef7e02d00743fd7407
|
4
|
+
data.tar.gz: a7534672884d78323aa41838e1048c1cfff7a59d19a7f633034eaf9e8dc680d0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b8957504e31a3a5519538bd7b5fecdb7837f502b5cdccea51c59d3c585bb26f5dc7642449808e3913d361ee778af74e06708dc54b5ed771cb8839434f1e7834c
|
7
|
+
data.tar.gz: 6227de3f572c770425145ef074dbbdbec0cebf8cd0c7f95ba4cc1d00a0ef24e60534e3537d5ae305d1a6af41688304b55fea00b4bd78b6a3b0e951ee5f28dea4
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require_relative 'user_agent'
|
2
|
+
require "mechanize"
|
3
|
+
require "nokogiri"
|
4
|
+
|
5
|
+
module BaseScraper
|
6
|
+
class Service
|
7
|
+
def agent_object
|
8
|
+
agent = Mechanize.new
|
9
|
+
agent.read_timeout = 5
|
10
|
+
agent.open_timeout = 8
|
11
|
+
agent.keep_alive = false
|
12
|
+
agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
13
|
+
agent.user_agent = UserAgent.random
|
14
|
+
agent.idle_timeout = 5
|
15
|
+
agent.pluggable_parser.default = Mechanize::Page
|
16
|
+
|
17
|
+
# Prevent from <Mechanize::Error: unsupported content-encoding: UTF-8>
|
18
|
+
content_encoding_hooks_func = lambda do |a, uri, resp, body_io|
|
19
|
+
if resp['Content-Encoding'].to_s == 'UTF-8'
|
20
|
+
resp['Content-Encoding'] = 'gzip'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
agent.content_encoding_hooks << content_encoding_hooks_func
|
24
|
+
|
25
|
+
agent
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'dotenv'
|
3
|
+
require "./#{ENV['SERVICE_NAME']}_offers_service"
|
4
|
+
|
5
|
+
configure { set :server, :puma }
|
6
|
+
|
7
|
+
class Base < Sinatra::Base
|
8
|
+
|
9
|
+
get "/#{ENV['SERVICE_NAME']}/isbn_offers" do
|
10
|
+
isbn = params[:isbn]
|
11
|
+
uuid = SecureRandom.uuid
|
12
|
+
|
13
|
+
@res = {
|
14
|
+
isbn: isbn,
|
15
|
+
uuid: uuid,
|
16
|
+
item_condition: params[:item_condition],
|
17
|
+
ship_type: params[:ship_type]
|
18
|
+
}
|
19
|
+
|
20
|
+
if valid_params?
|
21
|
+
service_response = Object.const_get(get_service_name).new(isbn, uuid).scrape_offers
|
22
|
+
offers = service_response[:offers]
|
23
|
+
|
24
|
+
offers = filter_offers(offers)
|
25
|
+
offers.sort_by! { |offer| offer[:total_price] }
|
26
|
+
offers_count = offers.count
|
27
|
+
|
28
|
+
@res[:status] = service_response[:status]
|
29
|
+
@res[:short_message] = service_response[:short_message]
|
30
|
+
@res[:long_message] = service_response[:long_message]
|
31
|
+
if @res[:status] == 200
|
32
|
+
@res[:offers_count] = offers.count
|
33
|
+
@res[:data] = { offers: offers }
|
34
|
+
end
|
35
|
+
else
|
36
|
+
@res[:status] = 400
|
37
|
+
@res[:short_message] = 'error'
|
38
|
+
end
|
39
|
+
|
40
|
+
halt @res[:status], @res.to_json
|
41
|
+
end
|
42
|
+
|
43
|
+
not_found do
|
44
|
+
send_file( 'public/404.html', { status: 404 })
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_service_name
|
48
|
+
ENV['SERVICE_NAME'].capitalize + 'OffersService'
|
49
|
+
end
|
50
|
+
|
51
|
+
def send_sinatra_file(path)
|
52
|
+
file_path = File.join(File.dirname(__FILE__), 'public', path)
|
53
|
+
file_path = File.join(file_path, 'index.html') unless file_path =~ /\.[a-z]+$/i and !File.directory?(file_path)
|
54
|
+
File.exist?(file_path) ? send_file(file_path) : not_found
|
55
|
+
end
|
56
|
+
|
57
|
+
def filter_offers(offers)
|
58
|
+
offers = offers.select{ |offer| offer[:Item_Condition].downcase == params[:item_condition].downcase} if params[:item_condition].present?
|
59
|
+
offers = offers.select{ |offer| offer[:ship_type].downcase == params[:ship_type].downcase} if params[:ship_type].present?
|
60
|
+
|
61
|
+
offers
|
62
|
+
end
|
63
|
+
|
64
|
+
def constantize(lower_case_string)
|
65
|
+
"#{lower_case_string.split('_').collect(&:capitalize).join + 'OffersService'}".constantize
|
66
|
+
end
|
67
|
+
|
68
|
+
def valid_params?
|
69
|
+
valid_isbn?(params[:isbn]) &&
|
70
|
+
valid_book_condition?(params[:item_condition].to_s) &&
|
71
|
+
valid_ship_type?(params[:ship_type].to_s)
|
72
|
+
end
|
73
|
+
|
74
|
+
def valid_isbn?(isbn)
|
75
|
+
return true if StdNum::ISBN.valid?(isbn) && [10, 13].include?(isbn.size)
|
76
|
+
|
77
|
+
@res[:long_message] = 'invalid isbn'
|
78
|
+
false
|
79
|
+
end
|
80
|
+
|
81
|
+
def valid_book_condition?(item_condition)
|
82
|
+
return true if ['', 'used', 'new'].include?(item_condition.downcase)
|
83
|
+
|
84
|
+
@res[:long_message] = 'invalid item condition'
|
85
|
+
false
|
86
|
+
end
|
87
|
+
|
88
|
+
def valid_ship_type?(ship_type)
|
89
|
+
return true if ['', 'standard', 'expedited'].include?(ship_type.downcase)
|
90
|
+
|
91
|
+
@res[:long_message] = 'invalid ship type'
|
92
|
+
false
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'mechanize'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'thread'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'logger'
|
6
|
+
require "dotenv"
|
7
|
+
require 'csv'
|
8
|
+
require 'date'
|
9
|
+
require 'active_support/time'
|
10
|
+
require 'library_stdnums'
|
11
|
+
require 'base_scraper_service'
|
12
|
+
require_relative 'user_agent'
|
13
|
+
require_relative 'agent_object'
|
14
|
+
|
15
|
+
module BaseScraper
|
16
|
+
class Service
|
17
|
+
def send_request(agent, uri, params = nil, headers = {}, _optoins = {})
|
18
|
+
tries = 0
|
19
|
+
max_tries = 5
|
20
|
+
page = nil
|
21
|
+
|
22
|
+
refresh_agent(agent)
|
23
|
+
change_proxy(agent)
|
24
|
+
begin
|
25
|
+
page = params.nil? ? agent.get(uri, [], nil, headers) : agent.post(uri, params, headers)
|
26
|
+
|
27
|
+
rescue Mechanize::ResponseCodeError => e
|
28
|
+
change_proxy(agent)
|
29
|
+
|
30
|
+
tries += 1
|
31
|
+
|
32
|
+
agent.set_proxy(ENV["LPM_SERVER_URL"], ENV["LPM_SERVER_PORT"]) if tries >= 4
|
33
|
+
|
34
|
+
retry if tries < max_tries
|
35
|
+
rescue Exception => e
|
36
|
+
refresh_agent(agent)
|
37
|
+
change_proxy(agent)
|
38
|
+
|
39
|
+
tries += 1
|
40
|
+
|
41
|
+
agent.set_proxy(ENV["LPM_SERVER_URL"], ENV["LPM_SERVER_PORT"]) if tries >= 4
|
42
|
+
|
43
|
+
retry if tries < max_tries
|
44
|
+
puts "Message: #{e.message} from #{uri}, proxy: #{agent.proxy_addr}" if logs_enable?
|
45
|
+
end
|
46
|
+
|
47
|
+
page
|
48
|
+
end
|
49
|
+
|
50
|
+
def format_price(price)
|
51
|
+
return unless price.present?
|
52
|
+
price.to_s.strip.gsub("$", "").strip.to_f
|
53
|
+
end
|
54
|
+
|
55
|
+
def format_isbn(isbn)
|
56
|
+
StdNum::ISBN.convert_to_13(isbn)
|
57
|
+
end
|
58
|
+
|
59
|
+
def with_exception(long_message: "", status: 500, short_message: "exception")
|
60
|
+
return { offers: [], short_message: short_message, long_message: long_message, status: status }
|
61
|
+
end
|
62
|
+
|
63
|
+
def logs_enable?
|
64
|
+
ENV["ENABLE_LOGS"] == "true"
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def refresh_agent(agent)
|
70
|
+
agent.cookie_jar.clear!
|
71
|
+
agent.history.clear
|
72
|
+
agent.user_agent = UserAgent.random
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_proxy_index
|
76
|
+
(0..(@proxy_array.count - 1)).to_a.sample
|
77
|
+
end
|
78
|
+
|
79
|
+
def change_proxy(agent)
|
80
|
+
if @proxy_array.count > 0
|
81
|
+
cur_proxy_index = get_proxy_index
|
82
|
+
if @proxy_array[cur_proxy_index].present?
|
83
|
+
agent.set_proxy(@proxy_array[cur_proxy_index][0], @proxy_array[cur_proxy_index][1])
|
84
|
+
end
|
85
|
+
else
|
86
|
+
agent.set_proxy(ENV['LPM_SERVER_URL'], ENV['LPM_SERVER_PORT'])
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,348 @@
|
|
1
|
+
module BaseScraper
|
2
|
+
class Service
|
3
|
+
class LocationService
|
4
|
+
def initialize(address)
|
5
|
+
@address = address.to_s.gsub('.', '')
|
6
|
+
end
|
7
|
+
|
8
|
+
def extract_state
|
9
|
+
# 1- return state abbreviation if matched with state abbreviations
|
10
|
+
# 2- return state abbreviation if matched with state name
|
11
|
+
# 3- otherwise return empty string
|
12
|
+
state = us_states_hash.keys.select { |state_abbreviation| @address.upcase.include?(state_abbreviation) }.first
|
13
|
+
return state if state.present? && @address.length != 3
|
14
|
+
state = us_states_hash.select { |_, state| @address.include?(state) }.first&.first
|
15
|
+
|
16
|
+
return state.to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
def extract_country
|
20
|
+
# 1- return country abbreviation if matched with country abbreviations
|
21
|
+
# 2- return country abbreviation if matched with country name
|
22
|
+
# 3- return USA if address contains a USA state
|
23
|
+
# 4- otherwise return empty string
|
24
|
+
country = countries_hash.keys.select { |country_abbreviation| @address.include?(country_abbreviation) }.first
|
25
|
+
puts country, @address
|
26
|
+
return country if country.present?
|
27
|
+
country = countries_hash.select { |_, country_name| @address.include?(country_name) }.first&.first
|
28
|
+
return country if country.present?
|
29
|
+
|
30
|
+
return 'USA' if extract_state.present?
|
31
|
+
|
32
|
+
return country.to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def us_states_hash
|
38
|
+
{
|
39
|
+
'AL' => 'Alabama',
|
40
|
+
'AK' => 'Alaska',
|
41
|
+
'AZ' => 'Arizona',
|
42
|
+
'AR' => 'Arkansas',
|
43
|
+
'CA' => 'California',
|
44
|
+
'CO' => 'Colorado',
|
45
|
+
'CT' => 'Connecticut',
|
46
|
+
'DE' => 'Delaware',
|
47
|
+
'DC' => 'District Of Columbia',
|
48
|
+
'FL' => 'Florida',
|
49
|
+
'GA' => 'Georgia',
|
50
|
+
'HI' => 'Hawaii',
|
51
|
+
'ID' => 'Idaho',
|
52
|
+
'IL' => 'Illinois',
|
53
|
+
'IN' => 'Indiana',
|
54
|
+
'IA' => 'Iowa',
|
55
|
+
'KS' => 'Kansas',
|
56
|
+
'KY' => 'Kentucky',
|
57
|
+
'LA' => 'Louisiana',
|
58
|
+
'ME' => 'Maine',
|
59
|
+
'MD' => 'Maryland',
|
60
|
+
'MA' => 'Massachusetts',
|
61
|
+
'MI' => 'Michigan',
|
62
|
+
'MN' => 'Minnesota',
|
63
|
+
'MS' => 'Mississippi',
|
64
|
+
'MO' => 'Missouri',
|
65
|
+
'MT' => 'Montana',
|
66
|
+
'NE' => 'Nebraska',
|
67
|
+
'NV' => 'Nevada',
|
68
|
+
'NH' => 'New Hampshire',
|
69
|
+
'NJ' => 'New Jersey',
|
70
|
+
'NM' => 'New Mexico',
|
71
|
+
'NY' => 'New York',
|
72
|
+
'NC' => 'North Carolina',
|
73
|
+
'ND' => 'North Dakota',
|
74
|
+
'OH' => 'Ohio',
|
75
|
+
'OK' => 'Oklahoma',
|
76
|
+
'OR' => 'Oregon',
|
77
|
+
'PA' => 'Pennsylvania',
|
78
|
+
'RI' => 'Rhode Island',
|
79
|
+
'SC' => 'South Carolina',
|
80
|
+
'SD' => 'South Dakota',
|
81
|
+
'TN' => 'Tennessee',
|
82
|
+
'TX' => 'Texas',
|
83
|
+
'UT' => 'Utah',
|
84
|
+
'VT' => 'Vermont',
|
85
|
+
'VA' => 'Virginia',
|
86
|
+
'WA' => 'Washington',
|
87
|
+
'WV' => 'West Virginia',
|
88
|
+
'WI' => 'Wisconsin',
|
89
|
+
'WY' => 'Wyoming'
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def countries_hash
|
94
|
+
{
|
95
|
+
'AFG' => 'Afghanistan',
|
96
|
+
'ALB' => 'Albania',
|
97
|
+
'DZA' => 'Algeria',
|
98
|
+
'ASM' => 'American Samoa',
|
99
|
+
'AND' => 'Andorra',
|
100
|
+
'AGO' => 'Angola',
|
101
|
+
'AIA' => 'Anguilla',
|
102
|
+
'ATA' => 'Antarctica',
|
103
|
+
'ATG' => 'Antigua and Barbuda',
|
104
|
+
'ARG' => 'Argentina',
|
105
|
+
'ARM' => 'Armenia',
|
106
|
+
'ABW' => 'Aruba',
|
107
|
+
'AUS' => 'Australia',
|
108
|
+
'AUT' => 'Austria',
|
109
|
+
'AZE' => 'Azerbaijan',
|
110
|
+
'BHS' => 'Bahamas',
|
111
|
+
'BHR' => 'Bahrain',
|
112
|
+
'BGD' => 'Bangladesh',
|
113
|
+
'BRB' => 'Barbados',
|
114
|
+
'BLR' => 'Belarus',
|
115
|
+
'BEL' => 'Belgium',
|
116
|
+
'BLZ' => 'Belize',
|
117
|
+
'BEN' => 'Benin',
|
118
|
+
'BMU' => 'Bermuda',
|
119
|
+
'BTN' => 'Bhutan',
|
120
|
+
'BOL' => 'Bolivia',
|
121
|
+
'BES' => 'Bonaire, Sint Eustatius and Saba',
|
122
|
+
'BIH' => 'Bosnia and Herzegovina',
|
123
|
+
'BWA' => 'Botswana',
|
124
|
+
'BVT' => 'Bouvet Island',
|
125
|
+
'BRA' => 'Brazil',
|
126
|
+
'IOT' => 'British Indian Ocean Territory',
|
127
|
+
'BRN' => 'Brunei Darussalam',
|
128
|
+
'BGR' => 'Bulgaria',
|
129
|
+
'BFA' => 'Burkina Faso',
|
130
|
+
'BDI' => 'Burundi',
|
131
|
+
'CPV' => 'Cabo Verde',
|
132
|
+
'KHM' => 'Cambodia',
|
133
|
+
'CMR' => 'Cameroon',
|
134
|
+
'CAN' => 'Canada',
|
135
|
+
'CYM' => 'Cayman Islands',
|
136
|
+
'CAF' => 'Central African Republic',
|
137
|
+
'TCD' => 'Chad',
|
138
|
+
'CHL' => 'Chile',
|
139
|
+
'CHN' => 'China',
|
140
|
+
'CXR' => 'Christmas Island',
|
141
|
+
'CCK' => 'Cocos (Keeling) Islands',
|
142
|
+
'COL' => 'Colombia',
|
143
|
+
'COM' => 'Comoros',
|
144
|
+
'COD' => 'Congo',
|
145
|
+
'COG' => 'Congo',
|
146
|
+
'COK' => 'Cook Islands',
|
147
|
+
'CRI' => 'Costa Rica',
|
148
|
+
'HRV' => 'Croatia',
|
149
|
+
'CUB' => 'Cuba',
|
150
|
+
'CUW' => 'Curaçao',
|
151
|
+
'CYP' => 'Cyprus',
|
152
|
+
'CZE' => 'Czechia',
|
153
|
+
'CIV' => "Côte d'Ivoire",
|
154
|
+
'DNK' => 'Denmark',
|
155
|
+
'DJI' => 'Djibouti',
|
156
|
+
'DMA' => 'Dominica',
|
157
|
+
'DOM' => 'Dominican Republic',
|
158
|
+
'ECU' => 'Ecuador',
|
159
|
+
'EGY' => 'Egypt',
|
160
|
+
'SLV' => 'El Salvador',
|
161
|
+
'GNQ' => 'Equatorial Guinea',
|
162
|
+
'ERI' => 'Eritrea',
|
163
|
+
'EST' => 'Estonia',
|
164
|
+
'SWZ' => 'Eswatini',
|
165
|
+
'ETH' => 'Ethiopia',
|
166
|
+
'FLK' => 'Falkland Islands',
|
167
|
+
'FRO' => 'Faroe Islands',
|
168
|
+
'FJI' => 'Fiji',
|
169
|
+
'FIN' => 'Finland',
|
170
|
+
'FRA' => 'France',
|
171
|
+
'GUF' => 'French Guiana',
|
172
|
+
'PYF' => 'French Polynesia',
|
173
|
+
'ATF' => 'French Southern Territories',
|
174
|
+
'GAB' => 'Gabon',
|
175
|
+
'GMB' => 'Gambia',
|
176
|
+
'GEO' => 'Georgia',
|
177
|
+
'DEU' => 'Germany',
|
178
|
+
'GHA' => 'Ghana',
|
179
|
+
'GIB' => 'Gibraltar',
|
180
|
+
'GRC' => 'Greece',
|
181
|
+
'GRL' => 'Greenland',
|
182
|
+
'GRD' => 'Grenada',
|
183
|
+
'GLP' => 'Guadeloupe',
|
184
|
+
'GUM' => 'Guam',
|
185
|
+
'GTM' => 'Guatemala',
|
186
|
+
'GGY' => 'Guernsey',
|
187
|
+
'GIN' => 'Guinea',
|
188
|
+
'GNB' => 'Guinea-Bissau',
|
189
|
+
'GUY' => 'Guyana',
|
190
|
+
'HTI' => 'Haiti',
|
191
|
+
'HMD' => 'Heard Island and McDonald Islands',
|
192
|
+
'VAT' => 'Holy See',
|
193
|
+
'HND' => 'Honduras',
|
194
|
+
'HKG' => 'Hong Kong',
|
195
|
+
'HUN' => 'Hungary',
|
196
|
+
'ISL' => 'Iceland',
|
197
|
+
'IND' => 'India',
|
198
|
+
'IDN' => 'Indonesia',
|
199
|
+
'IRN' => 'Iran',
|
200
|
+
'IRQ' => 'Iraq',
|
201
|
+
'IRL' => 'Ireland',
|
202
|
+
'IMN' => 'Isle of Man',
|
203
|
+
'ISR' => 'Israel',
|
204
|
+
'ITA' => 'Italy',
|
205
|
+
'JAM' => 'Jamaica',
|
206
|
+
'JPN' => 'Japan',
|
207
|
+
'JEY' => 'Jersey',
|
208
|
+
'JOR' => 'Jordan',
|
209
|
+
'KAZ' => 'Kazakhstan',
|
210
|
+
'KEN' => 'Kenya',
|
211
|
+
'KIR' => 'Kiribati',
|
212
|
+
'PRK' => "Korea",
|
213
|
+
'KOR' => 'Korea',
|
214
|
+
'KWT' => 'Kuwait',
|
215
|
+
'KGZ' => 'Kyrgyzstan',
|
216
|
+
'LAO' => "Lao People's Democratic Republic",
|
217
|
+
'LVA' => 'Latvia',
|
218
|
+
'LBN' => 'Lebanon',
|
219
|
+
'LSO' => 'Lesotho',
|
220
|
+
'LBR' => 'Liberia',
|
221
|
+
'LBY' => 'Libya',
|
222
|
+
'LIE' => 'Liechtenstein',
|
223
|
+
'LTU' => 'Lithuania',
|
224
|
+
'LUX' => 'Luxembourg',
|
225
|
+
'MAC' => 'Macao',
|
226
|
+
'MDG' => 'Madagascar',
|
227
|
+
'MWI' => 'Malawi',
|
228
|
+
'MYS' => 'Malaysia',
|
229
|
+
'MDV' => 'Maldives',
|
230
|
+
'MLI' => 'Mali',
|
231
|
+
'MLT' => 'Malta',
|
232
|
+
'MHL' => 'Marshall Islands',
|
233
|
+
'MTQ' => 'Martinique',
|
234
|
+
'MRT' => 'Mauritania',
|
235
|
+
'MUS' => 'Mauritius',
|
236
|
+
'MYT' => 'Mayotte',
|
237
|
+
'MEX' => 'Mexico',
|
238
|
+
'FSM' => 'Micronesia',
|
239
|
+
'MDA' => 'Moldova',
|
240
|
+
'MCO' => 'Monaco',
|
241
|
+
'MNG' => 'Mongolia',
|
242
|
+
'MNE' => 'Montenegro',
|
243
|
+
'MSR' => 'Montserrat',
|
244
|
+
'MAR' => 'Morocco',
|
245
|
+
'MOZ' => 'Mozambique',
|
246
|
+
'MMR' => 'Myanmar',
|
247
|
+
'NAM' => 'Namibia',
|
248
|
+
'NRU' => 'Nauru',
|
249
|
+
'NPL' => 'Nepal',
|
250
|
+
'NLD' => 'Netherlands',
|
251
|
+
'NCL' => 'New Caledonia',
|
252
|
+
'NZL' => 'New Zealand',
|
253
|
+
'NIC' => 'Nicaragua',
|
254
|
+
'NER' => 'Niger',
|
255
|
+
'NGA' => 'Nigeria',
|
256
|
+
'NIU' => 'Niue',
|
257
|
+
'NFK' => 'Norfolk Island',
|
258
|
+
'MNP' => 'Northern Mariana Islands',
|
259
|
+
'NOR' => 'Norway',
|
260
|
+
'OMN' => 'Oman',
|
261
|
+
'PAK' => 'Pakistan',
|
262
|
+
'PLW' => 'Palau',
|
263
|
+
'PSE' => 'Palestine, State of',
|
264
|
+
'PAN' => 'Panama',
|
265
|
+
'PNG' => 'Papua New Guinea',
|
266
|
+
'PRY' => 'Paraguay',
|
267
|
+
'PER' => 'Peru',
|
268
|
+
'PHL' => 'Philippines',
|
269
|
+
'PCN' => 'Pitcairn',
|
270
|
+
'POL' => 'Poland',
|
271
|
+
'PRT' => 'Portugal',
|
272
|
+
'PRI' => 'Puerto Rico',
|
273
|
+
'QAT' => 'Qatar',
|
274
|
+
'MKD' => 'Republic of North Macedonia',
|
275
|
+
'ROU' => 'Romania',
|
276
|
+
'RUS' => 'Russian Federation',
|
277
|
+
'RWA' => 'Rwanda',
|
278
|
+
'REU' => 'Réunion',
|
279
|
+
'BLM' => 'Saint Barthélemy',
|
280
|
+
'SHN' => 'Saint Helena, Ascension and Tristan da Cunha',
|
281
|
+
'KNA' => 'Saint Kitts and Nevis',
|
282
|
+
'LCA' => 'Saint Lucia',
|
283
|
+
'MAF' => 'Saint Martin',
|
284
|
+
'SPM' => 'Saint Pierre and Miquelon',
|
285
|
+
'VCT' => 'Saint Vincent and Grenadines',
|
286
|
+
'WSM' => 'Samoa',
|
287
|
+
'SMR' => 'San Marino',
|
288
|
+
'STP' => 'Sao Tome and Principe',
|
289
|
+
'SAU' => 'Saudi Arabia',
|
290
|
+
'SEN' => 'Senegal',
|
291
|
+
'SRB' => 'Serbia',
|
292
|
+
'SYC' => 'Seychelles',
|
293
|
+
'SLE' => 'Sierra Leone',
|
294
|
+
'SGP' => 'Singapore',
|
295
|
+
'SXM' => 'Sint Maarten',
|
296
|
+
'SVK' => 'Slovakia',
|
297
|
+
'SVN' => 'Slovenia',
|
298
|
+
'SLB' => 'Solomon Islands',
|
299
|
+
'SOM' => 'Somalia',
|
300
|
+
'ZAF' => 'South Africa',
|
301
|
+
'SGS' => 'South Georgia and South Sandwich Islands',
|
302
|
+
'SSD' => 'South Sudan',
|
303
|
+
'ESP' => 'Spain',
|
304
|
+
'LKA' => 'Sri Lanka',
|
305
|
+
'SDN' => 'Sudan',
|
306
|
+
'SUR' => 'Suriname',
|
307
|
+
'SJM' => 'Svalbard and Jan Mayen',
|
308
|
+
'SWE' => 'Sweden',
|
309
|
+
'CHE' => 'Switzerland',
|
310
|
+
'SYR' => 'Syrian Arab Republic',
|
311
|
+
'TWN' => 'Taiwan',
|
312
|
+
'TJK' => 'Tajikistan',
|
313
|
+
'TZA' => 'Tanzania, United Republic of',
|
314
|
+
'THA' => 'Thailand',
|
315
|
+
'TLS' => 'Timor-Leste',
|
316
|
+
'TGO' => 'Togo',
|
317
|
+
'TKL' => 'Tokelau',
|
318
|
+
'TON' => 'Tonga',
|
319
|
+
'TTO' => 'Trinidad and Tobago',
|
320
|
+
'TUN' => 'Tunisia',
|
321
|
+
'TUR' => 'Turkey',
|
322
|
+
'TKM' => 'Turkmenistan',
|
323
|
+
'TCA' => 'Turks and Caicos Islands',
|
324
|
+
'TUV' => 'Tuvalu',
|
325
|
+
'UGA' => 'Uganda',
|
326
|
+
'UKR' => 'Ukraine',
|
327
|
+
'ARE' => 'United Arab Emirates',
|
328
|
+
'GBR' => 'United Kingdom of Great Britain and Northern Ireland',
|
329
|
+
'UMI' => 'United States Minor Outlying Islands',
|
330
|
+
'USA' => 'United States of America',
|
331
|
+
'URY' => 'Uruguay',
|
332
|
+
'UZB' => 'Uzbekistan',
|
333
|
+
'VUT' => 'Vanuatu',
|
334
|
+
'VEN' => 'Venezuela',
|
335
|
+
'VNM' => 'Viet Nam',
|
336
|
+
'VGB' => 'Virgin Islands',
|
337
|
+
'VIR' => 'Virgin Islands',
|
338
|
+
'WLF' => 'Wallis and Futuna',
|
339
|
+
'ESH' => 'Western Sahara',
|
340
|
+
'YEM' => 'Yemen',
|
341
|
+
'ZMB' => 'Zambia',
|
342
|
+
'ZWE' => 'Zimbabwe',
|
343
|
+
'ALA' => 'Åland Islands'
|
344
|
+
}
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|