| import gradio as gr |
| 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 |
| from io import BytesIO |
| import tempfile |
| import time |
| import os |
|
|
| def get_full_dimensions(driver): |
| """ |
| <body>と<html>の scrollWidth/scrollHeight を比較して |
| ページ全体の幅・高さを返す |
| """ |
| body_w = driver.execute_script("return document.body.scrollWidth") |
| body_h = driver.execute_script("return document.body.scrollHeight") |
| html_w = driver.execute_script("return document.documentElement.scrollWidth") |
| html_h = driver.execute_script("return document.documentElement.scrollHeight") |
| full_width = max(body_w, html_w) |
| full_height = max(body_h, html_h) |
| return full_width, full_height |
|
|
| def scroll_to_bottom(driver): |
| """ |
| 一旦ページの最下部までスクロールし、 |
| Lazy Loadなどで追加要素が生成されるのを待つ |
| """ |
| last_height = driver.execute_script("return document.body.scrollHeight") |
| while True: |
| driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") |
| time.sleep(1) |
| new_height = driver.execute_script("return document.body.scrollHeight") |
| if new_height == last_height: |
| break |
| last_height = new_height |
|
|
| def render_fullpage_screenshot(html_code): |
| |
| tmp_file = tempfile.NamedTemporaryFile(suffix=".html", delete=False) |
| tmp_path = tmp_file.name |
| tmp_file.write(html_code.encode('utf-8')) |
| tmp_file.close() |
|
|
| |
| options = Options() |
| options.add_argument("--headless") |
| options.add_argument("--no-sandbox") |
| options.add_argument("--disable-dev-shm-usage") |
| options.add_argument("--force-device-scale-factor=1") |
|
|
| try: |
| driver = webdriver.Chrome(options=options) |
| |
| driver.set_window_size(1200, 800) |
| driver.get("file://" + tmp_path) |
|
|
| |
| WebDriverWait(driver, 10).until( |
| EC.presence_of_element_located((By.TAG_NAME, "body")) |
| ) |
| time.sleep(1) |
|
|
| |
| w1, h1 = get_full_dimensions(driver) |
| driver.set_window_size(w1, h1) |
| time.sleep(1) |
|
|
| |
| scroll_to_bottom(driver) |
| time.sleep(1) |
|
|
| |
| w2, h2 = get_full_dimensions(driver) |
| if (w2 != w1) or (h2 != h1): |
| driver.set_window_size(w2, h2) |
| time.sleep(1) |
| |
| scroll_to_bottom(driver) |
| time.sleep(1) |
|
|
| |
| driver.execute_script(""" |
| document.documentElement.style.overflow = 'hidden'; |
| document.body.style.overflow = 'hidden'; |
| """) |
| time.sleep(1) |
|
|
| |
| w3, h3 = get_full_dimensions(driver) |
| driver.set_window_size(w3, h3) |
| time.sleep(1) |
|
|
| |
| driver.execute_script("window.scrollTo(0, 0);") |
| time.sleep(1) |
|
|
| |
| png = driver.get_screenshot_as_png() |
|
|
| except Exception as e: |
| |
| return Image.new('RGB', (1, 1), color=(0, 0, 0)) |
|
|
| finally: |
| driver.quit() |
| if os.path.exists(tmp_path): |
| os.remove(tmp_path) |
|
|
| return Image.open(BytesIO(png)) |
|
|
| |
| iface = gr.Interface( |
| fn=render_fullpage_screenshot, |
| inputs=gr.Textbox(lines=15, label="HTMLコード入力"), |
| outputs=gr.Image(type="pil", label="ページ全体のスクリーンショット"), |
| title="Full Page Screenshot App", |
| description="HTMLをヘッドレスブラウザでレンダリングし、ページ全体を1枚の画像として取得します。" |
| ) |
|
|
| if __name__ == "__main__": |
| iface.launch() |
|
|