Twitter "Like" Bot
I was on Twitter and became angry after seeing a website charge for a course that teaches how to "like" using Python and Selenium. Yes, the exact same thing this tutorial teaches for free. First off, do not pay for this type of course! There's tons of documentation available to learn on your own. This post is a breakdown of my personal and professional use of Selenium.
Full script available here.
Step 1: Requirements
Step 2: Gather Elements
I prefer to find elements using iPython and then wrap them into classes. Here's an example:
In : from selenium import webdriver In : driver = webdriver.Chrome() In : driver.get('http://twitter.com') drive In : username = driver.find_element_by_name('session[username_or_email]') In : username.send_keys('test-user')
As you can see, I've found the
username input field and successfully sent
test-user to the element, so I add
username as an attribute on the
Locator class. I've done the same for all elements that I'll interact with throughout this example
class TwitterLocator: username = (By.NAME, "session[username_or_email]") password = (By.NAME, "session[password]") submit_btn = (By.CLASS_NAME, "js-submit") search_input = (By.ID, "search-query") search_btn = (By.ID, "nav-search") tweets = (By.CLASS_NAME, "js-stream-item") like_btn = (By.CLASS_NAME, "HeartAnimation") latest_tweets = (By.PARTIAL_LINK_TEXT, 'Latest')
Step 3: Define Constants
I've identified the below three attributes as constant variables (not required - I prefer the organization):
class Constants: USERNAME = os.environ.get("TWITTER_USERNAME") PASSWORD = os.environ.get("TWITTER_PASSWORD") GLOBAL_ENTRY_Q = '#globalentry'
Step 4: Bot
Now that we have the above out of the way, let's create the
Bot class to piece this all together.
class LikeBot(object): def __init__(self): self.locator_dictionary = TwitterLocator.__dict__ self.browser = webdriver.Chrome() self.browser.get(URL.TWITTER) self.timeout = 10
Take a look at
locator_dictionary. It's a
TwitterLocator attributes, attached to the
LikeBot class. We've basically given
LikeBot the same attributes as
TwitterLocator (as a variable). More on this later...
It's important to instantiate with a
webdriver, to visit the
url intended (
http://twitter.com) in this case, and to set the
timeout (in seconds).
From here we can start creating methods, such as
login, that will login to an account as long as the browser is on the login page. A convenient. syntax-smart way of writing methods is to include a
find_element along with a
__getattr__ method that looks at the locator dictionary.
def _find_element(self, *loc): return self.browser.find_element(*loc) def __getattr__(self, what): try: if what in self.locator_dictionary.keys(): try: element = WebDriverWait(self.browser, self.timeout).until( EC.presence_of_element_located(self.locator_dictionary[what]) ) except(TimeoutException, StaleElementReferenceException): traceback.print_exc() try: element = WebDriverWait(self.browser, self.timeout).until( EC.visibility_of_element_located(self.locator_dictionary[what]) ) except(TimeoutException, StaleElementReferenceException): traceback.print_exc() # I could have returned element, however because of lazy loading, I am seeking the element before return return self._find_element(*self.locator_dictionary[what]) except AttributeError: super(LikeBot, self).__getattribute__("method_missing")(what) def method_missing(self, what): print "No %s here!" % what
Now we can write methods using the below syntax in the methods:
def login(self, username=Constants.USERNAME, password=Constants.PASSWORD): self.username.send_keys(username) self.password.send_keys(password) self.submit_btn.click()
I created a
run method to handle all actions as one:
def run(self): self.login() self.search() self.view_latest_tweets() time.sleep(2) self.like_tweet() self.browser.quit()
time.sleep() line – this is only to wait a few seconds before executing the next lines (because changing between tabs isn't always instantaneous)