Last week in this Noob’s Guide to Twython we covered setting up your Twython for the first time (installing Twython, authenticating with the Twitter API, and Tweeting your first Tweet from Twython). Now we’re going to begin exploring how you can use your Twitter bot to ReTweet.
Reasons to ReTweet
Though the very idea of having a bot automatically ReTweeting things has been corrupted by the mindless Twitter accounts that distribute nothing but spam, the use of a ReTweet bot is not actually against any of Twitter’s terms and conditions. If executed correctly. This is because there’s a whole wealth of value to having a ReTweet bot.
All Twitter cares about is spam. But when not performed for spam, a ReTweet can be a powerful thing. It can be used to promote certain events or news across a wider audience. People’s incentive to follow a ReTweet bot may be to receive Tweets regarding a subject, but wouldn’t want to Follow the original poster on Twitter as they are only interested in very specific Tweets and not everything that user has to say. People can use the hashtag ReTweet bots to follow the hashtag within their stream, so they don’t have to access it via a separate search just to browse.
Other automated ReTweet possibilities could include anyone mentioning your domain or brand name. Of course, you would definitely have to create a negative keyword list to filter out any negative sentiment being expressed toward your brand. Wouldn’t want to be ReTweeting abusive messages about yourself! How unfortunate would that be!
ReTweets are a great method of content discovery, and I can’t tell you how many times I’ve Followed users from seeing a ReTweet of their status. Their Tweet gained my interest, I checked it out and it inspired me to Follow them for more! Similarly, if there’s a big event going on with a promoted hashtag, you could have each Tweet containing that hashtag automatically be ReTweeted via your account. So those at the event can just Follow the user to discover everything that’s going on at the event, and network with other Twitter users who are attending.
Maybe you only want the bot to share only certain hashtagged Tweets from those Following you on Twitter, so you can Follow the account as a consumer or a provider. People will either Follow you because they want the latest news regarding the hashtagged subject, or because they want you to ReTweet their news.
So as you can see, depending on how you are ReTweeting, and for what purpose, a ReTweet bot can be a great central hub of information and a network for open communication and discovery.
Unfortunately, having shared with you now just a tiny portion of the possibilities of a ReTweet bot, there are still going to be some who are only looking to build a bot with the intention of spamming people. This tutorial then might seem a little like handing a child a loaded gun. But I’m going to trust here that you’ll be responsible enough to use this tutorial example to learn and not to go spamming 100 ReTweets an hour. Twitter will ban you. And nobody likes a spammer.
Your First Unnecessarily Difficult ReTweet
So let’s test out this whole ReTweet thing by ReTweeting a single Tweet. Go find yourself something that you want to ReTweet and retrieve it’s status ID. (For the sake of saving a lot of people from getting mildly irritated by your Twitter bot testing, I do suggest you using your own Twitter accounts to test and play with. If you don’t already have another Twitter account, make one, or alternatively you can play with the corpse of an abandoned account that hasn’t had any activity for years. But if it returns as an angry zombie, don’t blame me!
You can find the status ID of a Tweet by clicking on the Tweet so it brings it up as its own page. (Twitter’s a little fiddly. You may want to click “Expand”, and then once the Tweet has expanded, click on “Details”. Once the page is loaded, there you can find the status ID in the page’s URL in the address bar. It should look something like this:
https://twitter.com/YOUR_USERNAME/status/TWEET_STATUS_ID
Replace TWEET_ID with that long number. That long number is the ID. (Your keys, tokens and secrets should still be kept as your actual keys, tokens and secrets throughout all tutorials obviously, as we covered in the tutorial last week.)
from twython import Twython
app_key = "YOUR_APP_KEY"
app_secret = "YOUR_APP_SECRET"
oauth_token = "YOUR_OAUTH_TOKEN"
oauth_token_secret = "YOUR_OAUTH_TOKEN_SECRET"
twitter = Twython(app_key, app_secret, oauth_token, oauth_token_secret)
#ReTweeting by ID of the Tweet
twitter.retweet(id = "TWEET_ID")
Now check your Twitter profile! Has it ReTweeted successfully?
Well, that’s all good and well, but it’s hardly going to be an automatic process if you’re going to be inserting the ID of each Tweet you want to ReTweet by hand each time. Thankfully, you won’t have to!
Dissecting the Search Query
#Import TwythonError now too!
from twython import Twython, TwythonError
app_key = "YOUR_APP_KEY"
app_secret = "YOUR_APP_SECRET"
oauth_token = "YOUR_OAUTH_TOKEN"
oauth_token_secret = "YOUR_OAUTH_TOKEN_SECRET"
twitter = Twython(app_key, app_secret, oauth_token, oauth_token_secret)
#Setting Twitter's search results as a variable
search_results = twitter.search(q="SOMETHING", count=10)
try:
for tweet in search_results["statuses"]:
twitter.retweet(id = tweet["id_str"])
except TwythonError as e:
print e
For someone who’s completely new to Python, picking this up for the first time, that may just look like a strange block of code right now. So let’s break it down to the basics.
Let’s start with search_results. We can read on Twitter’s REST API documentation that search takes a required parameter of q (for query). After all, to use the search results you do actually need to be searching for something. In fact, you can see this for yourself when you do search for something on Twitter. When I perform a search for “southend” (the town in which we here at Silkstream are based – Southend, Essex), you can see in the URL that the search is taking a parameter of q=southend.
So in our code, if we wanted to access the search results for “southend”, we would type:
search_results = twitter.search(q="southend", count=10)
And all that count is for is just to specify how many results we would like to return. In this case: Twitter, I would like exactly ten search results back based on the query “southend” please!
The count is an optional parameter, but a very useful one. Otherwise you might be biting off more than you can chew…
Other optional search parameters include:
- geocode – e.g. “longitude, latitude, radius”
- lang – restricts Tweets to a certain language
- locale – specifies the query’s language
- result_type – return mixed, recent or popular Tweets
- until – returns Tweets generated before the given date
- since_id – returns only Tweets more recent than the given one’s ID
- max_id – returns only Tweets older than the given one’s ID
- include_entities – the entities node will be disincluded when set to false
As you can see, some are more useful than others depending on what it is you’re boiling things down to.
Automatically ReTweeting based on Search Query
So what about:
try:
for tweet in search_results["statuses"]:
twitter.retweet(id = tweet["id_str"])
except TwythonError as e:
print e
In the above bit of Python code here we are asking Twitter to try, for every Tweet’s status in our search results for “SOMETHING”, to ReTweet each Tweet that comes up for that search. Notice how instead of:
twitter.retweet(id = "TWEET_ID")
we are now using:
twitter.retweet(id = tweet["id_str"])
This is because, as you so cleverly pointed out earlier, we can’t sit there all day manually entering the IDs of every Tweet we want to ReTweet. It would be quicker to just use Twitter itself if we were to do that. It’s just plain silly.
Instead we are telling Twitter to identify the ID of each Tweet that pops up in our search results, and insert its ID there as a string. That’s the difference between id and id_str. To set it as a non-string (or an integer) would mean that you are giving the ID a numerical value, which we don’t want. So we want the number to be enclosed in quotation marks, indicating that it is a string. As we would if we were to be typing out the Tweet’s ID to be ReTweeted manually. Which we won’t do, because it’s just plain silly.
And what about that TwythonError?
What does TwythonError do? This is just a generic “catch all” Error exception that will display the issue, should an error occur. For example, if it returns a HTTP status code of 403 in the console, the text will display as “Forbidden” and explain that, though the request was understood, it has been refused or access has not been allowed. You may find that this is due to you having hit a limit of some kind.
Filtering search queries to ReTweet
Sometimes there are words that you will want to prevent from automatically ReTweeting, such as curse words, irrelevant words or words that express a certain sentiment. Or we have a multiple choice of words that we want Twitter to search for, such as a variation of spellings for a keyword and such.
from twython import Twython, TwythonError
app_key = "YOUR_APP_KEY"
app_secret = "YOUR_APP_SECRET"
oauth_token = "YOUR_OAUTH_TOKEN"
oauth_token_secret = "YOUR_OAUTH_TOKEN_SECRET"
#Let's gather a list of words we DON'T want to RT
naughty_words = [" -RT", "Boston", "football", "charlotte", "amos"]
#And a list of words we WOULD like to RT
good_words = ["southend", "southendonsea", "southend on sea"]
#OR is Twitter's search operator to search for this OR that
#So let's join everything in good_words with an OR!
filter = " OR ".join(good_words)
# The - is Twitter's search operator for negative keywords
# So we want to prefix every negative keyword with a -
blacklist = " -".join(naughty_words)
#And finally our list of keywords that we want to search for
#This will search for any words in good_words minus any naughty_words
keywords = filter + blacklist
twitter = Twython(app_key, app_secret, oauth_token, oauth_token_secret)
#This time we want to set our q to search for our keywords
search_results = twitter.search(q=keywords, count=10)
try:
for tweet in search_results["statuses"]:
try:
twitter.retweet(id = tweet["id_str"])
except TwythonError as e:
print e
except TwythonError as e:
print e
So again, let’s take a closer look at everything new we’ve added to our Twitter bot.
So we’ve made an example list of naughty_words, and since for this example we want to be ReTweeting Tweets about Silkstream’s hometown of Southend in Essex, I’ve included negative keywords like “boston”, “charlotte” and “amos” as they tend to be popular keywords used in Tweets containing “Southend” but SouthEnd (or South End) in the United States rather than in Essex, UK.
I’ve also added “football” just for this example (I don’t really care too much about football news myself…) and I’ve also added at the beginning ” -RT”. I don’t want to be ReTweeting ReTweets so it’s important for me to add that. You may also notice that I’ve prefixed it with a ” -“, which as we know is the negative keyword search operator on Twitter. This is because when we joined the naughty_words for our blacklist, it does just that. It joins each item in that list. And since ” -RT” is our first item, it doesn’t add a ” -” to the beginning. So we’ve had to do that manually. Since it’s a one off and the program is just for us, it’s just easier to do it manually for now.
filter = " OR ".join(good_words)
blacklist = " -".join(naughty_words)
keywords = filter + blacklist
We’re using Twitter’s OR operator to join our good_words so that Twitter knows that we’re searching for any Tweet that contains “southend OR southendonsea OR southend on sea”. Which is why our ” OR ” has spaces before and after the OR. So it doesn’t search for “southendORsouthendonseaORsouthend on sea”.
Likewise, as we already covered, our blacklist joins every item in our naughty_words by a ” -“, with a space before the “-” but not after. So Twitter will search for “-RT -Boston -football -charlotte -amos”, and not “-RT-Boston-football-charlotte-amos”.
And finally, our keywords list is just a concatenation of our filter and our blacklist so if we set our search query to keywords, Twitter will be searching for:
southend OR southendonsea OR southend on sea -RT -Boston -football -charlotte -amos
Awesome. So our Twitter ReTweet bot right now should look a little like this:
from twython import Twython, TwythonError
app_key = "YOUR_APP_KEY"
app_secret = "YOUR_APP_SECRET"
oauth_token = "YOUR_OAUTH_TOKEN"
oauth_token_secret = "YOUR_OAUTH_TOKEN_SECRET"
naughty_words = [" -RT", "Boston", "football", "charlotte", "amos"]
good_words = ["southend", "southendonsea", "southend on sea"]
filter = " OR ".join(good_words)
blacklist = " -".join(naughty_words)
keywords = filter + blacklist
twitter = Twython(app_key, app_secret, oauth_token, oauth_token_secret)
search_results = twitter.search(q=keywords, count=10)
try:
for tweet in search_results["statuses"]:
try:
twitter.retweet(id = tweet["id_str"])
except TwythonError as e:
print e
except TwythonError as e:
print e
Next week, we’ll be looking to tinker a little bit more with our Twitter ReTweet bot and really see what this baby can do!
Cannot wait to read the next tutorial.
The next tutorial is up!
And I’m glad you’re enjoying our Noob’s Guide to Twython! :D
Thanks for the tutorial, it’s very easy to read which makes a nice change :)
Now that I have Twython installed and working, I’d like to listen for and reply to direct messages. I’ve seen other people mention this online, but I can not find any way to access direct messages via Twython. Can you possibly shed any light on the best way to achieve this?
Many thanks,
Kelly.
Hi Kelly!
I’m glad you’re enjoying the tutorial. Really trying to make it as simple as possible so anyone can just pick it up with little to no experience.
I haven’t personally played around with direct messages, but I’m aware that:
twitter.get_direct_messages()
will return you the authenticating user’s 20 most recent DMs.
You can find the optional parameters for this function here.
So if you only wanted to receive the last 5 DMs and only the ones that are more recent than the one with the ID of (for example) “12345”:
twitter.get_direct_messages(count=5, since_id=”12345″)
If you’re looking to only return a single DM, you can try:
twitter.get_direct_message(id=”12345″)
If you’re looking to SEND a DM, you need either a screen name or user ID of the recipient, and of course the text to send:
twitter.send_direct_message(screen_name=”recipient”, text=”Hello, recipient!”)
Or you can replace the screen_name=”recipient” with user_id=”12345″.
I hope that helps! :D
Ria
Hey, Ria
I have been trying to figure this out for a long time, but I’m having no luck. How do you figure out if a tweet gathered from a timeline is a retweet or posted by the user who’s timeline we are accessing?
I tried to implement the retweet_status attribute but I get False even when its a retweeted tweet.
Any help?
Hi Mufaddal,\n\nI’ve just been weeding out retweets using -RT as a negative keyword in the search. This seems to do the trick in removing any retweets from my searches, as I believe RTs in their text format still display as “RT @username”.\n\nLet me know whether this works, or whether you need any more help! :)\nGood luck!
Sorry, I don’t think this helps because what I’m trying to do is get tweets from a user’s timeline. If they retweeted normally and not as a quote retweet then there doesn’t necessary have to be a RT text bit in the tweet.
Do you know if there is a way to differentiate between a USER POSTED tweet and a tweet that the USER RETWEETED?
for example, someone’s timeline may be like:
@user: “Having fun”
@blahblah “I love food”
the user tweeted the first tweet, but RT’d the second tweet so there is no “RT” text in the retweeted tweet.
Do you know how to handle this?
But when we see a retweet on the Twitter website, we see the retweet graphically. In text format, the tweet still displays “RT @username” even if the “RT @username” isn’t how it is displayed on Twitter itself. You can see this for yourself by printing a bunch of tweets from a search into your console. Those that have been retweeted will print to console as “RT @username” even though the user who retweeted did this by pressing the retweet button, not by quoting. Just try it, and see if it works. It has always worked for me.\n\nGood luck!
Ohh, that’s brilliant! Thanks, it should work.
I haven’t tested it yet, but would you iterate through the words in the text to check for the string “RT”?
like this:
tweet = tweet[‘text’]
for words in tweet:
if word == “RT”:
twitter.destroy_status(id = tweet[‘id_str’])
Thanks for your help btw!
If you are using Twython’s search function, you can just include it into the search query.
OR OTHERWISE:
You could create a list of negative keywords of things that you don’t want included in your RTs (such as their RTs or any offensive words.):
dont_rt = ["RT", "curse word", "whatever"]
and then check if the Tweet includes any of the words:
if any(word in dont_rt for word in tweet):
That may then make your bot a little more flexible in what it can and can’t ReTweet.
Hope that helps.
Hey Guys!
This Guide is awesome! :D
How can i prevent to retweet or favorite something from a specific User?
Because the topics im searching for are the same like some “@user” names…
Best wishes!
Tortoc
Hi,
I am able to retweet using search patter. But it seems that script is skipping some tweets with the search pattern present in them. Could you please tell me why is it doing it?
Also, I tried using multiple search pattern in one variable and pass it to he search q string, but it doesn’t work.
regards
Raj
This line doesn’t work:
id= tweet[“id_str”]
It returns an error that says indices have to be integers. I haven’t been able to find another way to find the id from the tweet itself.
Strange how it works for me. If it has to be an integer, try id=tweet[“id”]
I get an error that says oauth_token_secret = “where i put my token secret”
SytaxError: invalid syntax
anything I can do to prevent this?
That should be correct. Is there anything wrong with your indentation or anything like that?
Hi Ria,
I Just learn how to automatic rt using python. is there any code how to retweet from twitter list not from search query?
example what i need :
– retweet from twitter list A max 4 per hours.
– No RT (only origin tweet)
– exclude word :
– Only RT from people who tweet with image.
thank you for your help :)
Hi Tom,
For RTing Twitter lists, look into using get_list_statuses(**params), and how list statuses work using Twitter API. (Check out https://dev.twitter.com/docs/api/1.1/get/lists/statuses)
In the tutorial above, I also mention using “-RT” as a naughty word.
e.g.
naughty_words = [" -RT"]
The inclusion of “-RT” in your filter should exclude your Twitter bot from RTing any RTs. It works for me, and means I can just stick it in with my other filter words (which I find a good idea so I don’t end up Tweeting inappropriate things or naughty words).
For only RTing image Tweets, you’ll probably want to stick an “if” condition in there. For example, if I wanted to edit my code to only RT images, I would probably shove the if statement here:
try:
for tweet in search_results["statuses"]:
{ IF TWEET IS IMAGE }
try:
twitter.retweet(id = tweet["id_str"])
except TwythonError as e:
print e
except TwythonError as e:
print e
Since the easiest identifier of whether a tweet includes an image or not is the pic.twitter.com URL, you could easily just check whether the status contains that URL or not. And, if so, RT. Else, skip.
Just play around with it and have fun. I’m sure you’ll discover for yourself the method that suits your needs the most, and learn new things as you explore. Rather than just copying and pasting straight from a tutorial :P
Hope I’ve helped at all…
Hi Ria,
I have to say this is suburb, but i have a question ..
with the new twitter “quote” re-tweets , they changed it, in the past is used to be with RT …etc now the re-tweeted tweets will be in the same tweets ( Hard to explain :( but i think you get what i mean) .. is there anyway that i can do to let my bot ignore these type of tweets like -RT?
Also is there any way that i can make my bot retweet the quoted tweet ” the original ” in the new system ?
cheers
Hi –
Thanks for the tutorial! i can have it working locally, I would like to run it continuously online. from what i have found i need to include a sleep function, maybe a loop function and then in the folder a requirements.txt. any chance you have a tutorial for how to do this? or the source on github? i am trying to deploy to open shift.