tomo2chin2's picture
Update app.py
e170610 verified
raw
history blame
4.37 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 render_fullpage_screenshot(html_code):
"""
ページを少しずつスクロールしながら複数回のスクリーンショットを撮影し、
それらを縦方向に結合して1枚の長い画像にする。
"""
# 1) 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()
# 2) ヘッドレスChrome(Chromium)起動オプション設定
options = Options()
options.add_argument("--headless") # ヘッドレスモード
options.add_argument("--no-sandbox") # コンテナ環境でのサンドボックス無効化
options.add_argument("--disable-dev-shm-usage") # /dev/shmを使わない
options.add_argument("--force-device-scale-factor=1") # DPI/スケール固定
try:
driver = webdriver.Chrome(options=options)
# 適当な初期ウィンドウサイズに設定してページを読み込む
driver.set_window_size(1200, 800)
driver.get("file://" + tmp_path)
# 3) ページロード完了を待機
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.TAG_NAME, "body"))
)
# さらにフォントや外部リソースを読み込み終わるまで少し待つ
time.sleep(2)
# ---- スクロールバーを非表示にしたい場合 ----
# (ただし一部ページでレイアウトが変化する可能性があるので要注意)
driver.execute_script(
"document.documentElement.style.overflow = 'hidden';"
"document.body.style.overflow = 'hidden';"
)
time.sleep(1)
# 4) 画面のビューポート高・ページ全体の高さを取得
viewport_height = driver.execute_script("return window.innerHeight")
scroll_height = driver.execute_script("return document.body.scrollHeight")
# スクロール+キャプチャを繰り返す
images = []
current_position = 0
while True:
# 現在の画面をスクリーンショット
png = driver.get_screenshot_as_png()
img = Image.open(BytesIO(png))
images.append(img)
# もし次のスクロールでページ末尾を超えるなら、ループを抜ける
if current_position + viewport_height >= scroll_height:
break
# 次のスクロール位置へ移動
current_position += viewport_height
driver.execute_script(f"window.scrollTo(0, {current_position})")
# スクロール後の描画待ち
time.sleep(1)
# 5) 取得した複数画像を縦方向に結合
total_width = max(img.width for img in images)
total_height = sum(img.height for img in images)
full_screenshot = Image.new('RGB', (total_width, total_height))
current_y = 0
for img in images:
full_screenshot.paste(img, (0, current_y))
current_y += img.height
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 full_screenshot
# 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 with Scrolling",
description=(
"ページを少しずつスクロールしながら複数回キャプチャを撮影し、"
"最終的に縦に結合して1枚の長い画像を生成します。"
)
)
if __name__ == "__main__":
iface.launch()