In order to make a Twitter bot, you will need to use something called Tweepy. But Tweepy doesn’t come with Python by default. So you will need to use PyPi to install it.
In a terminal window, use the following command:
pip install tweepy
For more information about PyPi, check this site out:
Please note: on some systems, pip means pip3. On others, pip means pip2. So in some cases, you could do something like “pip install tweepy” and then you get an error about your python program not being able to use a dependency (such as tweepy or any others), but that’s because it’s installed for the wrong version of Python. So in that case, you’d need to do pip3 install tweepy instead. If that doesn’t work, then first you will need to do sudo apt-get install python-pip3 and then do pip3 install tweepy. If you ever get an error about permissions, it means you have to run the program again but with sudo in front of it. You will be prompted to enter your password to proceed.
If you’re annoyed by this confusing split between Python 2 and Python 3, you’re not alone! It’s an annoying software problem called fragmentation, meaning users are split between many different versions of the same software. The concept of fragmentation comes up a lot in Android too, as many people are still using very old versions of Android because their phones don’t get software updates.
If you have an issue with an IDE like PyCharm not being able to find tweepy, then just use a terminal window, like Git Bash on Windows or the Terminal app on macOS, and then type this to run your twitter program:
python tweet.py
Or:
python3 tweet.py
Please note that you will only be able to run a command line python3 myprogram.py if you’re in the directory you made your file in. So if your program is in a folder (directory) like C:\Some\Directory\myprogram.py or /home/yourname/Desktop, you will have to change your directory first, like so:
Unix shells:
cd /home/yourname/Desktop
Windows command prompt:
dir C:\Some\Directory\
For more information about command line stuff, see chapter 8, which covers all sorts of useful command line stuff.
My computer’s path variable is set up so that python means python3. But it’s common for other computers to have python mean python2, which is not what you want.
You also need a Twitter account in order to use the Twitter API. You can make one here if you don’t have one already:
I recommend using a separate dedicated bot account rather than making a Twitter bot that uses your main account. I once made the mistake of using my main account and then I had to transfer it, and it takes a while for Twitter to get back to you to do that. So make a separate account, like weatherbot456 or something.
A Twitter account alone isn’t enough though. You will also need to get an API key from Twitter so that you can use the API and your account to send tweets. There are plenty of other things you can do with their API, but for now I’m going to keep it simple and focus on making a simple program that sends a tweet.
This page has info on how to get Twitter API access tokens:
Remember: access tokens, keys, etc are just like passwords! Don’t make them public! Don’t put them on Twitter or GitHub!
Go here to get access tokens:
Click on “create an app.”
Then click “apply” to apply.
Then click “student” if you’re a student, or a hobbyist category if you’re not.
You will need a phone number associated with your Twitter account and it must be verified before you can start with using the Twitter API. Phone numbers are verified with text message codes.
On the application page, after you’ve selected “student” you still need to fill out a couple things.
You will need to select which country you live in, and also your name. I just put my first name rather than my full name. You can also optionally get email updates about Twitter stuff.
Once you’re all done, hit “next.”
Then you will need to write an explanation of why you want to use the API.
Here’s what I wrote in my own Twitter API application:
Are you planning to analyze Twitter data? No
Will your app use Tweet, Retweet, like, follow, or Direct Message functionality? Yes
“I will only use tweet functionality, and I will use it for sending weather data. My first test will just be making a tweet that says “I sent this tweet from my Python program” and that’s it. But I am planning on making a weather account. I am only going to send tweets, not do anything else. I am going to use Python and Tweepy.” (Don’t copy this verbatim)
Do you plan to display Tweets or aggregate data about Twitter content outside of Twitter? No
Will your product, service or analysis make Twitter content or derived information available to a government entity? No
Once you’re done filling out the questions, hit “next.”
Then click “looks good” after reviewing your application information.
Then review the developer agreement, click to accept, and then hit “submit application.”
Then you will get a developer confirmation email sent to the email address associated with your Twitter account. You will need to click the link in the email to accept it.
From there, you should see the “#welcome” page. From there, click “create an app.” Then click “create an app” again.
Here’s what I filled out for my Twitter app:
App name: WeatherBotChicago (put your city in the name if you want to follow along and make a Python/OpenWeatherMap/Twitter bot project). You can only choose a name that hasn’t been used by someone else. Also, please note that there might not be weather data for very small towns. Just bigger cities.
Application description: “This is an educational project for learning more about APIs. It tweets about the weather in Chicago.” (Write your own answer here)
Website URL: I put my saintlouissoftware.com site there, but if you don’t have your own domain name, use something like github.com/your_username_here.
None of the following fields are required aside from the last one:
Tell us how this app will be used: “This is a project I’m using to learn more about software development and APIs. I will use the Twitter API in conjunction with a weather API to tweet about the weather where I live. I’m going to make it in Python. there are no customers for this app because it’s a personal/educational project.” (Write something similar but in your own words)
Then click “create” and then read and review the developer terms. You might want to read the “automation” section because it applies to this kind of project. Then click “create.”
Finally, you can now get keys and tokens to actually make the Twitter bot. Click the “keys and tokens” tab.
If you close your browser tab and ever want to find your app page again to look at tokens and whatnot, go here:
On the keys and tokens page, you will find an API key and an API secret key. But you will also need an access token and access token secret.
If you want to view your timeline using Tweepy and Python, use this code:
import tweepy
consumer_key = “REPLACEME”
consumer_secret = “REPLACEME”
access_token = “REPLACEME”
access_token_secret = “REPLACEME”
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)
public_tweets = api.home_timeline()
for tweet in public_tweets:
print(tweet.text)
Viewing your Twitter timeline is an example of using an API to get data, but in the following weather project code, I am using the API to send data. You can eventually make interactive apps that combine sending and receiving data, such as making a Twitter bot that responds to other tweets.
For the key, secret, token, and token secret, you will need to do something like put in your own keys, though many people think that’s bad because it’s less secure. Or you can store them in a separate config file, which is what I do. This is safer if you plan on putting your code on GitHub. You can use something called .gitignore to not upload your secret key info to GitHub. More on .gitignore in the GitHub chapter though.
If you want to send a tweet, use this code:
import tweepy
consumer_key = “REPLACEME”
consumer_secret = “REPLACEME”
access_token = “REPLACEME”
access_token_secret = “REPLACEME”
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)
api.update_status(‘I sent this tweet using Python and the Twitter API!’)
An oversimplified explanation of this is that you basically need 4 passwords (API keys and tokens) to use the API. People who know a lot about authentication might say that’s not a good explanation, but for beginners, don’t delve too deep into authentication. Just know that keys and tokens give you access. You can’t use an API without them, and it’s generally a bad idea to share them with other people.
Without further ado, here is the full code for the weather bot I made (and don’t worry, there is an thorough explanation of what it does after the code):
# Alan’s Weather bot for Twitter
# You will need API keys for Twitter and OpenWeatherMap
# copy twitter_api_example.json to twitter_api.json
# and put your keys/tokens in there
# copy weather_api_example.json to weather_api.json
# and put your openweathermap api key there
# .gitignore will ignore the real config files with your keys
# don’t put then on github!
import sys
import os
import tweepy
import urllib.request
import json
import datetime
import time
# function for checking if a key is not properly loaded
# return true = key is good
# return false = key is bad
def check_loaded(key):
return (not ((key == “NOTLOADED”) or (key == “”)))
def main():
# three tweets per day with different wait times between each
# 1 is at 6am, 2 is at noon, 3 is at 6pm
tweet_num = 2
while True:
# variables for keys
consumer_key = “NOTLOADED”
consumer_secret = “NOTLOADED”
access_token = “NOTLOADED”
access_token_secret = “NOTLOADED”
weather_api_key = “NOTLOADED”
# variables for key file names
# if you use encrypted storage, you might want to change these
twitter_file = “twitter_api.json”
weather_file = “weather_api.json”
# check if required json files exist
files_exist = (os.path.exists(weather_file) and os.path.exists(twitter_file))
weather_api_json = “”
twitter_api_json = “”
if files_exist:
print(“Passed initial file checks”)
# loading weather api key from file
try:
with open(weather_file, “r”) as fopen:
weather_api_json = json.load(fopen)
weather_api_key = weather_api_json[“api_key”]
except IOError:
print(weather_file + ” IOError”)
sys.exit()
print(“Finished loading Weather key”)
# loading twitter_api_keys from file
try:
with open(twitter_file, “r”) as fopen:
twitter_api_json = json.load(fopen)
consumer_key = twitter_api_json[“api_key”]
consumer_secret = twitter_api_json[“api_secret_key”]
access_token = twitter_api_json[“access_token”]
access_token_secret = twitter_api_json[“access_token_secret”]
except IOError:
print(twitter_file + ” IOError”)
sys.exit()
print(“Finished loading Twitter keys”)
# checking stuff got loaded correctly
check1 = check_loaded(consumer_key)
check2 = check_loaded(consumer_secret)
check3 = check_loaded(access_token)
check4 = check_loaded(access_token_secret)
check5 = check_loaded(weather_api_key)
keys_valid = check1 and check2 and check3 and check4 and check5
if keys_valid:
print(“Keys passed check”)
# Twitter API authentication using Tweepy
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)
print(“Successfully authenticated”)
# got some help from here: https://stackoverflow.com/questions/12965203/how-to-get-json-from-webpage-into-python-script
# piecing together API request for weather data
api_request_first_part = “https://api.openweathermap.org/data/2.5/weather?q=”
api_request_location = “Chicago”
api_key_part = “&appid=”
api_request_units = “&units=imperial”
# “weather” is the full API call
weather = api_request_first_part + api_request_location + api_key_part + weather_api_key + api_request_units
# downloading weather json data
with urllib.request.urlopen(weather) as url:
json_data = json.loads(url.read().decode())
print(“JSON data:”)
print(json_data)
print(“Finished downloading weather data”)
# getting data from the json
# some of which is nested multiple times
main_json = json_data[“main”]
temp = main_json[“temp”]
weather_json = json_data[“weather”]
temp_min = main_json[“temp_min”]
temp_max = main_json[“temp_max”]
humidity = main_json[“humidity”]
wind = json_data[“wind”]
wind_speed = wind[“speed”]
description_json = weather_json[0]
description = description_json[“description”]
print(“Building tweet string”)
now = datetime.datetime.now().strftime(“%I:%M%p”)
# building the tweet text
first_string = “As of ” + now
first_string += “, it is currently ” + str(int(temp)) + ” F in Chicago. High of “
first_string += str(int(temp_max)) + ” F and low of ” + str(int(temp_min)) + ” F. “
first_string += str(int(humidity)) + “% humidity. “
first_string += str(int(wind_speed)) + ” mph wind. “
second_string = “The weather is ” + description + “.”
final_tweet = first_string + second_string
# send the weather tweet
api.update_status(final_tweet) #send tweet
current_time = datetime.datetime.now().strftime(“%I:%M%p on %B %d, %Y”)
print(“Sent the following tweet at ” + current_time + “”)
print(“\”” + final_tweet + “\””)
# tweet scheduling stuff
# 1 = 6am, 2 = noon, 3 = 6pm
if tweet_num == 1:
# wait 6 hours before tweeting again
time.sleep(21600)
tweet_num = 2
elif tweet_num == 2:
# wait 6 hours before tweeting again
time.sleep(21600)
tweet_num = 3
elif tweet_num == 3:
# wait 12 hours before tweeting again
time.sleep(43200)
tweet_num = 1
else:
print(“error”)
sys.exit()
else:
print(“missing api key files”)
if __name__ == ‘__main__’:
try:
main()
except KeyboardInterrupt:
print(“\nQuitting. Goodbye.”)
sys.exit()
The end result is that the Twitter bot sends tweets that look like this:
As of 06:19AM, it is currently 71 F in Chicago. High of 75 F and low of 68 F. 78% humidity. 5 mph wind. The weather is scattered clouds.
To see the bot in action, go here: https://twitter.com/ChiWeather
That’s a pretty long program compared to previous examples, but it’s essentially a “capstone” project for this chapter. It combines many different programming and Python concepts into a big project that helps you understand how little pieces all fit together. It can be hard to think about exception handling, loops, etc. until you see a real-world demonstration of it.
To see the code on GitHub, go here:
More info on GitHub in chapter 9 though.
I commented the code to try and make it easier to read, so hopefully you can at least get what the different sections of code do. All single-line comments start with #.
import sys
import os
import tweepy
import urllib.request
import json
import datetime
import time
Firstly, all the imports add extra functionality to the program. Because of using sys.exit() (which closes the program), I had to import sys. And os is used for operating system stuff. In this case, I am using it for something that checks if a file exists. tweepy makes it easy to make a Twitter bot, so that’s why it’s imported. urllib.request is used for downloading the weather data. json is used for dealing with JSON data. In this case, the weather data from the weather API is structured as JSON, which is a data exchange format, similar to things like XML or GraphQL. datetime is used because the tweets include the time. That might sound unnecessary, because you can see when tweets are made, but here’s the thing: the API won’t let you send duplicate tweets. So what if the weather doesn’t change? The API would give you an error and then the program would stop running. So adding the time makes it much less likely that your weather bot will send two tweets with the same text in a short amount of time. In this case, I made the Twitter weather bot send 3 tweets per day. time might sound like it’s similar to datetime, but it’s not. I use the time module for sleep, which means making the program pause and wait a certain amount of time.
Moving on, there’s the check_loaded() function:
def check_loaded(key):
return (not ((key == “NOTLOADED”) or (key == “”)))
It checks if the API keys/tokens have been loaded properly or not. I made key string variables that have a default value of “NOTLOADED” as a placeholder, and then I load the actual keys from a file. But if there’s something wrong with the keys being loaded, or they don’t get loaded at all, then this function will return False. If the keys were loaded properly, it will return True. The main() calls this function and will only proceed if it returns True. It takes just one string argument, so the way I designed it requires calling it once per key to check, which I guess I could’ve made more efficient, but oh well. In total, this program has to check 5 keys – the 4 keys for Twitter and the one key for the weather API. So the function gets called 5 times in total.
Next up is the main() function:
def main():
#removed for brevity
if __name__ == ‘__main__’:
try:
main()
except KeyboardInterrupt:
print(“\nQuitting. Goodbye.”)
sys.exit()
Just boilerplate stuff, which was covered earlier in the chapter. Notice how I am going by levels of code blocks rather than from the first line of code to the last.
I made three scheduled times for when the program tweets, as 3 per days seems good but isn’t so much that it’d be considered spammy.
Within the main(), there’s a variable for keeping track of which tweet it is, because there are different times that it should tweet.
tweet num = 2
I set it up so that the 1st tweet is at 6am, the 2nd is at noon, and the 3rd is at 6pm. This is all going by central time because it’s in Chicago. I set it to 2 to indicate that I started the program at noon. That’s when I ran the program on my server and now it’s set to run 24/7. There are probably better ways of scheduling tweets at certain times, but I chose to use a really simple way instead of doing something more complicated.
tweet num = 2
while True:
#removed for brevity
while True: is an infinite loop (because a loop will run an iteration if the condition evaluates to True, and True is always True), which is usually bad, but it’s actually what I want in this case because it means I can set up the program once and it will tweet for as many days as I want with no additional effort. I could leave it for another month and it would still tweet 3 times a day. In general, infinite loops can be bad, but I’m okay with using one here.
Towards the end of the infinite loop, you will notice the scheduling code:
if tweet_num == 1:
# wait 6 hours before tweeting again
time.sleep(21600)
tweet_num = 2
elif tweet_num == 2:
# wait 6 hours before tweeting again
time.sleep(21600)
tweet_num = 3
elif tweet_num == 3:
# wait 12 hours before tweeting again
time.sleep(43200)
tweet_num = 1
else:
print(“error”)
sys.exit()
If tweet_num is 1, it will wait 6 hours (21600 seconds) before looping again, because the difference between 6am and noon is 6 hours. Then it will set the tweet_num variable to 2 to indicate that it’s the second tweet of the day. If tweet_num is 2, it will wait another 6 hours and then change the tweet number to 3. The difference between noon and 6pm is 6 hours, or 21600 seconds. The numeric argument provided to time.sleep() is in seconds. When tweet_num finishes the third tweet, it will sleep for 12 hours or 43200 seconds, because the time between 6pm and 6am is 12 hours. It also sets the tweet_num back to one, thus resetting the daily tweet cycle for another day of tweets. One limitation of this system of scheduling is that you have to start the program at either 6am, noon, or 6pm. That’s why I made it so that you can set the tweet_num at the beginning of the program. I set it to tweet_num = 2 because I ran the program on my server around noon.
Task scheduling is a complicated subject, and some task scheduling is specific to an OS. So Windows task scheduling is different from Linux task scheduling. For that reason, I decided to go with my more primitive sleep solution, even if it isn’t necessarily a best practice. At least it works on all operating systems. Sometimes, task scheduling is done with an OS rather than the program itself, or it can be a module that checks the current time and then does things if it’s a certain time. But I wanted to make it easy to understand and not add unwanted complexity. I just didn’t want to inundate the reader with too much OS-specific technical minutiae as I’m trying to keep this book as multi-platform as possible.
Moving on, within the infinite loop, towards the top, string variables for keys are declared with placeholders:
# variables for keys
consumer_key = “NOTLOADED”
consumer_secret = “NOTLOADED”
access_token = “NOTLOADED”
access_token_secret = “NOTLOADED”
weather_api_key = “NOTLOADED”
# variables for key file names
# if you use encrypted storage, you might want to change these
twitter_file = “twitter_api.json”
weather_file = “weather_api.json”
Also, please note that in order to run this program, within the GitHub repository, you first need to copy the twitter_api_example.json file to twitter_api.json, and change the weather_api_example.json file to weather_api.json. You then need to fill in the keys by opening the .json files in a text editor. I did this so that I wouldn’t accidentally upload my private keys to GitHub. I use something called .gitignore in my GitHub repository, which means that git won’t upload files that I specifiy within .gitignore. In this case, my .gitignore is set to ignore twitter_api.json and weather_api.json in order to protect your secret credentials from being uploaded to GitHub. Within these files, they are JSON and you need to replace the values with your actual keys. Here’s what the JSON files look like:
weather_api.json:
{
“api_key”: ” REPLACEME”
}
twitter_api.json:
{
“api_key”: “REPLACEME”,
“api_secret_key”: “REPLACEME”,
“access_token”: “REPLACEME”,
“access_token_secret”: “REPLACEME”
}
You will need to put your keys in there. If you wanted added security, you could even encrypt the .json files containing keys, and then make the program have the user enter in a decryption key when they run the program, leaving no keys in files easily accessible except if an attacker could view the contents of your RAM. But because that adds extra complexity to this project, I decided to leave it out, as it is already long enough as it is. But encrypting credentials is something you should consider for your own projects. You can’t send encrypted credentials to a server – you need to decrypt them first. The transport should use encryption, but that’s different. What I mean is that the request you make to the API needs to have the unencrypted stuff, but you can still encrypt things when they’re stored. Long story short, storing keys in a secure way is important but more complicated.
This line checks if the required JSON files exist:
files_exist = (os.path.exists(weather_file) and os.path.exists(twitter_file))
os.path.exists() will return True if a file path exists. So it’s a way to see if there’s a required file for a program. exists() takes a string argument, which is the path to a file.
The Boolean is stored to a variable to be used in the next conditional:
if files_exist:
#removed for brevity
else:
print(“missing api key files”)
In this case, if the required API key/token files are all good, then the program proceeds. If not, it lets you know there was an error and then quits the program.
Within the if file_exists block of code, it first starts by loading the weather API key from weather_api.json, like so:
try:
with open(weather_file, “r”) as fopen:
weather_api_json = json.load(fopen)
weather_api_key = weather_api_json[“api_key”]
except IOError:
print(weather_file + ” IOError”)
sys.exit()
try/except is exception handling. There could be an issue that prevents you from properly opening a file. Maybe it’s corrupted. Maybe you don’t have permission to view it. Maybe it doesn’t exist. Maybe it’s already in use. with open() is a way to open a file, and it automatically closes it after the block is done, though if you just do regular open and close, you will need to specifically do fopen.close() instead. with open() is more convenient.
with open(weather_file, “r”) as open: means to open the file to read it (hence “r”) with the path that is located in the weather_file variable, and it’s opening it as read mode. The name for the file variable is fopen, but you can call it anything if you really want.
The following line takes the file and uses json.load() to parse and load the JSON from weather_api.json (which is fopen) and store it in a variable called weather_api_json:
weather_api_json = json.load(fopen)
From there, the next line gets a specific value from a key in the JSON, as JSON is made up of key-value pairs:
weather_api_key = weather_api_json[“api_key”]
Now that the weather API key has been loaded, it’s time to get the 4 keys/access tokens for the Twitter API:
try:
with open(twitter_file, “r”) as fopen:
twitter_api_json = json.load(fopen)
consumer_key = twitter_api_json[“api_key”]
consumer_secret = twitter_api_json[“api_secret_key”]
access_token = twitter_api_json[“access_token”]
access_token_secret = twitter_api_json[“access_token_secret”]
except IOError:
print(twitter_file + ” IOError”)
sys.exit()
It’s basically the same as getting the weather API key, only this time there are 4 things to get instead of one.
So at this point, all of the keys have been loaded, but not validated. The next lines assign the Boolean output of the check_loaded() function to different variables in order to make sure all of the keys are okay:
check1 = check_loaded(consumer_key)
check2 = check_loaded(consumer_secret)
check3 = check_loaded(access_token)
check4 = check_loaded(access_token_secret)
check5 = check_loaded(weather_api_key)
I should note that my check_loaded() function is very lax when it comes to pattern matching, but in this case, it doesn’t need to be perfect. At the very least, it makes sure that the user changed them from their default values of “NOTLOADED”.
The next line assigns a boolean to a new variable called keys_valid, which will only be True if all of the checks were good, meaning all of the keys were loaded properly and verified:
keys_valid = check1 and check2 and check3 and check4 and check5
Now we’re entering a new block of code:
if keys_valid:
#removed for brevity
If all the keys are valid, it will proceed with the rest of the program. If not, it will just end the program. This will prevent the program from trying to run with invalid keys. But even without this check, the program can’t continue if the keys are invalid because you won’t be able to authenticate for the APIs.
Within the if keys_valid: block, the first thing it does is authenticate with the Twitter API via Tweepy:
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)
This uses the 4 Twitter keys/tokens/secrets that were loaded for JSON. So far, all that has happened is the authentication, not actually making any API calls. That comes later.
Next, the weather API string is built using many different strings that get combined into one:
api_request_first_part = “https://api.openweathermap.org/data/2.5/weather?q=”
api_request_location = “Chicago”
api_key_part = “&appid=”
api_request_units = “&units=imperial”
# “weather” is the full API call
weather = api_request_first_part + api_request_location + api_key_part + weather_api_key + api_request_units
I broke the string up into multiple parts to make it easier to change. For example, if you want to change the location, you just edit the api_request_location string. You don’t have to do it this way, but one benefit is that you break up super long lines into many shorter lines. Don’t put tons and tons of characters on a single line. I once saw someone’s code on GitHub and they had strings that were hundreds of characters, all on single lines. That’s bad for the sake of readability. 80ish should be the max, and even shorter lines are better.
In this case, the one API key from the weather_api.json is being put into the string for requesting the data from the weather API. It’s a little different from how Tweepy authenticates with Twitter. It’s much simpler.
In this weather API case, the API call is a URL with a query string consisting of multiple parameters and values.
Next up, the JSON data gets downloaded:
with urllib.request.urlopen(weather) as url:
json_data = json.loads(url.read().decode())
print(“JSON data:”)
print(json_data)
This is another with open(), but for downloading a remote file rather than a local file on a computer. But you will notice the resemblance to the previous JSON file opening code. urllib is a library for URLs and networking stuff. In this case, it’s downloading data using the URL that was made using the strings in the previous code, and it uses url.read().decode() to convert the downloaded data into something that can be parsed by json.loads(), and it’s then stored in the variable json_data. Unlike the Java weather API demonstration from the last chapter, this only keeps the JSON data in RAM rather than writing it to a file on the local storage.
The next lines parse the json_data for specific things within it. The JSON from the weather API is unfortunately a little weird and uses varying levels of nesting, some being many JSON objects or arrays deep:
main_json = json_data[“main”]
temp = main_json[“temp”]
weather_json = json_data[“weather”]
temp_min = main_json[“temp_min”]
temp_max = main_json[“temp_max”]
humidity = main_json[“humidity”]
wind = json_data[“wind”]
wind_speed = wind[“speed”]
description_json = weather_json[0]
description = description_json[“description”]
The response from the API contains lots of things and only some of it is needed for this particular project. The next line gets the current time and uses strftime() to for time string formatting.
%I means hour, : is a literal :, %M means minute, and %p is for am/pm.
now = datetime.datetime.now().strftime(“%I:%M%p”)
Here is an example of what it can be:
6:23pm
The following lines build the tweet, but it’s not being sent just yet:
first_string = “As of ” + now
first_string += “, it is currently ” + str(int(temp)) + ” F in Chicago. High of “
first_string += str(int(temp_max)) + ” F and low of ” + str(int(temp_min)) + ” F. “
first_string += str(int(humidity)) + “% humidity. “
first_string += str(int(wind_speed)) + ” mph wind. “
second_string = “The weather is ” + description + “.”
final_tweet = first_string + second_string
And lastly, the following line sends the tweet:
api.update_status(final_tweet) #send tweet
You might also notice that I added print() lines here and there. That doesn’t do any tweeting, but it does make it so that I can monitor what’s happening on my server. I periodically check on it to make sure it’s doing what it’s supposed to. While it’s not 100% necessary, it is a basic way of monitoring the status of a program. For more advanced stuff, you might want to log these kinds of messages to a log file rather than just printing them to the terminal, because the terminal text gets lost when the server is powered off or rebooted. But in this case, it’s okay for it to be a little simple.
That was a somewhat long project to make and explain, but you need to see more complex stuff instead of just short 2-3 line code snippets that have no context. Seeing things fit into a bigger program can help you understand the big picture. And you can also use this code to make your own bot. You can make a similar weather bot, or repurpose and modify the code to your liking to make your own Twitter bot. For example, you could edit the code so that you have a bunch of quotes or facts that you like, and then the Twitter bot could tweet them out. Or you could make a bot that analyzes tweet trends about certain topics. There are many possibilities. I hope this chapter inspires you to use APIs and make bots, or at least come up with other interesting and more complex ideas for apps you can make. The possibilities are endless!