Screenshots based on a port list
In the previous script, we created our base function to return an image for a URL. We will now expand on that to loop over a list of ports that are commonly associated with web-based administration portals. This will allow us to point the script at an IP and automatically run through the possible ports that could be associated with a web server. This is to be used in cases when we don't know which ports are open on a server, rather than when where we are specifying the port and domain.
Getting ready
In order for this script to work, we'll need to have the script created in the Getting screenshots of a website with QtWeb Kit recipe. This should be saved in the Pythonxx/Lib
folder and named something clear and memorable. Here, we've named that script screenshot.py
. The naming of your script is particularly essential as we reference it with an important declaration.
How to do it…
This is the script that we will be using:
import screenshot import requests portList = [80,443,2082,2083,2086,2087,2095,2096,8080,8880,8443,9998,4643, 9001,4489] IP = '127.0.0.1' http = 'http://' https = 'https://' def testAndSave(protocol, portNumber): url = protocol + IP + ':' + str(portNumber) try: r = requests.get(url,timeout=1) if r.status_code == 200: print 'Found site on ' + url s = screenshot.Screenshot() image = s.get_image(url) image.save(str(portNumber) + '.png') except: pass for port in portList: testAndSave(http, port) testAndSave(https, port)
How it works…
We first create our import declarations. In this script, we use the screenshot
script we created before and also the requests
library. The requests
library is used so that we can check the status of a request before trying to convert it to an image. We don't want to waste time trying to convert sites that don't exist.
Next, we import our libraries:
import screenshot import requests
The next step sets up the array of common port numbers that we will be iterating over. We also set up a string with the IP address we will be using:
portList = [80,443,2082,2083,2086,2087,2095,2096,8080,8880,8443,9998,4643, 9001,4489] IP = '127.0.0.1'
Next, we create strings to hold the protocol part of the URL that we will be building later; this just makes the code later on a little bit neater:
http = 'http://' https = 'https://'
Next, we create our method, which will do the work of building the URL string. After we've created the URL, we check whether we get a 200
response code back for our get
request. If the request is successful, we convert the web page returned to an image and save it with the filename being the successful port number. The code is wrapped in a try
block because if the site doesn't exist when we make the request, it will throw an error:
def testAndSave(protocol, portNumber): url = protocol + IP + ':' + str(portNumber) try: r = requests.get(url,timeout=1) if r.status_code == 200: print 'Found site on ' + url s = screenshot.Screenshot() image = s.get_image(url) image.save(str(portNumber) + '.png') except: pass
Now that our method is ready, we simply iterate over each port in the port list and call our method. We do this once for the HTTP protocol and then with HTTPS:
for port in portList: testAndSave(http, port) testAndSave(https, port)
And that's it. Simply run the script and it will save the images to the same location as the script.
There's more…
You might notice that the script takes a while to run. This is because it has to check each port in turn. In practice, you would probably want to make this a multithreaded script so that it can check multiple URLs at the same time. Let's take a quick look at how we can modify the code to achieve this.
First, we'll need a couple more import declarations:
import Queue import threading
Next, we need to create a new function that we will call threader
. This new function will handle putting our testAndSave
functions into the queue:
def threader(q, port): q.put(testAndSave(http, port)) q.put(testAndSave(https, port))
Now that we have our new function, we just need to set up a new Queue
object and make a few threading calls. We will take out the testAndSave
calls from our FOR
loop over the portList
variable and replace it with this code:
q = Queue.Queue() for port in portList: t = threading.Thread(target=threader, args=(q, port)) t.deamon = True t.start() s = q.get()
So, our new script in total now looks like this:
import Queue import threading import screenshot import requests portList = [80,443,2082,2083,2086,2087,2095,2096,8080,8880,8443,9998,4643, 9001,4489] IP = '127.0.0.1' http = 'http://' https = 'https://' def testAndSave(protocol, portNumber): url = protocol + IP + ':' + str(portNumber) try: r = requests.get(url,timeout=1) if r.status_code == 200: print 'Found site on ' + url s = screenshot.Screenshot() image = s.get_image(url) image.save(str(portNumber) + '.png') except: pass def threader(q, port): q.put(testAndSave(http, port)) q.put(testAndSave(https, port)) q = Queue.Queue() for port in portList: t = threading.Thread(target=threader, args=(q, port)) t.deamon = True t.start() s = q.get()
If we run this now, we will get a much quicker execution of our code as the web requests are now being executed in parallel with each other.
You could try to further expand the script to work on a range of IP addresses too; this can be handy when you're testing an internal network range.