How To Win At Twitter Without Really Trying ― A Python Script to Delete Old Tweets
In the last few days I have decided to reconnect with my mostly dormant Twitter persona. Aside from tweeting links to a few Steem posts I had not paid serious attention to my Twitter account since 2016 or so.
Overall, I had tweeted about 1500 times since joining the service in August of 2007. This is not exactly prolific. Nevertheless, many of my older tweets did point to blog posts that were no longer available. Others discuss technical topics that were of little relevance today. A few were just silly. Or maybe incomprehensible.
CC-0 from Pixabay
Given the short and rapid format of Twitter, it seemed important to focus my feed on topics that matter in the moment. I decided to archive and delete most of the older content. And thereby I encountered a small challenge.
The feature to mass delete tweets is not built in to Twitter's web interface. Painstakingly vaporizing a thousand tweets didn't sound like much fun either.
As we often do in this age, I first turned to Google and the marketplace of apps. The first search result for my hastily devised "mass delete tweets" query was this listicle. It identifies five third party tools for deleting tweets in bulk.
From Tweet Deleter's dashboard
Hesitant to re-invent the wheel, I gave the first one listed, Tweet Deleter, a try. To be fair it didn't seem like an unworkable option. It had useful tools for filtering and searching for Tweets that you may wish to delete. These filters offered a variety of criteria.
I quickly encountered the main limitation, though. Tweet Deleter wanted to sell me a premium subscription in order to delete more than 5 of my own tweets on any given day.
Tweet Deleter's oAuth note
I also was rather skeptical of the application's twitter API authorization. It identified itself as "Global auth" for a variety of services rather than a specific application.
There was in fact only one purpose for which I was willing to temporarily grant access. I didn't really want to contemplate how "many cool services" would gain delete capable, write access to my account.
So, I could either pay for a shady feature that should have been built in anyway. Or I could make a year long project out of taking back control of my own feed.
Suspecting that the remaining options would eventually reveal comparable shortcomings, I chose to invent Option C ― build it my damned self (while standing on the shoulders of giants, of course).
Fortunately, I had just spent a good portion of the holidays reacquainting myself with Python. And there's a rule among developers. If there isn't a JavaScript for it there's one in Python. Actually there's probably both. But the more languages with which you're familiar, the greater the likelihood that you can adapt the first answers you find.
In this case a quick search of Stack Overflow and GitHub turned up two pieces of Python code. Each on its own came close to meeting my objective of deleting all tweets older than a certain date. But complete satisfaction would involve combining the two ideas.
First up, I noticed this gist under the GitHub account of Dave Jeffery. This is a handy bit of Python scripting using the open source tweepy library to nuke all of the tweets in a feed. There are a couple of things to note about this script.
It's written in Python 2 syntax. This isn't really a problem. To use the script with minimal modification there are readily available Python 2 environments that won't require any setup. For example, I used a Python 2 notebook at Google's Colaboratory. Alternatively, you could tweak the syntax to its Python 3 equivalent.
As mentioned in the comments of the gist it's necessary to have your own application keys. These are useful for any sort of Twitter automation you may wish to do on your own. And are readily obtainable for each Twitter account at https://dev.twitter.com/apps
The comments also mention a bug that may require refreshing your Twitter feed from time to time while the script runs. I did not encounter this. Perhaps it's an old bug that has since been fixed.
There is a further consideration regarding the use of Python 2. When the script authenticates to the Twitter API the server may, depending on the setup of your app, respond with a message in the browser that
Python 2.5 is no longer available.
Don't panic. Even though you encounter a browser error message the required verification code will be available in a URL query parameter.
If you don't receive a code in your browser, just look for the parameteroauth_verifier
in your callback URL. This value is the code for which the Python script is prompting you.
By itself this script was ready to do most of the heavy lifting as to the quest at hand. However, I wanted a slightly finer degree of control than that provided ― not necessarily the granular filtering offered by some of the fully polished apps out there. But I did, at least, wish to keep a few of my more recent, topical posts.
After skimming my eleven year Twitter history, I decided it would be sufficient to delete anything older than April 20th, 2016.
For advice on how to get that done I turned next to Stack Overflow and found this. It's a discussion of exactly the problem I faced ― how to use Tweepy to act only on tweets in a certain date range.
As noted by Siddarth Sreeni's answer the approach of fetching an entire feed and then weeding out each tweet by date is far from the most efficient. Since I had only hundreds of tweets to deal with I was not overly concerned about this. And indeed ultimately the script had handled my entire feed in less than two minutes.
However, if your feed is orders of magnitude larger than mine, you may wish to look for a safer and more efficient approach―requesting paged results, or a series of smaller date ranges, for example.
Here are the changes to the base script inspired by the Stack Overflow discussion:
- First, I did need to import the
datetime
library. This minor detail is actually not illustrated in the sample code on Stack Overflow. But it is easy enough...
import datetime
- Next, define the date range in which to delete tweets. I want to delete everything before a certain date. So I simply set the start of the date range earlier than the date I joined Twitter.
START_DATE = datetime.datetime(1970, 1, 1, 0, 0, 0)
END_DATE = datetime.datetime(2016, 4, 20, 0, 0, 0)
- Finally, we find the action loop in the original script. It starts out like this:
for status in tweepy.Cursor(api.user_timeline).items():
try:
api.destroy_status(status.id)
print "Deleted:", status.id
except:
print "Failed to delete:", status.id
Notice how in the code the formal name for a tweet is a status
. And the act of permanently deleting one is called destroy
.
All that is needed here is to add the date criteria to this loop so that it does not destroy a status that falls outside the targeted range. With our constants in place this will work:
for status in tweepy.Cursor(api.user_timeline).items():
if status.created_at < END_DATE and status.created_at > START_DATE:
try:
api.destroy_status(status.id)
print "Deleted:", status.id
except:
print "Failed to delete:", status.id
For Python code indentation matters. Remember to indent the try-except
block to be within the conditional if
.
It worked like a charm. And now if you visit my Twitter account, TrevorReidMBA, only my most recent tweets remain.
You can get the my modified version of the script from this gist.
Resources
Repository
https://github.com/tweepy/tweepy
Gists
https://gist.github.com/davej/113241
https://gist.github.com/tdreid/707a202edda9d3e5eb6fadd3031bedbe
Thank you for providing the Information about the tweepy project. This post is informative and engaging. I am glad that you were able to find an accurate tool that you needed to eradicate those old irrelevant tweets. This post will certainly be useful to a lot of people that need a tool like this. Although, the post is a little bit technical for a blog post. It contains few technicals that appear like a tutorial. Nevertheless, the information is deemed valuable. Thank you!
Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.
To view those questions and the relevant answers related to your post, click here.
Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]
Thanks for the review @tykee. Yes, I was on the fence about whether to approach this as a blog or a tutorial myself. In the end, because it is more a story than a lesson, I decided to treat it as a blog. But I see where it could have gone the other way too.
I don't think we should avoid all technical details in utopian blogs posts. Compare it, perhaps, to a story about a meal that happens to include a recipe. As long as the contribution is valuable I hope for blog to remain the most broad and flexible of categories. This makes sense to my mind.
Again, I really appreciate your thoughtful comments.
Thank you for your review, @tykee! Keep up the good work!
This post has been voted on by the SteemSTEM curation team and voting trail in collaboration with @curie.
If you appreciate the work we are doing then consider voting both projects for witness by selecting stem.witness and curie!
For additional information please join us on the SteemSTEM discord and to get to know the rest of the community!
img credz: pixabay.com
Nice, you got an awesome upgoat, thanks to @tdre
BuildTeam wishes everyone a great Christmas and bullish Holidays
Want a boost? Minnowbooster's got your back!
I take it these Goats will be available for all twelve days of christmastide BuildTeam @MinnowBooster? :)
Congratulations! This post has been upvoted from the communal account, @minnowsupport, by tdre from the Minnow Support Project. It's a witness project run by aggroed, ausbitbank, teamsteem, someguy123, neoxian, followbtcnews, and netuoso. The goal is to help Steemit grow by supporting Minnows. Please find us at the Peace, Abundance, and Liberty Network (PALnet) Discord Channel. It's a completely public and open space to all members of the Steemit community who voluntarily choose to be there.
If you would like to delegate to the Minnow Support Project you can do so by clicking on the following links: 50SP, 100SP, 250SP, 500SP, 1000SP, 5000SP.
Be sure to leave at least 50SP undelegated on your account.
This is really cool! It'll be neat to try on my own twitter. :3
Thanks @jjay
Hey, @tdre!
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!
Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).
Want to chat? Join us on Discord https://discord.gg/h52nFrV.
Vote for Utopian Witness!