HTMLviewer2_API / app.py
tomo2chin2's picture
Update app.py
ee6f0ce verified
raw
history blame
4.59 kB
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)
# ---- (A) 一度ページ全体のサイズを取得してウィンドウを拡張 ----
w1, h1 = get_full_dimensions(driver)
driver.set_window_size(w1, h1)
time.sleep(1)
# ---- (B) ページ下端までスクロールしてLazy Load等を発火させる ----
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)
# ---- (C) スクロールバーを非表示にする(不要ならコメントアウト)----
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)
# ---- (D) ★最終的にトップへ戻す★ ----
driver.execute_script("window.scrollTo(0, 0);")
time.sleep(1)
# ---- (E) スクリーンショット取得 ----
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()