Take screenshot from Zabbix site - Python

Prerequisite:

1.1. Install Chromium and chromedriver:

sudo amazon-linux-extras install epel -y
sudo yum install chromium -y
sudo yum install chromedriver -y

The reason for installing chromium and chromedriver is:

  • Chromium installs a browser that will be used to open web pages.

  • Chromedriver will control the Chromium browser to open websites, fill text, click buttons, etc.

Those 2 are essential packages so that you can use Selenium WebDriver.

1.2. Install Pillow and selenium using pip:

pip install Pillow
pip install selenium
  • Pillow: Python imaging library. Basically, it interacts with the matrix and can be used to save the matrix as an image.

  • selenium: Primarily, it is for automating web applications for testing purposes. But it can also be a tool that helps automate tasks on a website.

2. Write Python code to take screenshot:

from _future_ import print_function
from PIL import Image
from io import BytesIO
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
import smtplib
import imghdr
from email.message import EmailMessage
from datetime import datetime
import sys

def time_now(style="file"):
    time_format = "%Y%m%d_%H%M%S" if style == "file" else "%Y-%m-%d %H:%M:%S"
    return datetime.now().strftime(time_format)

def open_url(zabbix_url, z_user, z_password, delay=5):
    options = Options()
    options.headless = True

    driver = webdriver.Chrome(options=options)
    driver.get(zabbix_url)
    # idk but sleep for 5 second
    time.sleep(delay)

    login = driver.find_element_by_id("name")
    login.send_keys(z_user)
    password = driver.find_element_by_id("password")
    password.send_keys(z_password)
    submit = driver.find_element_by_id("enter")
    submit.click()

    WebDriverWait(driver=driver, timeout=10).until(
        lambda x: x.execute_script("return document.readyState === 'complete'")
    )
    error_message = "Cannot bind to LDAP server."
    errors = driver.find_elements(by=By.CLASS_NAME, value="red")

    if any(error_message in e.text for e in errors):
        print("[!] Login failed")
        return None
    else:
        print("[+] Login successful")
    # idk but sleep for 5 second
    time.sleep(delay)
    driver.maximize_window()
    images_title = save_screenshot(driver, "screen")
    driver.close()
    return images_title

def save_screenshot(driver, file_name):
    height, width = scroll_down(driver)
    driver.set_window_size(width, height)
    img_binary = driver.get_screenshot_as_png()
    img = Image.open(BytesIO(img_binary))
    image_title = "zabbix_capture_%s.png" %time_now()
    img.save(image_title)
    print("Screenshot saved")
    return [image_title]

def scroll_down(driver):
    total_width = driver.execute_script("return document.body.offsetWidth")
    total_height = driver.execute_script("return document.body.parentNode.scrollHeight")
    viewport_width = driver.execute_script("return document.body.clientWidth")
    viewport_height = driver.execute_script("return window.innerHeight")

    rectangles = []

    i = 0
    while i < total_height:
        ii = 0
        top_height = i + viewport_height
        if top_height > total_height:
            top_height = total_height
        while ii < total_width:
            top_width = ii + viewport_width
            if top_width > total_width:
                top_width = total_width
            rectangles.append((ii, i, top_width, top_height))
            ii = ii + viewport_width
        i = i + viewport_height
    previous = None

    for rectangle in rectangles:
        if not previous is None:
            driver.execute_script("window.scrollTo({0}, {1})".format(rectangle[0], rectangle[1]))
            time.sleep(0.5)
        if rectangle[1] + viewport_height > total_height:
            offset = (rectangle[0], total_height - viewport_height)
        else:
            offset = (rectangle[0], rectangle[1])
        previous = rectangle

    return (total_height, total_width)

def send_mail(files_title):
    sender_email = sys.argv[1]
    sender_password = sys.argv[2]
    receiver_email = sys.argv[3]

    new_message = EmailMessage()
    new_message["Subject"] = "Check out Dashboard screenshot" 
    new_message["From"] = sender_email
    new_message["To"] = receiver_email

    new_message.set_content("This is your screenshot. Image attached!") 
    files = files_title

    for file in files:
        with open(file, "rb") as f:
            image_data = f.read()
            image_type = imghdr.what(f.name)
            image_name = f.name
        new_message.add_attachment(image_data, maintype="image", subtype=image_type, filename=image_name)

    with smtplib.SMTP_SSL("smtp.gmail.com", 465) as smtp:
        smtp.login(sender_email, sender_password)
        smtp.send_message(new_message)
        print("Sent mail!")

if __name__ == "__main__":
    if len(sys.argv) < 4:
        print('This script is to capture a webpage and send the image to emai.')
        print('You should run this script as following: python screenshot_tool.py <from_email> <password_of_from_email> <to_email>')
        print('For e.g, python screenshot_tool.py tthyen@example.com 1234eecffxe tthyen@example2.com')
    else:
        ZABBIX_URL = "<zabbix_url>"
        ZABBIX_USER = "<zabix_username"
        ZABBIX_PASSWORD = "Zabbix_password"
        images_title = open_url(ZABBIX_URL, ZABBIX_USER, ZABBIX_PASSWORD)
        if images_title is None:
            pass
        else:
            send_mail(images_title)

2.1 Code explanation:

if __name__ == "__main__":
    if len(sys.argv) < 4:
        print('This script is to capture a webpage and send the image to emai.')
        print('You should run this script as following: python screenshot_tool.py <from_email> <password_of_from_email> <to_email>')
        print('For e.g, python screenshot_tool.py tthyen@example.com 1234eecffxe tthyen@example2.com')
    else:
        ZABBIX_URL = "<zabbix_url>"
        ZABBIX_USER = "<zabix_username"
        ZABBIX_PASSWORD = "Zabbix_password"
        images_title = open_url(ZABBIX_URL, ZABBIX_USER, ZABBIX_PASSWORD)
        if images_title is None:
            pass
        else:
            send_mail(images_title)
  • This is the entry point of the code. You have to specify three parameters: sender email, sender password and receiver email.

  • There are some predefined values:

    • ZABBIX_URL: Store URL of Zabbix.

    • ZABBIX_USER: Store Zabbix logging username.

    • ZABBIX_PASSWORD: Store Zabbix logging password.

  • If the logging information is incorrect, it will print out on the terminal “[!] Login failed” and will not send an email.

  • There are four main functions that are:

    • open_url: handle web driver control, Zabbix logging, and so on.

    • scroll_down: calculate the maximum height and width of the Zabbix site by scrolling down.

    • After calculating the height and width, using the web driver, take a screenshot of the website and save it to disk.

2.2 Run code:

python zabbix_screenshot.py sender@example.mail sender_password receiver@example.mail

With:

  • sender@example.mail: This email will send an email with a Zabbix screenshot.

  • reciver@example.mail: This email will receive email from the sender.

  • sender_password: This is the password used for logging into the sender account to send email.

For example:

python zabbix_screenshot.py tthyen@example.com 1234eecffxe tthyen@example2.com