{"id":2245,"date":"2020-04-10T18:42:37","date_gmt":"2020-04-10T18:42:37","guid":{"rendered":"https:\/\/www.codeastar.com\/?p=2245"},"modified":"2020-04-10T19:08:22","modified_gmt":"2020-04-10T19:08:22","slug":"cheap-flights-checker-extra-the-airport-seeker","status":"publish","type":"post","link":"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/","title":{"rendered":"Cheap Flights Checker Extra – the Airport Seeker"},"content":{"rendered":"\n

2020 is a challenging year. First, we have social unrest in Hong Kong since June 2019. Then we have COVID-19 pandemic<\/a> around the world. Some people lost their beloved ones, some people lost their jobs, some people had to postpone their dreams. During that very season, nobody is safe. I canceled two of my trips and got some financial loss as well. Frustrated? Yes. But what we can do currently are, stay positive and keep going. Last time, we created a Cheap Flights Checker<\/a> console program with Skyscanner API. I would like to build a web app using the same API. Then, we need an Airport Seeker with Skyscanner API.<\/p>\n\n\n\n\n\n\n\n

The Cheap Flights Web App<\/h3>\n\n\n\n

Yes, we are talking about the Cheap Flights Web App. So why do we need an Airport Seeker? Since we are making a Cheap Flights Web App, the UI picture should look like:<\/p>\n\n\n\n

\"Cheap<\/figure><\/div>\n\n\n\n

Where we have <Market<\/em>>, <Currency<\/em>>, <From<\/em>> and <To<\/em>> select options. <\/p>\n\n\n\n

We can get <Market> <\/em>and <Currency> <\/em>listings from Skyscanner APIs. But there is no such thing for getting airport listings on <From<\/em>> and <To><\/em> options.<\/p>\n\n\n\n

In order to make the Cheap Flights Web App, we have to solve the airport listing problem. That is why we need the Airport Seeker.<\/p>\n\n\n\n

Airport Seeker using Skyscanner API<\/h3>\n\n\n\n

First, let us check what Skyscanner API can help with the airport list. Well, they have a “Places API” which accepts location as input (e.g. “Stockholm”) and returns places related to the input. (we can see the output sample below)<\/p>\n\n\n\n

\"Stockholm<\/figure><\/div>\n\n\n\n

We can use country name as our input, then use the returned PlaceId as IATA code and PlaceName as the airport name to make our airport list.<\/p>\n\n\n\n

Limitation on Skyscanner API<\/h3>\n\n\n\n

Last time, we mentioned a limitation of the Skyscanner API — we can only make 50 requests within 1 minute. There are around 190 countries in the world. That means we need to run around 190 requests to build the airport list. <\/p>\n\n\n\n

By not exceeding the “1 minute with 50 requests” rule, then we can record every API request starting time. If 50 requests have been run within 1 minute, we let the program sleep for certain seconds after the 50th or the number multiplied by 50th request. Assume we can handle 50 requests per minute, we will need 4 minutes to make our airport list.<\/p>\n\n\n\n

It is Coding Time<\/h3>\n\n\n\n

Input? Check. Output? Check. Limitation? Check. So what time is it? IT IS CODING TIME!<\/p>\n\n\n\n

And the good thing is, we can use most of the code from our last Cheap Flights Checker<\/a>. So we install requests and TinyDB Python modules again, then create “Profile”, “Countries” and “Airports” tables. <\/p>\n\n\n\n

import requests\nimport os, sys, json, time\nfrom tinydb import TinyDB, Query\n\ndb = TinyDB('skyscanner_iata.json')\nProfile = db.table('Profile')\nCountries = db.table('Countries')\nAirports = db.table('Airports')\n\nENDPOINT_PREFIX = \"https:\/\/skyscanner-skyscanner-flight-search-v1.p.rapidapi.com\/apiservices\/\"\nMARKET = \"US\"\nCURRENCY = \"USD\"\nCOUNTRY_ENDPOINT = \"http:\/\/country.io\/names.json\"\nSLEEP_BUFFER = 5\n<\/pre>\n\n\n\n

“Profile” is the place where we store the API key (see the previous post if you forgot how had we handled it), “Countries” is a list of countries while “Airports” is the table we wanted. <\/p>\n\n\n\n

Okay, another question, where do we get the list of countries? We can’t find it from Skyscanner API, but we can get it from other web sites. For our case, we use country.io<\/a> ‘s JSON response.<\/p>\n\n\n\n

Before we go further, let’s create our common functions, which are almost the same as the ones used in our previous exercise.<\/p>\n\n\n\n

def initProfileDB():\n  if \"SKYSCAN_RAPID_API_KEY\" in os.environ:\n    API_KEY = os.environ['SKYSCAN_RAPID_API_KEY']   \n    Profile.upsert({'api_key':API_KEY}, Query().api_key.exists())\n  else: \n    API_KEY = Profile.search(Query().api_key)\n    if API_KEY == []: \n      sys.exit(\"No API key found\")\n    API_KEY = API_KEY[0]['api_key']\n\n  profile_dict = {\n    \"API_KEY\": API_KEY,\n  }\n  return profile_dict    \n\ndef handleAPIException(responseText, apiname):\n      print(json.dumps(json.loads(responseText), indent=3, sort_keys=True))\n      sys.exit(f\"API exception on [{apiname}]\")   \n<\/pre>\n\n\n\n

Now it is the time we add something new. First, the country list. <\/p>\n\n\n\n

def getCountries():\n    country_list = []\n    ss_countries = Countries.search(Query())\n    if len(ss_countries) == 0:\n        response = requests.request(\"GET\", COUNTRY_ENDPOINT)\n        if response.status_code != 200: handleAPIException(response.text, \"getCountries\")\n        country_json = json.loads(response.text)\n        Countries.insert(country_json)\n        ss_countries = [country_json]\n    for country in ss_countries[0]:\n        country_list.append(ss_countries[0][country])\n    return country_list\n<\/pre>\n\n\n\n

Airport, Airport and Airport<\/h3>\n\n\n\n

Then we add our core airport finding logic here.<\/p>\n\n\n\n

def getIataCode(place_string, request_time_list):\n    url = ENDPOINT_PREFIX+f\"autosuggest\/v1.0\/{MARKET}\/{CURRENCY}\/en-US\/\"\n    querystring = {\"query\":place_string}\n    request_start_time = time.time()\n    request_time_list.append(request_start_time)\n    if (len(request_time_list) % 50 == 0): \n        the_first_request_time = request_time_list[0]\n        second_from_1st_request = round(time.time() - the_first_request_time)\n        print(f\"Hit the 50th request mark, wait for 60-{second_from_1st_request} seconds\")\n        time.sleep(60-second_from_1st_request+SLEEP_BUFFER)\n        request_time_list =[]    #clean up the request start time list \n    response = requests.request(\"GET\", url, headers=headers, params=querystring)\n    if response.status_code != 200: handleAPIException(response.text, \"getIataCode\")\n    place_json = json.loads(response.text)    \n    for place in place_json[\"Places\"]:\n        if ((len(place['PlaceId']) == 7) and (place['CountryName']==place_string)):\n            print(f\"{place['PlaceName']}, {place['CountryName']} - {place['PlaceId'][:3]}\")\n            place_dict = {\n                \"PlaceName\": place['PlaceName'],\n                \"CountryName\": place['CountryName'],\n                \"Iata\": place['PlaceId'][:3], \n            }\n            Airports.upsert(place_dict, Query().Iata == place['PlaceId'][:3])\n    return request_time_list        \n<\/pre>\n\n\n\n

In order to handle the limitation of 50 requests per minute, we create a list called request_time_list<\/em>. We record the starting time of every request. When we hit the 50th request, we check rather it passes the 1 minute mask. If everything is fine, let it process more requests. Otherwise, just let it wait for the remaining seconds within the 1 minute mask. Please note that there are (optional) 5 seconds added there, to ensure it won’t break the limit. <\/p>\n\n\n\n

The rest of the codes are straight forward, they are mostly JSON handling.<\/p>\n\n\n\n

print(\"Start processing your request...\")\nprofile_dict = initProfileDB()\nheaders = {\n    'x-rapidapi-host': \"skyscanner-skyscanner-flight-search-v1.p.rapidapi.com\",\n    'x-rapidapi-key': profile_dict[\"API_KEY\"]\n    }    \nairports = Airports.search(Query().Iata)\nif airports == []: \n    print(\"No Airport found, start requesting from Skyscanner API...\")\n    country_list = getCountries()\n    request_time_list = []\n    for country in country_list:\n        request_time_list = getIataCode(country, request_time_list)\n\nprint(\"Got Airport from DB\")\nprint(Airports.search(Query()))\n<\/pre>\n\n\n\n

To run it, all we need to do are:<\/p>\n\n\n\n

>export SKYSCAN_RAPID_API_KEY=abcde   (for Linux\/MacOS)\nor\n>$Env:SKYSCAN_RAPID_API_KEY=\"abcde\"   (for Win10 powershell, double quotes are needed)\nor\n>SET SKYSCAN_RAPID_API_KEY=abcde      (for Win10 command prompt)\n\nThen run the program\n>python getairportcode.py<\/code><\/pre>\n\n\n\n

The program should then capture airport information from Skyscanner, store it in our TinyDB. The result set should be used in our next project — the Cheap Flights Web App.<\/p>\n\n\n\n

<\/div>\n\n\n\n

What have we learned in this post?<\/h3>\n\n\n\n
  1. Use time and sleep to limit the number of our API request<\/li>
  2. Think positive and keep preparing!<\/li><\/ol>\n\n\n\n

    (the complete source can be found at\u00a0GitHub<\/strong>:\u00a0 <\/a>https:\/\/github.com\/codeastar\/<\/a>easy_iata_airport_seeker<\/a> )<\/p>\n\n\n\n

    <\/p>\n","protected":false},"excerpt":{"rendered":"

    2020 is a challenging year. First, we have social unrest in Hong Kong since June 2019. Then we have COVID-19 pandemic around the world. Some people lost their beloved ones, some people lost their jobs, some people had to postpone their dreams. During that very season, nobody is safe. I canceled two of my trips […]<\/p>\n","protected":false},"author":1,"featured_media":2270,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"site-sidebar-layout":"default","site-content-layout":"default","ast-site-content-layout":"","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_newsletter_tier_id":0,"jetpack_publicize_message":"Let's get IATA airport codes using Skyscanner API.","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[2],"tags":[15,169,168,165,164],"jetpack_publicize_connections":[],"yoast_head":"\nCheap Flights Checker Extra - the Airport Seeker ⋆ Code A Star<\/title>\n<meta name=\"description\" content=\"Last time, we created a Cheap Flights Checker console program with Skyscanner API. This time, let we create an API to get airport information.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Cheap Flights Checker Extra - the Airport Seeker ⋆ Code A Star\" \/>\n<meta property=\"og:description\" content=\"Last time, we created a Cheap Flights Checker console program with Skyscanner API. This time, let we create an API to get airport information.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/\" \/>\n<meta property=\"og:site_name\" content=\"Code A Star\" \/>\n<meta property=\"article:publisher\" content=\"codeastar\" \/>\n<meta property=\"article:author\" content=\"codeastar\" \/>\n<meta property=\"article:published_time\" content=\"2020-04-10T18:42:37+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-04-10T19:08:22+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.codeastar.com\/wp-content\/uploads\/2020\/04\/airport_1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"560\" \/>\n\t<meta property=\"og:image:height\" content=\"526\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Raven Hon\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@codeastar\" \/>\n<meta name=\"twitter:site\" content=\"@codeastar\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Raven Hon\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/\"},\"author\":{\"name\":\"Raven Hon\",\"@id\":\"https:\/\/www.codeastar.com\/#\/schema\/person\/832d202eb92a3d430097e88c6d0550bd\"},\"headline\":\"Cheap Flights Checker Extra – the Airport Seeker\",\"datePublished\":\"2020-04-10T18:42:37+00:00\",\"dateModified\":\"2020-04-10T19:08:22+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/\"},\"wordCount\":746,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.codeastar.com\/#\/schema\/person\/832d202eb92a3d430097e88c6d0550bd\"},\"keywords\":[\"api\",\"country\",\"iata\",\"skyscanner\",\"travel\"],\"articleSection\":[\"We code therefore we are\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/\",\"url\":\"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/\",\"name\":\"Cheap Flights Checker Extra - the Airport Seeker ⋆ Code A Star\",\"isPartOf\":{\"@id\":\"https:\/\/www.codeastar.com\/#website\"},\"datePublished\":\"2020-04-10T18:42:37+00:00\",\"dateModified\":\"2020-04-10T19:08:22+00:00\",\"description\":\"Last time, we created a Cheap Flights Checker console program with Skyscanner API. This time, let we create an API to get airport information.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.codeastar.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Cheap Flights Checker Extra – the Airport Seeker\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.codeastar.com\/#website\",\"url\":\"https:\/\/www.codeastar.com\/\",\"name\":\"Code A Star\",\"description\":\"We don't wish upon a star, we code a star\",\"publisher\":{\"@id\":\"https:\/\/www.codeastar.com\/#\/schema\/person\/832d202eb92a3d430097e88c6d0550bd\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.codeastar.com\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/www.codeastar.com\/#\/schema\/person\/832d202eb92a3d430097e88c6d0550bd\",\"name\":\"Raven Hon\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.codeastar.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2018\/08\/logo70.png?fit=70%2C70&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2018\/08\/logo70.png?fit=70%2C70&ssl=1\",\"width\":70,\"height\":70,\"caption\":\"Raven Hon\"},\"logo\":{\"@id\":\"https:\/\/www.codeastar.com\/#\/schema\/person\/image\/\"},\"description\":\"Raven Hon is\u00a0a 20 years+ veteran in information technology industry who has worked on various projects from console, web, game, banking and mobile applications in different sized companies.\",\"sameAs\":[\"https:\/\/www.codeastar.com\",\"codeastar\",\"https:\/\/twitter.com\/codeastar\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Cheap Flights Checker Extra - the Airport Seeker ⋆ Code A Star","description":"Last time, we created a Cheap Flights Checker console program with Skyscanner API. This time, let we create an API to get airport information.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/","og_locale":"en_US","og_type":"article","og_title":"Cheap Flights Checker Extra - the Airport Seeker ⋆ Code A Star","og_description":"Last time, we created a Cheap Flights Checker console program with Skyscanner API. This time, let we create an API to get airport information.","og_url":"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/","og_site_name":"Code A Star","article_publisher":"codeastar","article_author":"codeastar","article_published_time":"2020-04-10T18:42:37+00:00","article_modified_time":"2020-04-10T19:08:22+00:00","og_image":[{"width":560,"height":526,"url":"https:\/\/www.codeastar.com\/wp-content\/uploads\/2020\/04\/airport_1.png","type":"image\/png"}],"author":"Raven Hon","twitter_card":"summary_large_image","twitter_creator":"@codeastar","twitter_site":"@codeastar","twitter_misc":{"Written by":"Raven Hon","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/#article","isPartOf":{"@id":"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/"},"author":{"name":"Raven Hon","@id":"https:\/\/www.codeastar.com\/#\/schema\/person\/832d202eb92a3d430097e88c6d0550bd"},"headline":"Cheap Flights Checker Extra – the Airport Seeker","datePublished":"2020-04-10T18:42:37+00:00","dateModified":"2020-04-10T19:08:22+00:00","mainEntityOfPage":{"@id":"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/"},"wordCount":746,"commentCount":0,"publisher":{"@id":"https:\/\/www.codeastar.com\/#\/schema\/person\/832d202eb92a3d430097e88c6d0550bd"},"keywords":["api","country","iata","skyscanner","travel"],"articleSection":["We code therefore we are"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/","url":"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/","name":"Cheap Flights Checker Extra - the Airport Seeker ⋆ Code A Star","isPartOf":{"@id":"https:\/\/www.codeastar.com\/#website"},"datePublished":"2020-04-10T18:42:37+00:00","dateModified":"2020-04-10T19:08:22+00:00","description":"Last time, we created a Cheap Flights Checker console program with Skyscanner API. This time, let we create an API to get airport information.","breadcrumb":{"@id":"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.codeastar.com\/cheap-flights-checker-extra-the-airport-seeker\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.codeastar.com\/"},{"@type":"ListItem","position":2,"name":"Cheap Flights Checker Extra – the Airport Seeker"}]},{"@type":"WebSite","@id":"https:\/\/www.codeastar.com\/#website","url":"https:\/\/www.codeastar.com\/","name":"Code A Star","description":"We don't wish upon a star, we code a star","publisher":{"@id":"https:\/\/www.codeastar.com\/#\/schema\/person\/832d202eb92a3d430097e88c6d0550bd"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.codeastar.com\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.codeastar.com\/#\/schema\/person\/832d202eb92a3d430097e88c6d0550bd","name":"Raven Hon","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.codeastar.com\/#\/schema\/person\/image\/","url":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2018\/08\/logo70.png?fit=70%2C70&ssl=1","contentUrl":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2018\/08\/logo70.png?fit=70%2C70&ssl=1","width":70,"height":70,"caption":"Raven Hon"},"logo":{"@id":"https:\/\/www.codeastar.com\/#\/schema\/person\/image\/"},"description":"Raven Hon is\u00a0a 20 years+ veteran in information technology industry who has worked on various projects from console, web, game, banking and mobile applications in different sized companies.","sameAs":["https:\/\/www.codeastar.com","codeastar","https:\/\/twitter.com\/codeastar"]}]}},"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2020\/04\/airport_1.png?fit=560%2C526&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p8PcRO-Ad","jetpack-related-posts":[{"id":2281,"url":"https:\/\/www.codeastar.com\/easy-cheap-flights-seeker-web-app-with-flask-and-react\/","url_meta":{"origin":2245,"position":0},"title":"Easy Cheap Flights Seeker Web App with Flask and React","author":"Raven Hon","date":"October 5, 2020","format":false,"excerpt":"We have 1, 2, 3, 4, 5 months without updating the CodeAStar web site. It seems 2020 is not a good year for everybody. What we can do are, stay strong, stay positive and keep learning. So let's continue on what we mentioned last time --- Easy Cheap Flights Seeker\u2026","rel":"","context":"In "We code therefore we are"","block_context":{"text":"We code therefore we are","link":"https:\/\/www.codeastar.com\/category\/we-code-therefore-we-are\/"},"img":{"alt_text":"EZ Cheap Flights Web App","src":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2020\/10\/ezflight_1.png?fit=940%2C543&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2020\/10\/ezflight_1.png?fit=940%2C543&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2020\/10\/ezflight_1.png?fit=940%2C543&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2020\/10\/ezflight_1.png?fit=940%2C543&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":2192,"url":"https:\/\/www.codeastar.com\/cheap-flights-checker-flight-for-your-dream\/","url_meta":{"origin":2245,"position":1},"title":"Cheap Flights Checker – Flight for your dream","author":"Raven Hon","date":"January 19, 2020","format":false,"excerpt":"We love travel and we love easy stuff. So we have our easy flight prices checker :]] . When we start to plan our vacation, flight ticket is always the first item we purchase. It would be great if we can have a look on cheap flight tickets around our\u2026","rel":"","context":"In "We code therefore we are"","block_context":{"text":"We code therefore we are","link":"https:\/\/www.codeastar.com\/category\/we-code-therefore-we-are\/"},"img":{"alt_text":"Cheap Flights API","src":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2020\/01\/cheapflights_1.png?fit=798%2C611&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2020\/01\/cheapflights_1.png?fit=798%2C611&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2020\/01\/cheapflights_1.png?fit=798%2C611&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2020\/01\/cheapflights_1.png?fit=798%2C611&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":1740,"url":"https:\/\/www.codeastar.com\/flask-backend-react-frontend-weather-1\/","url_meta":{"origin":2245,"position":2},"title":"Flask Backend and React Frontend for Weather Forecast – Part 1","author":"Raven Hon","date":"February 25, 2019","format":false,"excerpt":"We built a weather forecast web app with Flask in past. That was an old fashioned way which we handled all frontend and backend stuff under Flask framework. The best practice for web applications nowadays is separating frontend and backend into 2 modules. So we can utilize both modules to\u2026","rel":"","context":"In "We code therefore we are"","block_context":{"text":"We code therefore we are","link":"https:\/\/www.codeastar.com\/category\/we-code-therefore-we-are\/"},"img":{"alt_text":"Flask backend","src":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2019\/02\/wq_milktea.png?fit=1000%2C500&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2019\/02\/wq_milktea.png?fit=1000%2C500&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2019\/02\/wq_milktea.png?fit=1000%2C500&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2019\/02\/wq_milktea.png?fit=1000%2C500&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":1769,"url":"https:\/\/www.codeastar.com\/react-frontend-weather-forecast-2\/","url_meta":{"origin":2245,"position":3},"title":"React Frontend and Flask Backend for Weather Forecast \u2013 Part 2","author":"Raven Hon","date":"March 4, 2019","format":false,"excerpt":"From our last post, \"Flask Backend and React Frontend for Weather Forecast \u2013 Part 1\", we built our magic user, RESTful API as the backend module with Flask. This time, we are going to build our sword swinger, who always deals with challenges at the front line. Before we go\u2026","rel":"","context":"In "We code therefore we are"","block_context":{"text":"We code therefore we are","link":"https:\/\/www.codeastar.com\/category\/we-code-therefore-we-are\/"},"img":{"alt_text":"React Frontend","src":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2019\/03\/wq_happy.png?fit=1000%2C500&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2019\/03\/wq_happy.png?fit=1000%2C500&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2019\/03\/wq_happy.png?fit=1000%2C500&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2019\/03\/wq_happy.png?fit=1000%2C500&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":387,"url":"https:\/\/www.codeastar.com\/easy-python-weather-forecast-tool\/","url_meta":{"origin":2245,"position":4},"title":"Easy Weather Forecast Tool in Python","author":"Raven Hon","date":"August 4, 2017","format":false,"excerpt":"Since I am going to have a 5-day trip to Sapporo, Hokkaido, Japan at the end of August, I would like to have a weather forecast for my trip. \"So why don't you check from a weather forecast site for free?\" Yes, but I would like to get the exact\u2026","rel":"","context":"In "We code therefore we are"","block_context":{"text":"We code therefore we are","link":"https:\/\/www.codeastar.com\/category\/we-code-therefore-we-are\/"},"img":{"alt_text":"Weather forecast in Python is easy and relaxing","src":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2017\/08\/egg_holidays.png?fit=769%2C655&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2017\/08\/egg_holidays.png?fit=769%2C655&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2017\/08\/egg_holidays.png?fit=769%2C655&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2017\/08\/egg_holidays.png?fit=769%2C655&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":1988,"url":"https:\/\/www.codeastar.com\/easy-accuweather-forecast-in-python\/","url_meta":{"origin":2245,"position":5},"title":"Easy AccuWeather Forecast in Python","author":"Raven Hon","date":"May 31, 2019","format":false,"excerpt":"We have talked different topics in CodeAStar here, ranging from AWS, CNN, Docker, LGB, Raspberry Pi, RNN and the list goes on. Do you know what is the most popular page here? According to the figure from Google Analytics, and out of my expectation, the most popular page is \"Easy\u2026","rel":"","context":"In "We code therefore we are"","block_context":{"text":"We code therefore we are","link":"https:\/\/www.codeastar.com\/category\/we-code-therefore-we-are\/"},"img":{"alt_text":"AccuWeather Forecast","src":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2019\/05\/accuw2.png?fit=1024%2C419&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2019\/05\/accuw2.png?fit=1024%2C419&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2019\/05\/accuw2.png?fit=1024%2C419&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.codeastar.com\/wp-content\/uploads\/2019\/05\/accuw2.png?fit=1024%2C419&ssl=1&resize=700%2C400 2x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.codeastar.com\/wp-json\/wp\/v2\/posts\/2245"}],"collection":[{"href":"https:\/\/www.codeastar.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.codeastar.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.codeastar.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.codeastar.com\/wp-json\/wp\/v2\/comments?post=2245"}],"version-history":[{"count":23,"href":"https:\/\/www.codeastar.com\/wp-json\/wp\/v2\/posts\/2245\/revisions"}],"predecessor-version":[{"id":2276,"href":"https:\/\/www.codeastar.com\/wp-json\/wp\/v2\/posts\/2245\/revisions\/2276"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.codeastar.com\/wp-json\/wp\/v2\/media\/2270"}],"wp:attachment":[{"href":"https:\/\/www.codeastar.com\/wp-json\/wp\/v2\/media?parent=2245"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.codeastar.com\/wp-json\/wp\/v2\/categories?post=2245"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.codeastar.com\/wp-json\/wp\/v2\/tags?post=2245"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}