How to capture website screenshot in high resolution?
Asked Answered
J

4

11

I want to capture screenshot of a website in high resolution to recognize text or simply to save high quality images. I tried this code in Python 2.7. The website http://www.flaticon.com/ has been taken merely as example.

from selenium import webdriver
import time
driver = webdriver.PhantomJS()
#Setting large window size doesn`t resolve the problem
driver.set_window_size(16000, 12000)
driver.get('http://www.flaticon.com/')
time.sleep(3)
#set resolution 640 dots per inch for this image 
#???
driver.save_screenshot('./downloaded/img/welcome_icons.png') # save a screenshot to disk
driver.close()

It captures screenshot, but the resolution is not enough for me. Enlarging window size doesn`t resolve the problem. The picture from webside reside only on the part of the image. It seems that image resolution is not affected. Is there some way to explicitly set image resolution before saving it?

Jasminejason answered 20/9, 2016 at 17:23 Comment(2)
Why not just get the text yourself with a web scrapper along with the imagines?Merla
Some times websites hide text under complicated web of links, so it may be simpler to grab a text from an image. I agree that in most cases, its better to get text with a web scrapper.Jasminejason
R
7

If it is about changing window size, you can set it by

driver.set_window_size(480, 320)

Here is an example of doing this from Github of one of the developers. As you can see, you can adjust both Window size and quality of the screenshot.

import StringIO
from selenium import webdriver
from PIL import Image
 
 
# Install instructions
#
# npm install phantomjs
# sudo apt-get install libjpeg-dev
# pip install selenium pillow
 
 
driver = webdriver.PhantomJS(executable_path="node_modules/phantomjs/bin/phantomjs")
driver.set_window_size(1366, 728) # optional
driver.get('http://google.com')
driver.save_screenshot('screen_hires.png')
 
screen = driver.get_screenshot_as_png()
 
# Crop it back to the window size (it may be taller)
box = (0, 0, 1366, 728)
im = Image.open(StringIO.StringIO(screen))
region = im.crop(box)
region.save('screen_lores.jpg', 'JPEG', optimize=True, quality=95)

The quality of 100 is max, 0 - min.

EDIT:

You can also use selenium.windowMaxmize().

And if you want to magnify the screen to see some specific texts as you said, you can try this in Mozilla:

from selenium.webdriver.common.keys import Keys    
from selenium.webdriver.common.action_chains import ActionChains

br = webdriver.Firefox()
zoom = ActionChains(br)
body = br.find_element_by_tag_name('body')
for i in range(2):
    zoom.send_keys_to_element(body,Keys.CONTROL,"+").perform()
Reynold answered 20/9, 2016 at 17:36 Comment(2)
Thank you @vlad.rad. This code does its the best. But when I enlarge a bit captured screenshot, there are squared pixels. It seems that the problem not only in output image resolution. Browsers allow users to zoom out web page. This feature makes it possible to see images and text on screen in larger scale. If we capture enlarged screenshot we will have input image in better quality, which we can than preserve. So, is there an approach to enlarge webpage programmatically, before taking screenshot?Jasminejason
Have you tried this: driver.execute_script("document.body.style.zoom='zoom %'") I don't know for sure if it will do what you want to. Otherwise I know unfortunately only how to zoom in a webpage and resize the window for screenshots.Reynold
I
8

I had the exact same problem, using Python 3.7 and the chrome webdriver, and the answers above helped a lot but none worked perfectly for me. Here's the solution I found:

from selenium import webdriver
from PIL import Image
from io import BytesIO
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
# MUST BE HEADLESS AND HAVE VERY LARGE WINDOW SIZE
chrome_options.add_argument("--headless")
chrome_options.add_argument("--window-size=6000x5000")

def get_screenshot(url_path, object_type, object_id):
    chrome = webdriver.Chrome(chrome_options=chrome_options, 
executable_path='/path/to/webdriver')
    chrome.get('http://website.com' + url_path)
    chrome.execute_script("document.body.style.zoom = '300%'")     # ZOOM

    element = chrome.find_element_by_id(object_id) # find part of the page you want image of
    location = element.location
    size = element.size
    png = chrome.get_screenshot_as_png() # saves screenshot of entire page
    chrome.quit()

    im = Image.open(BytesIO(png)) # uses PIL library to open image in memory

    left = location['x'] * 3 # must mutliply all these numbers by your zoom
    top = location['y'] * 3
    right = (location['x'] + size['width']) * 3
    bottom = (location['y'] + size['height']) * 3

    im = im.crop((left, top, right, bottom)) # defines crop points
    im.save(f'{object_id}.png') # saves new cropped image
Ichabod answered 15/5, 2020 at 4:50 Comment(1)
Thanks. This line chrome.get_screenshot_as_png() is not working for some reason. So, I used chrome.get_screenshot_as_file(filename) and zoom is set to 40%. It works okay. Please suggest something on how to get the same in non-headless modeTaro
R
7

If it is about changing window size, you can set it by

driver.set_window_size(480, 320)

Here is an example of doing this from Github of one of the developers. As you can see, you can adjust both Window size and quality of the screenshot.

import StringIO
from selenium import webdriver
from PIL import Image
 
 
# Install instructions
#
# npm install phantomjs
# sudo apt-get install libjpeg-dev
# pip install selenium pillow
 
 
driver = webdriver.PhantomJS(executable_path="node_modules/phantomjs/bin/phantomjs")
driver.set_window_size(1366, 728) # optional
driver.get('http://google.com')
driver.save_screenshot('screen_hires.png')
 
screen = driver.get_screenshot_as_png()
 
# Crop it back to the window size (it may be taller)
box = (0, 0, 1366, 728)
im = Image.open(StringIO.StringIO(screen))
region = im.crop(box)
region.save('screen_lores.jpg', 'JPEG', optimize=True, quality=95)

The quality of 100 is max, 0 - min.

EDIT:

You can also use selenium.windowMaxmize().

And if you want to magnify the screen to see some specific texts as you said, you can try this in Mozilla:

from selenium.webdriver.common.keys import Keys    
from selenium.webdriver.common.action_chains import ActionChains

br = webdriver.Firefox()
zoom = ActionChains(br)
body = br.find_element_by_tag_name('body')
for i in range(2):
    zoom.send_keys_to_element(body,Keys.CONTROL,"+").perform()
Reynold answered 20/9, 2016 at 17:36 Comment(2)
Thank you @vlad.rad. This code does its the best. But when I enlarge a bit captured screenshot, there are squared pixels. It seems that the problem not only in output image resolution. Browsers allow users to zoom out web page. This feature makes it possible to see images and text on screen in larger scale. If we capture enlarged screenshot we will have input image in better quality, which we can than preserve. So, is there an approach to enlarge webpage programmatically, before taking screenshot?Jasminejason
Have you tried this: driver.execute_script("document.body.style.zoom='zoom %'") I don't know for sure if it will do what you want to. Otherwise I know unfortunately only how to zoom in a webpage and resize the window for screenshots.Reynold
H
5

It's a bit hacky, but I solved this problem for myself by increasing the window size width to 3000 and the zoom to 250%.

driver.set_window_size(3000,800)

driver.execute_script("document.body.style.zoom='250%'")

Hope this helps.

Hyperform answered 20/4, 2017 at 22:25 Comment(1)
If you are using Mozilla Firefox as browser you can use driver.execute_script("document.body.style.webkitTransform = 'scale(2.5)'")Bendwise
V
3

To take higher-DPI screenshots in selenium, all you need to do is set a single-line preference on your driver profile. Let's do it for both Firefox and Chrome:

Firefox

desired_dpi = 2.0
profile = webdriver.FirefoxProfile()
profile.set_preference("layout.css.devPixelsPerPx", str(desired_dpi))
driver = webdriver.Firefox(firefox_profile=profile)

Chrome

desired_dpi = 2.0
options = ChromeOptions()
options.add_argument(f"--force-device-scale-factor={desired_dpi}")
driver = webdriver.Chrome(chrome_options=options)
Volkslied answered 4/2, 2022 at 9:48 Comment(1)
It works when I set ‘--force-device-scale-factor’ less than or equal to 1Presumptuous

© 2022 - 2024 — McMap. All rights reserved.