Python and Game of Thrones (Part 1 of 3)

With the final season of Game of Thrones happening soon, I wanted to do something fun. And by fun, I mean writing a 3 part series on some cool things you can do with Python! Because why not?

Check out Part 2 and Part 3 here.

I wanted to learn Python for a long time, but I could never find a reason. Ignoring the fact that it powers site like Reddit, Instagram and Dropbox, and that it was named Programming Language of the Year for 2018 – it’s also a really readable language that has a lot of powerful libraries.

When I got some tasks that needed automation in my job, I realized I had a opportunity to dig deep into Python. But rather than talk about boring office related tasks, let’s talk about Game of Thrones!

In this post, I covering web automation with the Selenium library. In Part 2, I covered web scraping with the BeautifulSoup library. And in Part 3, I covered generating reports with the csv module. And YES – they are all Game of Thrones related. Let’s get into it!


In this post, we are going to use Python to automatically log into our favorite Game of Thrones fan sites.

Other use cases for this:

  • You might want to automate account creations on your site.
  • You might want to run a bot from start to finish in your online course.
  • You might want to push a 100 bots to submit a form on your site with a single script.

A little backstory:

My company had a bunch of reports that needed to be generated, and I was stuck doing redundant tasks. I knew there had to be a option, so I dug deep into Python and spent a few weeks to learn enough to get dangerous.

In these set of tutorials, I wanted to share what I learned.

But that, my friends… is boring.

Python is WELL DOCUMENTED. There are so many free guides to learning Python. There’s a lot of great tutorials out there.

So instead of trying to write another ULTIMATE GUIDE on how use Python, I rather just go straight into the cool things that Python has to offer.

One final note: I also want to share that I’m not like a professional at Python. This is roughly a few weeks of Python experience. I was committed to learning just enough to do what I need to do.

Python and Web Automation

One of the coolest things you can do with Python is web automation.

For example – you can write a Python script that:

  1. Opens up a browser
  2. Automatically visits a specific website
  3. Logs you into that site
  4. Goes to another part of that website
  5. Finds the most recent blog post.
  6. Opens that blog post.
  7. Submits a comment that says, “Great writing! High five!”
  8. And finally logs you out of that website

It might not seem so hard to do. That takes what…. 20 seconds?

But if you had to do that over and over again, it would drive you insane.

For example – what if you had a staging site that’s still in development with a 100 blog posts, and you wanted to post a comment on every single page to test it’s functionality?

That’s 100 blog posts * 20 seconds = roughly 33 minutes

And what if there’s MULTIPLE testing phases, and you had to repeat the test six more times?

Python and the Game of Thrones

So, let’s talk about the elephant in the room. Or really, the IRON THRONE in the room.

With the final season of Game of Thrones coming up, I wanted to do something that’s a bit more fun.

We are going to log into our favorite Game of Thrones fan sites.

You will need to install Python 3, Selenium, and the Firefox webdrivers to get started.

If you have no idea where to start, check out my tutorial on How to automate form submissions with Python.

The Python Script

## Game of Thrones easy login script
## 
## Description: This code logs into all of your fan sites automatically

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
import time



driver = webdriver.Firefox()
driver.implicitly_wait(5)
    ## implicity_wait makes the bot wait 5 seconds before every action
    ## so the site content can load up

# Define the functions

def login_to_westeros (username, userpass):

    ## Open the login page
    driver.get('https://asoiaf.westeros.org/index.php?/login/')    

    ## Log the details
    print(username + " is logging into westeros.")
    
    ## Find the fields and log into the account. 
    textfield_username = driver.find_element_by_id('auth')
    textfield_username.clear()
    textfield_username.send_keys(username)

    textfield_email = driver.find_element_by_id('password')
    textfield_email.clear()
    textfield_email.send_keys(userpass)

    submit_button = driver.find_element_by_id('elSignIn_submit')
    submit_button.click()

    ## Log the details
    print(username + " is logged in! -> westeros")



		
def login_to_reddit_freefolk (username, userpass):

    ## Open the login page
    driver.get('https://www.reddit.com/login/?dest=https%3A%2F%2Fwww.reddit.com%2Fr%2Ffreefolk')    

    ## Log the details
    print(username + " is logging into /r/freefolk.")
    
    ## Find the fields and log into the account. 
    textfield_username = driver.find_element_by_id('loginUsername')
    textfield_username.clear()
    textfield_username.send_keys(username)

    textfield_email = driver.find_element_by_id('loginPassword')
    textfield_email.clear()
    textfield_email.send_keys(userpass)

    submit_button = driver.find_element_by_class_name('AnimatedForm__submitButton')
    submit_button.click()

    ## Log the details
    print(username + " is logged in! -> /r/freefolk.")
    

## Define the user and email combo. 

login_to_westeros("gameofthronesfan86", PASSWORDHERE)

time.sleep(2)
driver.execute_script("window.open('');")
Window_List = driver.window_handles
driver.switch_to_window(Window_List[-1])

login_to_reddit_freefolk("MyManMance", PASSWORDHERE)

time.sleep(2)
driver.execute_script("window.open('');")
Window_List = driver.window_handles
driver.switch_to_window(Window_List[-1])


## wait for 2 seconds
time.sleep(2)


print("task complete")

Let’s break those code blocks down

To start, I’m importing the Selenium library to help with the heavy lifting.

I also imported the time library, so after each action, it will wait x seconds. Adding a wait allows the page to load.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
import time

What is Selenium

Selenium is the Python library we use for web automation. Selenium has developed API so third-party authors can develop webdrivers to the communication to browsers.

That way, the Selenium team can focus on their codebase, while another team can focus on the middleware.

For example:

  • The Chromium team made their own webdriver for Selenium called chromedriver.
  • The Firefox team made their own webdriver for Selenium called geckodriver.
  • The Opera team made their own webdriver for Selenium called operadriver.

In the code above, you’ll see me do things like “Open Firefox”, and “pass this link to Firefox”, and finally “Close Firefox”. I would need the geckodriver to do that.

Logging into sites

To make it easier to read, I wrote a separate function to log into each site, to show the pattern that we are making.

def login_to_westeros (username, userpass):

    ## Open the login page
    driver.get('https://asoiaf.westeros.org/index.php?/login/')    

    ## Log the details
    print(username + " is logging into westeros.")
    
    ## Find the fields and log into the account. 
    textfield_username = driver.find_element_by_id('auth')
    textfield_username.clear()
    textfield_username.send_keys(username)

    textfield_email = driver.find_element_by_id('password')
    textfield_email.clear()
    textfield_email.send_keys(userpass)

    submit_button = driver.find_element_by_id('elSignIn_submit')
    submit_button.click()

    ## Log the details
    print(username + " is logged in! -> westeros")

If we break that down even more — each function has the following elements.

I’m telling Python to:

  1. Visit a specific page.
  2. Look for the login box
    • Clear the text if there is any
    • Submit my variable
  3. Look for the password box
    • Clear the text if there is any
    • Submit my variable
  4. Look for the submit button, and click it
  5. Wait a few seconds so you can bast in the glory.

Opening up a new tab

Since we have multiple sites, we want to open up a new tab. Otherwise, Selenium will override the current tab.

There’s various code floating around to do it that no longer work or didn’t work for me. (For example: there was a method to having Selenium push the hotkeys to open up a new tab, but it wouldn’t fire).

This worked, which I found here:

driver.execute_script("window.open('');")
Window_List = driver.window_handles
driver.switch_to_window(Window_List[-1])

Running the code

Here’s a short video of me running the code.

Let’s break that down even more.

How to find the login box and password box

The Selenium Library has a bunch of handy ways to find elements on a webpage. Here are some of the ones I like to use.

  • find_element_by_id
  • find_element_by_name
  • find_element_by_xpath
  • find_element_by_class_name

For the whole list, visit the Selenium Python documentation for locating elements.

To use asoiaf.westeros.com as an example, when I inspect the elements – they all have IDs… which is GREAT! That makes my life easier.

When you inspect elements of the ‘Display Name’, the ‘Password’, and the ‘Sign In’ elements, you’ll notice that they all have unique IDs. Huzzah!

Conclusion

With web automation, you’re playing a game of ‘how can I get Selenium to find the element’. Once you find it, you can then manipulate it.

In this post, I covered web automation with the Selenium library. In Part 2, I covered web scraping with the BeautifulSoup library. And in Part 3, I covered generating reports with the csv module.

See you in the next part!

2 Comments

  1. […] Python and Game of Thrones (Part 1 of 3) […]

  2. […] Python and Game of Thrones (Part 1 of 3) […]

Leave a Comment