Arthur

Pemberton

Full-stack web applications developer


Full page screenshots with Python and Selenium

December 18, 2017Arthur Pemberton0 Comments

Currently, none of the major Selenium drivers (browsers) support the ability to easily take a screenshot of an entire web page. The following function takes multiple screenshots through the viewport and scrolls between screenshots, then stitches the resulting images into a single PNG.

def save_fullpage_screenshot(driver, url, output_path, tmp_prefix='selenium_screenshot', tmp_suffix='.png'):
	"""
	Creates a full page screenshot using a selenium driver by scrolling and taking multiple screenshots,
	and stitching them into a single image.
	"""

	# get the page
	driver.get(url)

	# get dimensions
	window_height = driver.execute_script('return window.innerHeight')
	scroll_height = driver.execute_script('return document.body.parentNode.scrollHeight')
	num = int( math.ceil( float(scroll_height) / float(window_height) ) )

	# get temp files
	tempfiles = []
	for i in xrange( num ):
		fd,path = tempfile.mkstemp(prefix='{0}-{1:02}-'.format(tmp_prefix, i+1), suffix=tmp_suffix)
		os.close(fd)
		tempfiles.append(path)
		pass

	try:
		# take screenshots
		for i,path in enumerate(tempfiles):
			if i > 0:
				driver.execute_script( 'window.scrollBy(%d,%d)' % (0, window_height) )
			
			driver.save_screenshot(path)
			pass
		
		# stitch images together
		stiched = None
		for i,path in enumerate(tempfiles):
			img = Image.open(path)
			
			w, h = img.size
			y = i * window_height
			
			if i == ( len(tempfiles) - 1 ):
				img = img.crop((0, h-(scroll_height % h), w, h))
				w, h = img.size
				pass
			
			if stiched is None:
				stiched = Image.new('RGB', (w, scroll_height))
			
			stiched.paste(img, (
				0, # x0
				y, # y0
				w, # x1
				y + h # y1
			))
			pass
		stiched.save(output_path)
	finally:
		# cleanup
		for path in tempfiles:
			if os.path.isfile(path):
				os.remove(path)
		pass

	return output_path

The following libraries are required:

  • selenium
  • Pillow

Leave a Reply