base_scraper_service 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|