101 lines
3.3 KiB
Python
101 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Flatten the REST Countries v3.1 dataset into a clean, flat table.
|
|
|
|
Usage:
|
|
python3 extract_countries.py <source_json> <output_csv>
|
|
|
|
Source (raw, from the REST Countries repository):
|
|
https://raw.githubusercontent.com/restcountries/restcountries/master/src/main/resources/countriesV3.1.json
|
|
The JSON is an array of 250 country records; this script flattens every record
|
|
to one CSV row with the fixed 14-column contract below.
|
|
|
|
Columns (order):
|
|
name_common | name_official | alpha2 | alpha3 | numeric |
|
|
region | subregion | capital | population | area_km2 |
|
|
currencies | languages | tlds | flag
|
|
"""
|
|
import csv
|
|
import json
|
|
import sys
|
|
|
|
|
|
def as_text(value):
|
|
"""Empty string for None/empty, plain str otherwise."""
|
|
if value is None or value == '':
|
|
return ''
|
|
return str(value)
|
|
|
|
|
|
def list_join(value):
|
|
"""Join a list of strings with ' | '; empty string for None."""
|
|
if value is None:
|
|
return ''
|
|
return ' | '.join(str(item) for item in value)
|
|
|
|
|
|
def currency_codes(currencies):
|
|
if not isinstance(currencies, dict):
|
|
return ''
|
|
return ' | '.join(sorted(currencies.keys()))
|
|
|
|
|
|
def language_codes(languages):
|
|
if not isinstance(languages, dict):
|
|
return ''
|
|
return ' | '.join(sorted(languages.keys()))
|
|
|
|
|
|
def flatten(record):
|
|
name = record.get('name') or {}
|
|
return [
|
|
as_text(name.get('common')), # name_common
|
|
as_text(name.get('official')), # name_official
|
|
as_text(record.get('cca2')), # alpha2
|
|
as_text(record.get('cca3')), # alpha3
|
|
as_text(record.get('ccn3')), # numeric
|
|
as_text(record.get('region')), # region
|
|
as_text(record.get('subregion')), # subregion
|
|
list_join(record.get('capital')), # capital
|
|
as_text(record.get('population')), # population
|
|
as_text(record.get('area')), # area_km2
|
|
currency_codes(record.get('currencies')), # currencies
|
|
language_codes(record.get('languages')), # languages
|
|
list_join(record.get('tld')), # tlds
|
|
as_text(record.get('flag')), # flag
|
|
]
|
|
|
|
|
|
HEADERS = [
|
|
'name_common', 'name_official', 'alpha2', 'alpha3', 'numeric',
|
|
'region', 'subregion', 'capital', 'population', 'area_km2',
|
|
'currencies', 'languages', 'tlds', 'flag',
|
|
]
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) != 3:
|
|
sys.stderr.write('usage: extract_countries.py <source_json> <output_csv>\n')
|
|
return 2
|
|
source_path, out_path = sys.argv[1], sys.argv[2]
|
|
try:
|
|
with open(source_path, encoding='utf-8') as fh:
|
|
records = json.load(fh)
|
|
except (OSError, ValueError) as exc:
|
|
sys.stderr.write('cannot read source %s: %s\n' % (source_path, exc))
|
|
return 1
|
|
if not isinstance(records, list):
|
|
sys.stderr.write('source JSON is not a list\n')
|
|
return 1
|
|
with open(out_path, 'w', encoding='utf-8', newline='') as fh:
|
|
writer = csv.writer(fh, lineterminator='\n')
|
|
writer.writerow(HEADERS)
|
|
for record in records:
|
|
writer.writerow(flatten(record))
|
|
print('records_in: %d' % len(records))
|
|
print('wrote: %s' % out_path)
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|