Spaces:
Paused
Paused
| 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): | |
| # HTMLを一時ファイルに保存 | |
| tmp_file = tempfile.NamedTemporaryFile(suffix=".html", delete=False) | |
| tmp_path = tmp_file.name | |
| tmp_file.write(html_code.encode('utf-8')) | |
| tmp_file.close() | |
| # ヘッドレスChrome起動オプション | |
| 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) | |
| # 1) とりあえず適当なウィンドウサイズで開く | |
| 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) | |
| # 2) ページ全体サイズを取得してウィンドウを拡張 | |
| # → Lazy Loadがあればスクロールして要素を読み込む | |
| max_iterations = 3 | |
| for _ in range(max_iterations): | |
| # ページ全体の幅・高さを取得 | |
| w1, h1 = get_full_dimensions(driver) | |
| # ウィンドウをそのサイズに合わせる | |
| driver.set_window_size(w1, h1) | |
| time.sleep(1) | |
| # 一度最下部までスクロールし、Lazy Load等を促す | |
| scroll_to_bottom(driver) | |
| # 再度サイズを取得 | |
| w2, h2 = get_full_dimensions(driver) | |
| # 変化がなければ打ち切り | |
| if (w1 == w2) and (h1 == h2): | |
| break | |
| # 3) 最後にスクロールバーを消したい場合はここでoverflow: hidden | |
| driver.execute_script(""" | |
| document.documentElement.style.overflow = 'hidden'; | |
| document.body.style.overflow = 'hidden'; | |
| """) | |
| time.sleep(1) | |
| # overflow: hidden による再レイアウトを考慮してもう一度調整 | |
| w3, h3 = get_full_dimensions(driver) | |
| driver.set_window_size(w3, h3) | |
| time.sleep(1) | |
| # 4) 最終的にスクリーンショットを撮る | |
| png = driver.get_screenshot_as_png() | |
| except Exception as e: | |
| # エラー時は1x1の黒画像を返す | |
| 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)) | |
| # Gradioインターフェース | |
| 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() | |