Calling Web API's in Python

By Michael Fudge

1. Essentials Before We Code

Okay, Let's Start with "What is an API?"

API stands for Application Programming Interface. Simply put, it is code written to interact with something. For example if you want to write a program to make your computer perform text to speech you can either get your PhD in digital signal processing and write it yourself, or you can find someone else's code and figure out how to integrate it within your application. Programmers do the latter all the time, which is called consuming the API. API's make programming easier because we re-use other people's code and don't have to write everything ourselves.

You have been consuming API's all along in this course. Every time we import a Python module we are adding other people's code to our programs, and consuming their API. In addition, the built in Python string functions like startswith() and upper() are part of Pythons internal API. If we want to convert a string to upper case, we don't have to write that code ourselves, we can just use the built in string API!

What makes Python so great is there are many useful API's built into the language. There is also a website, called the Python Package Index https://pypi.org/ where you can find other API's and then install them into your Python environment using the pip utility.

What is a Web API?

A web API is an API that gets called over the world-wide-web. In this scenairo, the API code is not on your computer. It's on another computer on your network (almost always a web server over the Internet). When your code wants to call the Web API:

  1. It must make an request which travels over the network to the computer, a web server, hosting the API.
  2. The web server hosting the API runs the API code and generates a response which it sends back to your computer

Why Web API's?

Web API's are commonplace in the era of cloud computing, but the question is: why?

Initially the web focused on the direct user-consumption of information. We used a browser and search engine to get the news, sports scores, watch youtube or get the latest weather forecast. We did not need web API's because all of this consumption took place in a web browser, and the services we used could just send us HTML, which our browser rendered into nice looking webpages.

The emergence of smart devices like watches, phones, media players, and intelligent speakers has caused a shift in the web from user-based to device-based. Most of the information we consume nowadays is no longer in a browser, but instead on a variety of devices. We watch movies on our Roku players, check the news and sports scores on our smart phones, or get weather reports from Alexa. For example:

  • When we use an app on our smartphone to get stock quotes, a web API is delivering data to the app on our phone. The app is then displaying the information on our screen.
  • When we ask Alexa to play a song, Web API will search for the the song (on Spotify for example) and return back information about the song including how the speaker can play it.

You might think you need to know a lot about networking to call a web API, but actually HTTP (Hyptertext Transport Protocol) handles most of the details for you. HTTP is the protocol that makes the web work. You do need to understand some basics of HTTP in order to correctly consume web API's.

Understanding HTTP

The Hyptertext Transport Protocol (HTTP) is the means by which hosts on the web communicate. The communication occurs in a request/response pair.

  • An HTTP request is sent by the client to the web server and consists of a URL or Uniform Resource Locator and an HTTP Verb
  • An HTTP response is sent from the web server to the client and consists of a Status Code and a Response Body

URL

A URL consists of the name of the web server (the host) the path to the resource, and optional query arguments. For example this URL accesses the iSchool's Spring 2019 Undergraduate class schedule:https://ischool.syr.edu/classes/spring-2019/undergraduate.

In addition, you can include an optional query which affects how the resource returns a reponse. For example here's page 2 of the class schedule: https://ischool.syr.edu/classes/spring-2019/undergraduate/?page=2. URL's are controlled by the web developer and/or application running on the server. The client does not have any say is how the URL looks or behaves, just like you cannot choose another person's phone number or email address. One must simply know the URL to access the resource.

HTTP Verbs

In addition to the URL, an HTTP Verb must be included in the request. The verb specifies how the resource will be accessed.

  • The GET verb fetches an existing resource from the web server. No data is sent other than the URL.
  • The POST verb is for sending a data payload to the webserver along with the URL.
  • There are other verbs like PUT, PATCH, DELETE, HEAD, TRACE and OPTIONS but we will mostly stick to GET and POST.

Status Codes

When the server returns a response to a request, included in the response is the HTTP status code, which tells the client whether or not the request worked. Status codes are 3 digit numbers and the first number indicates the type of response:

  • 2xx - codes which begin with a 2 indicate success. The most common code is 200 - OK.
  • 3xx - codes which begin with a 3 indicate redirection - the response is not comming from the request URL. For example a 304 - Not modified means you requested the resource from the server, but the response is coming from the browser's cache (content already downloaded by your browser).
  • 4xx - codes which begin with a 4 indicate a client error. The most common code here is 404 - Not Found, which occurs when the client makes a request a URL for which the resource does not exist.
  • 5xx - codes which begin with a 5 indicate a server error. The most common code here is 500 - Internal server error, which indicated the server could not process the request.

Response Body

Included in any response, whether successful or not, is a response body. The response body contains the actual content. With most browser responses the content is HTML (Hypertext Markup Language). HTML is a content type for rendering data in a webpage; It has data and also layout information for how the page should look.

HTML is not a suitable format for Web API's because we only want the data - not the layout. As such most web API's return a response type in XML extensible markup language or JSON Javascript Object Notation formats. Both formats only contain data.

JSON (Javascript Object Notation)

Because the reciever of the information is now a device as opposed to a web browser, HTML is not a suitable format. HTML includes presentation and layout information with the data, making it difficult for a device to process. Instead we just want the API to return the data in a structured format so that our consumer program can extract the information we need.

Most web API's return data back to the consumer in JSON (JavaScript Object Notation) format. JSON is a lightweight data format which is easy for people to read and write.

Here's an example JSON response we might get from a weather API:

{ 'location' : 'Syracuse, NY',
  'time' : '2018-10-31 9:00+05:00',
  'temperature' : 59.6,
  'humidity' : 95.5
}

If you think that looks a lot like a Python dictionary object, you would be right! It's very easy to convert JSON into a Python object (a process called de-serialization) and to conver a Python object back into JSON (that's called serialization). This makes Python a very capable language for consuming web API's.

Putting it all together

There were a lot of concepts in this section, let's distill them into aa generic algorithm for consuming web API's in Python.

To call a web API in Python, we:

  1. Make an HTTP GET or POST Request to the web API's URL
  2. Check the Response Status Code 200/OK to ensure the request worked
  3. If OK we de-serialize the response Body JSON format into a Python object

That's it! The only thing that changes about the process is:

  1. The HTTP URL and Verb - it will depend on the specific web API we choose to call. We must read the API's instructions to understand how to use it.
  2. The Python object we get back from the de-serialized response. Once again it will depend on the API we call. It is up to you to read the instructions and figure out how to extract what you need from the response.

2. Making HTTP Requests in Python using the Requests Module

Before we call Web API's in Python, we must first understand how to make HTTP requests. For this, we will use the requests module: http://docs.python-requests.org/en/master/user/quickstart/. This library is based on Python's internal urllib library, but is more expressive and easier to understand. requests makes dealing with the HTTP protocol very pleasant by eliminating a lot of the boilerplate code you need to make a request and handle the response.

URLLIB: Life without the Requests module

When we use urllib we there is more boilerplate code - extra code we must write to make things work. Making the request and converting the response to a Python object are both 2 step processes.

In [26]:
import urllib.request, urllib.error, urllib.parse
import json
try:
    data = { 'name' : 'mike', 'age' : 45 }
    request = urllib.request.Request('https://httpbin.org/get?' + urllib.parse.urlencode(data) ) # make the request URL
    response = urllib.request.urlopen(request) # execute the request
    raw_data = response.read()           # read the data
    object_data = json.loads(raw_data)   # deserilaize the data into python object
    print(object_data)
except urllib.error.HTTPError as e:
    print(e)
{'args': {'age': '45', 'name': 'mike'}, 'headers': {'Accept-Encoding': 'identity', 'Connection': 'close', 'Host': 'httpbin.org', 'User-Agent': 'Python-urllib/3.6'}, 'origin': '128.230.182.217', 'url': 'https://httpbin.org/get?name=mike&age=45'}

The equivalent in Requests

The requests module requires just one line of code for request and response. All of the dirty work of encoding the URL and deserializing the response are handled for us!

In [27]:
import requests
data = { 'name' : 'mike', 'age' : 45 }
response = requests.get('https://httpbin.org/get', params = data) # make and execute the request to URL in one step!
if response.ok:
    object_data = response.json() # read and de-serialize in one step!
    print(object_data)
else:
    print(response.status_code, response.reason)
{'args': {'age': '45', 'name': 'mike'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.19.1'}, 'origin': '128.230.182.217', 'url': 'https://httpbin.org/get?name=mike&age=45'}

HTTP Requests

To make a request simply call requests.get() with the url string as the argument. This example gets the contents of the URL https://httpbin.org/html which returns a section of the novel Moby Dick as an HTML page.

In [39]:
response = requests.get('https://httpbin.org/html')
html = response.text
print(html[:296], '...') # just the first 296 characters, please
<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
      <h1>Herman Melville - Moby-Dick</h1>

      <div>
        <p>
          Availing himself of the mild, summer-cool weather that now reigned in these latitudes, and in preparation for the peculiarly active pursuits shortly to be anticipated, ...

Status Codes - Did it work?

How do you know if the request worked? You should check the response.ok variable. This is True when the HTTP response code is 200. A response code of 200 has the reason OK.

In [45]:
response = requests.get('https://httpbin.org/html')
print("OK?", response.ok)
print("HTTP Status Code:", response.status_code)
print("HTTP Status Code Reason:", response.reason)
OK? True
HTTP Status Code: 200
HTTP Status Code Reason: OK

Here's an example of a response which is not OK. I'm requesting the URL https://httpbin.org/mikefudge which should not be found on that web server. This yields a response status code of 404 and a reason of NOT FOUND.

In [46]:
response = requests.get('https://httpbin.org/mikefudge')
print("OK?", response.ok)
print("HTTP Status Code:", response.status_code)
print("HTTP Status Code Reason:", response.reason)
OK? False
HTTP Status Code: 404
HTTP Status Code Reason: NOT FOUND

HTTP Responses

The HTTP response is stored in a Python variable called response. We can get the raw response as a string by asking for response.text. Here is the raw response from the URL https://httpbin.org/get which returns JSON as a Python string:

In [48]:
response = requests.get('https://httpbin.org/get')
if response.ok:
    print(response.text)
else:
    print(response.status_code, response.reason)
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.19.1"
  }, 
  "origin": "128.230.182.217", 
  "url": "https://httpbin.org/get"
}

Deserializing the Response

If the response is in JSON format, we can easily deserialize the response into a Python object by calling the response.json(). For example we call the same URL https://httpbin.org/get, but this time easily extract the "origin" key from the Python object. It is far easier to extract information from a Python object than it is to search for what you need within the equivalent string!

In [72]:
response = requests.get('https://httpbin.org/get')
if response.ok:
    py_object = response.json() # de-serialize the string into a Python object!
    print("Python Object: ", py_object, '\n')
    print("Type of Object: ", type(py_object), '\n')
    print("Just the value of the 'origin' key: ", py_object['origin'], '\n')
else:
    print(response.status_code, response.reason)
Python Object:  {'args': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.19.1'}, 'origin': '128.230.182.217', 'url': 'https://httpbin.org/get'} 

Type of Object:  <class 'dict'> 

Just the value of the 'origin' key:  128.230.182.217 

What Happens when the Response Cannot be Deserialized?

What happens if you try and deserialize response content which is not in JSON format? You will get an exception of type json.decoder.JSONDecodeError. For example when we try to request the HTML at 'https://httpbin.org/html', the response is OK but the response.json() function fails to decode the text into a Python object:

In [69]:
try:
    url = 'https://httpbin.org/html'
    response = requests.get(url)
    if response.ok:
        print("HTTP Status Code:", response.status_code, response.reason)
        print(response.json()) # ERROR This is not JSON!!!
except json.decoder.JSONDecodeError:
    print("Sorry the contents of", url, "are not in the JSON format!")
HTTP Status Code: 200 OK
Sorry the contents of https://httpbin.org/html are not in the JSON format!

Putting it all together - making a request

Here's some boilerplate code to make an HTTP request. Just change the URL and go! If the response is JSON, it will deserialize it into the variable pyobj. The code handles invalid HTTP responses and content which is not JSON. Any time you call a web API your code should be similar to this!

In [ ]:
try:
    url = 'Any-URL-Here'
    response = requests.get(url)
    if response.ok:
        pyobj = response.json()
        print("YOUR PYTHON OBJECT: ", pyobj)
    else:
        print(response.status_code, response.reason)
except json.decoder.JSONDecodeError:
    print("Sorry the response from", url, "is not in the JSON format!")

3. Common Ways web API's are called

Now that you understand how to initiate HTTP requests and handle responses in Python code, we will conclude this reading by demonstrating several common methods by which web API's are called. In every example the response will be in JSON format, which is by far the most popular format for web API's. We will omit any boilerplate code to check the response status code and format so that we can instead focus on how to properly formulate requests.

Read The Docs!

If you want to understand how to consume a given Web API, you must read the docs. Any web API you are going to consider will include instructions for how to consume the API. They won't always have relevant examples in Python, but instead will explain things like whether you need to add an HTTP header or place an Argument on the Query string. Its up to YOU to figure out how to translate that into Python code. This part of the guide will walk you through most of the common ways this is done, serving as a cookbook of sorts.

Free APIs?

Sadly, the days of free access to Web API's is coming to an end. There's simply no money to be made in offering your serivce to other programmers if you cannot profit. For example, if I offer a weather API for free there will be hundereds of weather apps in the app store using my API. Those apps will charge customers and/or show advertisements and I will not make any money from the consumers while they profit off my service. If I want make money off my API, I must force the API consumer to register and pay per use.

Most API's we will use do this. They have a free tier for testing / trying out the API, which is usually sufficient for your demo day project. The web API's we consume in this reading are all free - an exception and not the rule! I chose free API's so that you can focus on the requests and reponses rather than the logistics of acquiring an API key.

HTTP GET Request to a resoure.

The simplest Web API call is an unauthenticated HTTP GET request with no arguments. Sadly, these types of API's are rare nowadays.

This example will call the httpbin Web API to help you answer what is the IP Address of my computer? the IP address is returned in the origin key:

In [76]:
web_api_url = 'https://httpbin.org/ip'
response = requests.get(web_api_url)
response.json()
Out[76]:
{'origin': '128.230.182.217'}

HTTP GET with Query String Parameters

Some API's allow you to include arguments on the query string. These are added to the end of the URL and effect what the URL does with the request.

In this example we will call the open street maps web API. We will request the search URL but include parameters for what we're searching for (in this case Animal Kingdom Lodge) and the format we would like the response (JSON).

We build a Python dictionary variable of query parameters required by the web API on line 2, and then pass them to the requests.get() function as the named argument params = options.

To refresh your memory, a named argument is optional in a function call. If you include it you must assign the parameter to the argument. In the example the parameter is params and the argument (what goes into the function) is the variable options.

In [82]:
web_api_url = 'https://nominatim.openstreetmap.org/search'  
options = { 'q' : 'Animal Kingdom Lodge', 'format' : 'json'}
response = requests.get(web_api_url, params = options)
response.json()
Out[82]:
[{'place_id': '68270960',
  'licence': 'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright',
  'osm_type': 'node',
  'osm_id': '5725706621',
  'boundingbox': ['28.3526885', '28.3527885', '-81.6026352', '-81.6025352'],
  'lat': '28.3527385',
  'lon': '-81.6025852',
  'display_name': 'Animal Kingdom Lodge, 2901, Osceola Parkway, Bay Lake, Reedy Creek Improvement District, Orange County, Florida, 34747, USA',
  'class': 'tourism',
  'type': 'hotel',
  'importance': 0.30100000000000005,
  'icon': 'https://nominatim.openstreetmap.org/images/mapicons/accommodation_hotel2.p.20.png'}]

Arguments in the HTTP Header

Some web API's like Reddit require you to include values in the HTTP Header. For the Reddit API you need a custom User-Agent key with a value which indicates what your application does.

For example, this code requests the top stories from subreddit /r/news in JSON format. We include the headers required by adding a named argument headers = custom_headers to the requests.get() function.

In [84]:
web_api_url = 'https://www.reddit.com/r/news/top.json'
custom_headers = {'User-Agent' : 'sample-python-application'}
response = requests.get(web_api_url, headers = custom_headers)
response.json() 
Out[84]:
{'kind': 'Listing',
 'data': {'modhash': '',
  'dist': 25,
  'children': [{'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_ce1jm',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': "Jury Orders 'Miracle Cure Doctor' to Pay $105 Million to Cancer Patient",
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9u7cwx',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 41590,
     'domain': 'nbcsandiego.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 41590,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541396014.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9u7cwx',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'todayilearned83',
     'num_crossposts': 3,
     'num_comments': 1153,
     'send_replies': False,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9u7cwx/jury_orders_miracle_cure_doctor_to_pay_105/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.nbcsandiego.com/news/local/Jury-Orders-Miracle-Cure-Doctor-to-pay-105-Million-to-Cancer-Patient-499354851.html',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541367214.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_10ck0y11',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': "Nurse who treated Pittsburgh shooter: 'I'm sure he had no idea I was Jewish'",
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9udaup',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 36003,
     'domain': 'theguardian.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 36003,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541451653.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9udaup',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'branstarktreewizard',
     'num_crossposts': 1,
     'num_comments': 2604,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9udaup/nurse_who_treated_pittsburgh_shooter_im_sure_he/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.theguardian.com/us-news/2018/nov/04/pittsburgh-shooting-robert-bowers-jewish-nurse',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541422853.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_gjx0j',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'Cancer-linked Chemicals Manufactured by 3M Are Turning Up in Drinking Water',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9u6h25',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 3272,
     'domain': 'bloomberg.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 3272,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541389944.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9u6h25',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'FreezeWolfy',
     'num_crossposts': 1,
     'num_comments': 157,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9u6h25/cancerlinked_chemicals_manufactured_by_3m_are/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.bloomberg.com/graphics/2018-3M-groundwater-pollution-problem/',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541361144.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_1pbw25he',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': '2 women sentenced to 3 years in jail for encouraging suicidal man to jump off Istanbul bridge',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9u6f62',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 3268,
     'domain': 'dailysabah.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 3268,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541389583.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9u6f62',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'Naaaahhhhh',
     'num_crossposts': 3,
     'num_comments': 320,
     'send_replies': False,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9u6f62/2_women_sentenced_to_3_years_in_jail_for/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.dailysabah.com/investigations/2018/10/25/2-women-sentenced-to-3-years-in-jail-for-encouraging-suicidal-man-to-jump-off-istanbul-bridge',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541360783.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_tbeh7',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'Newlyweds reportedly die in helicopter crash leaving their wedding',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9uczrc',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 1389,
     'domain': 'cbsnews.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 1389,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541448740.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9uczrc',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'Theholepatrol',
     'num_crossposts': 1,
     'num_comments': 280,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9uczrc/newlyweds_reportedly_die_in_helicopter_crash/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.cbsnews.com/news/newlyweds-will-byler-bailee-ackerman-byler-reportedly-die-texas-helicopter-crash-leaving-their-wedding/',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541419940.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_1loe9t0',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'Boy, 11, shoots and kills grandmother before turning gun on self, police say',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'hide_score': False,
     'name': 't3_9uacxf',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 1289,
     'domain': 'wfsb.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 1289,
     'approved_by': None,
     'thumbnail': '',
     'author_cakeday': True,
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541419411.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9uacxf',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'cleevethagreat',
     'num_crossposts': 1,
     'num_comments': 864,
     'send_replies': True,
     'whitelist_status': 'all_ads',
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9uacxf/boy_11_shoots_and_kills_grandmother_before/',
     'parent_whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.wfsb.com/boy-shoots-and-kills-grandmother-before-turning-gun-on-self/article_fa8ba1f8-18fb-5c34-a67a-eb3cd5dc0934.html?utm_source=facebook&amp;utm_medium=meredithHub&amp;fbclid=IwAR2jXN-qCD1qHJqnpnhiVQB5TaccFAY18BmiyvgbWf6NZaGHiNS6FqRAACA',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541390611.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_34ry6',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'Georgia man convicted of murdering grieving man who bumped into him at bar',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9u8av4',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 589,
     'domain': 'foxnews.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 589,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541402934.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9u8av4',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'gn3xu5',
     'num_crossposts': 1,
     'num_comments': 171,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9u8av4/georgia_man_convicted_of_murdering_grieving_man/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.foxnews.com/us/georgia-man-convicted-of-murdering-grieving-man-who-bumped-into-him-at-bar',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541374134.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_1rx71fa2',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'First Road in U.S. Made With Recycled Plastic Paved on Campus',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9ubdcq',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 381,
     'domain': 'ucsdguardian.org',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 381,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541429426.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9ubdcq',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'Fosse22',
     'num_crossposts': 1,
     'num_comments': 56,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9ubdcq/first_road_in_us_made_with_recycled_plastic_paved/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'http://ucsdguardian.org/2018/11/04/first-road-u-s-made-recycled-plastic-paved-campus/',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541400626.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_lz95l',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'California teacher caught on camera punching 14-year-old boy',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9u8v6b',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 310,
     'domain': 'cnn.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 310,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541407284.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9u8v6b',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'TenaciousProd',
     'num_crossposts': 1,
     'num_comments': 363,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9u8v6b/california_teacher_caught_on_camera_punching/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.cnn.com/2018/11/04/us/california-teacher-punches-student/index.html',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541378484.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_10dpf658',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'Report: Saudi investigators worked to remove evidence',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9uda28',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 246,
     'domain': 'abcnews.go.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 246,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541451442.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9uda28',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'Seapoogoo',
     'num_crossposts': 0,
     'num_comments': 22,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9uda28/report_saudi_investigators_worked_to_remove/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://abcnews.go.com/International/wireStory/report-saudi-investigators-worked-remove-evidence-58970313',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541422642.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_hucby',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'Privatisation of Britain’s railways has cost the taxpayer £5bn per year plus increased fares',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9ue6dt',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 252,
     'domain': 'thelondoneconomic.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 252,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541458663.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9ue6dt',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'Doener23',
     'num_crossposts': 1,
     'num_comments': 48,
     'send_replies': False,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9ue6dt/privatisation_of_britains_railways_has_cost_the/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.thelondoneconomic.com/news/privatisation-of-britains-railways-has-cost-the-taxpayer-5bn-per-year-plus-increased-fares/05/11/',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541429863.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_po0nw',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'Lost 6 year old boy found treat-or-treating alone while mom slept',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9ubdap',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 208,
     'domain': 'orlandosentinel.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 208,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541429409.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9ubdap',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'letsdoamakeover',
     'num_crossposts': 0,
     'num_comments': 73,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9ubdap/lost_6_year_old_boy_found_treatortreating_alone/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.orlandosentinel.com/news/breaking-news/os-ne-maitland-mom-arrested-kid-trick-or-treat-alone-20181102-story.html',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541400609.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_1fixh1gy',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'Thailand claims that Swine Fever has spread to Malaysia and urges army to prevent cross-border smuggling',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9u5t0o',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 182,
     'domain': 'thethaiger.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 182,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541385378.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9u5t0o',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'CattleTurdBurgler',
     'num_crossposts': 1,
     'num_comments': 1,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9u5t0o/thailand_claims_that_swine_fever_has_spread_to/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://thethaiger.com/news/south/southern-border-wild-boar-smuggling-risks-spread-of-african-swine-fever',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541356578.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_my78q',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'American Military Apologizes for Booklet With Racially Offensive Language - The New York Times',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9u61xe',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 152,
     'domain': 'nytimes.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': 'Soft paywall',
     'can_mod_post': False,
     'score': 152,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541387048.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9u61xe',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'crispy_attic',
     'num_crossposts': 1,
     'num_comments': 37,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9u61xe/american_military_apologizes_for_booklet_with/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.nytimes.com/2018/11/01/world/middleeast/american-military-racist-language.html',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541358248.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_p6ongy4',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'US sanctions on Iran to come into force',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9u9i4z',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 130,
     'domain': 'bbc.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 130,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541412428.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9u9i4z',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'fluffydog260',
     'num_crossposts': 2,
     'num_comments': 118,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9u9i4z/us_sanctions_on_iran_to_come_into_force/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.bbc.com/news/business-46092435',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541383628.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_1389xh',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'Explosion destroys multimillion-dollar home in Pennsylvania',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9ucxmf',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 126,
     'domain': 'abc11.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 126,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541448158.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9ucxmf',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'Kobobzane',
     'num_crossposts': 0,
     'num_comments': 24,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9ucxmf/explosion_destroys_multimilliondollar_home_in/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://abc11.com/gas-leak-causes-large-house-explosion-in-pennsylvania/4619452/',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541419358.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_1xnyijfs',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': '10-year-old is one of three youths charged with armed robbery in Columbia park',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9u91u5',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 119,
     'domain': 'baltimoresun.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 119,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541408812.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9u91u5',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'AGENTBAMELLL',
     'num_crossposts': 0,
     'num_comments': 9,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9u91u5/10yearold_is_one_of_three_youths_charged_with/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.baltimoresun.com/news/maryland/howard/ph-ho-cf-juveniles-arrests-1102-story.html',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541380012.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_9j9zj',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'Coroner: Woman Dies After Pit Bull Attack In Clark Co.',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9uehti',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 123,
     'domain': 'lex18.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 123,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541460833.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9uehti',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'wickedbadnaughtyZoot',
     'num_crossposts': 0,
     'num_comments': 183,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9uehti/coroner_woman_dies_after_pit_bull_attack_in_clark/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://lex18.com/news/covering-kentucky/2018/11/05/coroner-woman-dies-after-pit-bull-attack-in-clark-co/',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541432033.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_11vvub',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': "Mac Miller's Cause of Death Revealed, Fentanyl and Cocaine to Blame",
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': True,
     'name': 't3_9ueums',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 123,
     'domain': 'usmagazine.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 123,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541463269.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9ueums',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'irvw',
     'num_crossposts': 0,
     'num_comments': 86,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9ueums/mac_millers_cause_of_death_revealed_fentanyl_and/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.usmagazine.com/celebrity-news/news/mac-millers-cause-of-death-revealed/',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541434469.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_g8lad',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'Driver Was Huffing Before Girl Scout Hit-And-Run',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9uefvv',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 110,
     'domain': 'keloland.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 110,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541460462.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9uefvv',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'lescrivens',
     'num_crossposts': 1,
     'num_comments': 57,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9uefvv/driver_was_huffing_before_girl_scout_hitandrun/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.keloland.com/news/national/driver-was-huffing-before-girl-scout-hit-and-run/1573960518',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541431662.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_kixq1',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'K9 Officer killed in line of duty in St. Clair Shores, Michigan',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9uaqvn',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 107,
     'domain': 'fox2detroit.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 107,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541423025.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9uaqvn',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'throwawaythangoaway',
     'num_crossposts': 0,
     'num_comments': 52,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9uaqvn/k9_officer_killed_in_line_of_duty_in_st_clair/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'http://www.fox2detroit.com/news/local-news/st-clair-shores-k9-officer-killed-according-to-city-officials',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541394225.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_y0nlc',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'Air Force mascot falcon injured in prank by rival Army',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9udxm0',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 99,
     'domain': 'nbcnews.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 99,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541456902.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9udxm0',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'bustead',
     'num_crossposts': 1,
     'num_comments': 26,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9udxm0/air_force_mascot_falcon_injured_in_prank_by_rival/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.nbcnews.com/news/us-news/air-force-mascot-falcon-injured-prank-west-point-n931216',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541428102.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_my78q',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': "Georgia's Brookwood High School band spells out racial slur with instrument covers during half-time show",
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9ueg9s',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 95,
     'domain': 'cbsnews.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 95,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541460536.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9ueg9s',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'crispy_attic',
     'num_crossposts': 0,
     'num_comments': 80,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9ueg9s/georgias_brookwood_high_school_band_spells_out/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.cbsnews.com/news/gwinnett-county-georgia-brookwood-high-school-band-spells-out-racial-slur-with-instrument-covers-during-half-time-show/',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541431736.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_14f4n0',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'Swiss talk with U.S., Iran about humanitarian payment channel for food, drugs',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9ucoa8',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 86,
     'domain': 'reuters.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 86,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541445280.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9ucoa8',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'StronglyWeihrauch',
     'num_crossposts': 0,
     'num_comments': 7,
     'send_replies': False,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9ucoa8/swiss_talk_with_us_iran_about_humanitarian/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.reuters.com/article/us-usa-iran-sanctions-swiss/swiss-talk-with-u-s-iran-about-humanitarian-payment-channel-for-food-drugs-idUSKCN1NA12Y',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541416480.0,
     'media': None,
     'is_video': False}},
   {'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_iid7osh',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': 'Social Network Gab is Back Online 1 Week after Being De-Platformed by GoDaddy',
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9ueal5',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 57,
     'domain': 'bbc.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 57,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541459461.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9ueal5',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'bangkokscenes1024',
     'num_crossposts': 0,
     'num_comments': 148,
     'send_replies': True,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9ueal5/social_network_gab_is_back_online_1_week_after/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.bbc.com/news/technology-46097048',
     'subreddit_subscribers': 16909592,
     'created_utc': 1541430661.0,
     'media': None,
     'is_video': False}}],
  'after': 't3_9ueal5',
  'before': None}}

So 25 is too many stories to handle? Well the API allows you to include a query string parameter for story limit. This example shows you can combine the headers and params named arguments if your API requires it. This is true for any function call with named arguments, BTW.

In this example we return just one 1 story!

In [86]:
web_api_url = 'https://www.reddit.com/r/news/top.json'
custom_headers = {'User-Agent' : 'sample-python-application'}
options = { 'limit' : 1 }
response = requests.get(web_api_url, headers = custom_headers, params = options)
response.json() 
Out[86]:
{'kind': 'Listing',
 'data': {'modhash': '',
  'dist': 1,
  'children': [{'kind': 't3',
    'data': {'approved_at_utc': None,
     'subreddit': 'news',
     'selftext': '',
     'author_fullname': 't2_ce1jm',
     'saved': False,
     'mod_reason_title': None,
     'gilded': 0,
     'clicked': False,
     'title': "Jury Orders 'Miracle Cure Doctor' to Pay $105 Million to Cancer Patient",
     'link_flair_richtext': [],
     'subreddit_name_prefixed': 'r/news',
     'hidden': False,
     'pwls': 6,
     'link_flair_css_class': None,
     'downs': 0,
     'parent_whitelist_status': 'all_ads',
     'hide_score': False,
     'name': 't3_9u7cwx',
     'quarantine': False,
     'link_flair_text_color': 'dark',
     'author_flair_background_color': None,
     'subreddit_type': 'public',
     'ups': 41605,
     'domain': 'nbcsandiego.com',
     'media_embed': {},
     'author_flair_template_id': None,
     'is_original_content': False,
     'user_reports': [],
     'secure_media': None,
     'is_reddit_media_domain': False,
     'is_meta': False,
     'category': None,
     'secure_media_embed': {},
     'link_flair_text': None,
     'can_mod_post': False,
     'score': 41605,
     'approved_by': None,
     'thumbnail': '',
     'edited': False,
     'author_flair_css_class': None,
     'author_flair_richtext': [],
     'gildings': {'gid_1': 0, 'gid_2': 0, 'gid_3': 0},
     'content_categories': None,
     'is_self': False,
     'mod_note': None,
     'created': 1541396014.0,
     'link_flair_type': 'text',
     'wls': 6,
     'banned_by': None,
     'author_flair_type': 'text',
     'contest_mode': False,
     'selftext_html': None,
     'likes': None,
     'suggested_sort': None,
     'banned_at_utc': None,
     'view_count': None,
     'archived': False,
     'no_follow': False,
     'is_crosspostable': False,
     'pinned': False,
     'over_18': False,
     'media_only': False,
     'link_flair_template_id': None,
     'can_gild': False,
     'spoiler': False,
     'locked': False,
     'author_flair_text': None,
     'visited': False,
     'num_reports': None,
     'distinguished': None,
     'subreddit_id': 't5_2qh3l',
     'mod_reason_by': None,
     'removal_reason': None,
     'link_flair_background_color': '',
     'id': '9u7cwx',
     'is_robot_indexable': True,
     'report_reasons': None,
     'author': 'todayilearned83',
     'num_crossposts': 3,
     'num_comments': 1153,
     'send_replies': False,
     'mod_reports': [],
     'author_patreon_flair': False,
     'author_flair_text_color': None,
     'permalink': '/r/news/comments/9u7cwx/jury_orders_miracle_cure_doctor_to_pay_105/',
     'whitelist_status': 'all_ads',
     'stickied': False,
     'url': 'https://www.nbcsandiego.com/news/local/Jury-Orders-Miracle-Cure-Doctor-to-pay-105-Million-to-Cancer-Patient-499354851.html',
     'subreddit_subscribers': 16909626,
     'created_utc': 1541367214.0,
     'media': None,
     'is_video': False}}],
  'after': 't3_9u7cwx',
  'before': None}}

HTTP Posts

Some web API's require you to send a substantial amount of data to them. In this case an HTTP POST a more appropriate request than a GET. For example to get sentiment from text through the text-processing web API, you must include the text as part of the data payload. We accomplish this through the requests.post() function and the data = payload named argument:

In [90]:
tweet = "I dislike the Voice. I will not be sad when that show is cancelled. Horrible!"
web_api_url = 'http://text-processing.com/api/sentiment/'
payload = { 'text' : tweet }
response = requests.post(web_api_url, data = payload)
response.json()
Out[90]:
{'probability': {'neg': 0.7638937484899654,
  'neutral': 0.021024021628106692,
  'pos': 0.23610625151003461},
 'label': 'neg'}

Concuding Remarks - API Authentication

We've demonstrated the most common ways Web API's are called in Python. What we haven't discussed is API's which require authentication (a verification of your identity prior to consuming the web API).

Most of the web API's you will likely use in your project will require authentication. You must first sign up for the API on their website and in exchange some personal information you will be issued an API key. This key is required to send requests to the API so they can track how many requests you are making.

How exactly the API Key is used depends on the provider of that API. We have, however, demonstrated the possible ways you might need to include the key: in the URL, on the Query String, or in the HTTP Headers. There is no one way to call every API and thus you will need to read the documentation and play around with your code in order to learn how to correctly authenticate to the API and retrieve a valid response.

Lots of trial and error are required, so be persistent! We expect everyone to suffer through this process as part of what it takes to complete your demo day project. This shows us you are capable of learning new things independently and thus are ready to handle the next great thing Python throws our way!