As one of my first Python projects, I created Bob, a Ywitter bot that posts inspirational quotes to my Twitter.
Bob pulls a quote from theysaidso.com every day at 8 a.m. to give inspiration to everyone on my Twitter feed.
Over the last couple of months, I’ve been teaching myself machine learning and data science in an effort to become a data scientist. The journey has been really fun, and I absolutely love it.
However as I’ve been tackling different data-science projects, I realized I need to learn more about Pythonic code in order to effectively traverse and manipulate data sets. So over the next month, I’ll be reading “Fluent Python,” while tackling a book on statistics to prepare myself to kick it into high gear with machine-learning algorithms.
Projects are important for learning, and I decided my bot was due for an upgrade because I made it all the way in July.
Looking back at the code, I was horrified — there were just functions created all over the place. Now that I understand a bit more about the object-oriented nature of Python, I thought it would be a good opportunity to refactor my bot and use it to make my life easier. The internet is huge, and there are so many free resources. I thought it would be an interesting idea to use Bob to search Twitter for free machine-learning resources and then text me the links.
The full code for both Bob 1.0 and 2.0 can be found in my GitHub repository:
How is Bob Getting an Upgrade?
In general, creating classes can help keep code neat and readable as it helps with the separation of concerns.
You can create a class to store data then create methods to act on that data so everything can be found in one place.
To refactor this code, I think it would be a good idea to create a
‘TwitterAccount’ class where all the methods relating to the Twitter account would go.
For the this specific bot, I’ll need a method to access my Twitter account through Tweepy, to post the inspirational quotes, and then to create a new method to search for tweets about free machine-learning resources. We’ll need a way to initialize the class and a method to access the Twitter account.
self.consumer_key = consumer_key
self.access_token_secret = access_token_secret
auth = tweepy.OAuthHandler(self.consumer_key,self.consumer_secret) auth.set_access_token(self.access_token,self.access_token_secret) return tweepy.API(auth) # returns api object
Here I created a
TwitterAccount class with the information it needs to access the account: the access and consumer keys.
The access method returns an API object that is used to communicate with the Twitter account by using these keys.
Now we need to make more methods to post a quote then search through tweets. Posting the quotes is pretty simple, as it’s just an extension of previous code we had for Bob 1.0:
self.access().update_status('"%s." \n-%s \n\n Daily Inpsiration From Bob the Twitter Bot' % (quote_details))
Just as before, the quote details is going to be a function that makes a request to theysaidso.com for their quote of the day and just pulls the quote information from the corresponding JSON.
response = requests.get(url)
quote_info = json.loads(response.content).get('contents').get('quotes') quote = quote_info.get('quote')
author = quote_info.get('author')
The function above will return the
quote_details that we’ll feed into the
TwitterAccount.post() method. Now all we have to do is figure out how to search Twitter for specific tweets and then text message those tweets to myself at a specific time during the day.
Using Python to Send Text Messages
The next part I thought was important was to figure out how to use Python to send text messages. After figuring that out, I could read the documentation on using Tweepy to search Twitter.
I went to YouTube to find videos on how to use Python to send text messages, and Amazon Web Services has a Simple Notification Service (SNS) where you can send text messages.
You create an account (you can get up to 12 months of service free), and register a user for the SNS.
Then install the AWS CLI to set up your credentials, and when you run your script, the program will be able to use these credentials to send out messages.
The module that we use to send out these messages it Boto 3, so you’ll need to pip install that from your command line. After setting up your credentials, import Boto 3. The code to send a message is only two lines.
import boto3client = boto3.client('sns',region_name='us-east-1')client.publish(PhoneNumber='', Message='')
You choose a region based on where you’d like to send the message from and store it in the client variable. Then you just apply the publish method to send out a SMS text to the respective phone number. Now that we have this figured out, let’s see how we can search Twitter using Tweepy.
Using Tweepy to Search for Tweets
Tweepy has many methods that allow you to interact with your Twitter account. There are some that allow you to follow users, check your timeline, search for hashtags, and much more.
I did some tests on the Twitter website prior to writing the code just to get an idea of the output when searching for various topics.
I noticed that when I searched for words like “machine learning” or “data science,” I’d get all tweets that included those words (of course). Then I tried searching for hashtags instead, and those results were more in line with what I wanted. It was mainly professionals posting about trends and resources.
We have our search item, so let’s figure out how we can actually use Tweepy to search.
tweepy.Cursor is commonly used to search Twitter using different search queries. It’ll return a cursor object,, and we just have to pull the text from these objects to get our tweets.
Since this is something we’d do on our Twitter account, it’s appropriate to add this as a method to our
def search_hashtags(self,hashtags): #returns a cursor object tweets = tweepy.Cursor(self.access().search,q=hashtags,result_type='recent'). items(100) tweet_info = [tweet.text for tweet in tweets] return tweet_info
tweepy.Cursor takes several arguments — the first being the action we want our bot to do which is search Twitter.
q argument is the search item, and we can filter the search by the most recent 100 posts.
We then perform a list comprehension to pull the text from each of the tweets that is in our cursor object.
Now I don’t want all of these 100 tweets, so I’ll filter these based on some keywords that’ll help me find free machine-learning resources. For that, I think we should add another method to the
def filter_feed(self): search_word = '#MachineLearning -filter:retweets' filter_words = ['free','course','book','eBook'] cs_tweets = self.search_hashtags(search_word) text_tweets = for filters in filter_words: for tweets in cs_tweets: if filters in tweets: text_tweets.append(tweets)return text_tweets[:5]
We have our search word, which is #MachineLearning, and we’ll filter out all retweets so we don’t return repeating posts. I primarily want to search for resources that are free, either a book or some course.
We’ll use nested for loops to loop each filter word over every tweet and just return the tweets that contain those filter words. I’m sure there’s a more efficient way to check for these filter words in the tweets, but that’s the solution I came up with for now. Bob will definitely get another upgrade!
Then we just return up to five tweets, and we’ll use this list to send our text messages.
The Finishing Touches on Bob 2.0!
We have everything we need to upgrade Bob, and now we just have to fill in the pieces of the puzzle. First we need to change the previous algorithm a bit and figure out a time to send these text messages out.
The new algorithm looks like:
TwitterAccount = TwitterAccount(consumer_key,consumer_secret,access_token,access_token_secret)while True: t = check_time() if t == '08:00 AM' or t == '08:01 AM': print(t,flush=True) TwitterAccount.post(get_quote(url)) time.sleep(61) elif t == '17:00 PM' or t =='17:01 PM': text_tweets = TwitterAccount.filter_feed() for tweets in text_tweets: client = boto3.client('sns',region_name='us-east-1') client.publish(PhoneNumber='', Message=tweets) time.sleep(61) else: t = check_time() print(t,flush=True) print('It\'s not time yet',flush=True) time.sleep(50)
First we initialize a Twitter account class and create an infinite loop because this program will run forever.
It’ll check the time every 50 seconds, and if it’s 8:00 a.m., it’ll post a quote to my Twitter. If it’s 5:00 p.m., it’ll search Twitter and send me the free resources.
I’m going to take this next month to really hammer in statistical principles for machine learning and data science.
My main focus will be improving my Python, which I believe in turn will help with creating efficient code to perform data analysis. I’ll still be doing my machine-learning projects, but it’ll be at a slower rate for now.
Stay tuned for our next Python project.