I have the following Python code for loading the given page in selenium and taking a screenshot of the table.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from PIL import Image
import io
import os
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--window-size=1920x1080")
chrome_options.add_argument("--force-device-scale-factor=1")
driver = webdriver.Chrome(options=chrome_options)
path = os.path.abspath("table_minimal.html")
driver.get(f"file://{path}")
table = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, "table")))
png = table.screenshot_as_png
im = Image.open(io.BytesIO(png))
im.save("table.png")
driver.quit()
Here is the table_minimal.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap" rel="stylesheet">
<style>
table {
font-family: 'Montserrat';
font-size: 20px;
}
</style>
</head>
<body>
<table><tr><td>Text in the table</td></tr></tbody></table>
</body>
</html>
The above produces this image:
If I remove the --headless
flag then I get this instead:
So first one does not use the custom font, the second does but detects incorrect table width. Is there some settings I am missing to make this work correctly? Preferably in headless mode, but now I am curious why it does not work in normal mode as well...
Note: Changed the font to Matemasie
to make it stand out more in the screenshot.
The issue is caused by the screenshot being taken before the custom font has loaded.
There are some ways to wait for that to finish before continuing, eg:
time.sleep(2)
also works on such a simple DOM :)
Adding that to the code, and using table.screenshot()
to take the screenshot gives us:
path = os.path.abspath("table_minimal.html")
driver.get(f"file://{path}")
while True:
script = '''return document.fonts.status;'''
loaded = driver.execute_script(script)
if loaded == 'loaded':
break
time.sleep(.5)
table = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, "table")))
table.screenshot('./test3.png')
driver.quit()
Gives the expected result, with both --headless
and without: