Intellipaat Back

Explore Courses Blog Tutorials Interview Questions
0 votes
2 views
in DevOps and Agile by (19.7k points)

After trying out various approaches. I have stumbled upon this page to take a full-page screenshot with Chrome Driver, Selenium and python.

The original code is here. (and I copy the code in this posting below)

It used PIL and it works great! However, there is one issue, which is, it captures fixed headers and repeats for the whole page and also misses some parts of the page during page change. sample URL to take a screenshot:

http://www.w3schools.com/js/default.asp

How to avoid the repeated headers with this code. Or is there any better option which uses python only... ( i don't know java and do not want to use java).

Please see the screenshot of the current result and sample code below.

full page screenshot with repeated headers

test.py

"""

This script uses a simplified version of the one here:

https://snipt.net/restrada/python-selenium-workaround-for-full-page-screenshot-using-chromedriver-2x/

It contains the *crucial* correction added in the comments by Jason Coutu.

"""

import sys

from selenium import webdriver

import unittest

import util

class Test(unittest.TestCase):

    """ Demonstration: Get Chrome to generate fullscreen screenshot """

    def setUp(self):

        self.driver = webdriver.Chrome()

    def tearDown(self):

        self.driver.quit()

    def test_fullpage_screenshot(self):

        ''' Generate document-height screenshot '''

        #url = "http://effbot.org/imagingbook/introduction.htm"

        url = "http://www.w3schools.com/js/default.asp"

        self.driver.get(url)

        util.fullpage_screenshot(self.driver, "test.png")

if __name__ == "__main__":

    unittest.main(argv=[sys.argv[0]])

util.py

import os

import time

from PIL import Image

def fullpage_screenshot(driver, file):

        print("Starting chrome full page screenshot workaround ...")

        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")

        print("Total: ({0}, {1}), Viewport: ({2},{3})".format(total_width, total_height,viewport_width,viewport_height))

        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

                print("Appending rectangle ({0},{1},{2},{3})".format(ii, i, top_width, top_height))

                rectangles.append((ii, i, top_width,top_height))

                ii = ii + viewport_width

            i = i + viewport_height

        stitched_image = Image.new('RGB', (total_width, total_height))

        previous = None

        part = 0

        for rectangle in rectangles:

            if not previous is None:

                driver.execute_script("window.scrollTo({0}, {1})".format(rectangle[0], rectangle[1]))

                print("Scrolled To ({0},{1})".format(rectangle[0], rectangle[1]))

                time.sleep(0.2)

            file_name = "part_{0}.png".format(part)

            print("Capturing {0} ...".format(file_name))

            driver.get_screenshot_as_file(file_name)

            screenshot = Image.open(file_name)

            if rectangle[1] + viewport_height > total_height:

                offset = (rectangle[0], total_height - viewport_height)

            else:

                offset = (rectangle[0], rectangle[1])

            print("Adding to stitched image with offset ({0}, {1})".format(offset[0],offset[1]))

            stitched_image.paste(screenshot, offset)

            del screenshot

            os.remove(file_name)

            part = part + 1

            previous = rectangle

        stitched_image.save(file)

        print("Finishing chrome full page screenshot workaround...")

1 Answer

0 votes
by (62.9k points)

You can achieve this by changing the CSS of the header before the screenshot-code snippet:

 topnav = driver.find_element_by_id("topnav")

driver.execute_script("arguments[0].setAttribute('style', 'position: absolute; top: 0px;')", topnav) 

EDIT: Put this line after your window scroll:

driver.execute_script("document.getElementById('topnav').setAttribute('style', 'position: absolute; top: 0px;');")

So in your,  util.py, it will be:

 driver.execute_script("window.scrollTo({0}, {1})".format(rectangle[0], rectangle[1]))

driver.execute_script("document.getElementById('topnav').setAttribute('style', 'position: absolute; top: 0px;');")

If the site is using the header tag, you can do it with find_element_by_tag_name("header". I hope this helps!

If you wish to know about Hadoop and Big Data visit this Big Data Course by Intellipaat.

If you are interested to learn Selenium on a much deeper level and want to become a professional in the testing domain, check out Intellipaat’s Selenium course!

31k questions

32.8k answers

501 comments

693 users

Browse Categories

...