File size: 4,367 Bytes
b26e489 e0538f9 b26e489 e0538f9 b26e489 e170610 600cc03 e170610 600cc03 e170610 b26e489 e0538f9 e170610 e0538f9 e170610 e0538f9 b26e489 e170610 fbe2dc1 b26e489 e0538f9 e170610 e0538f9 e170610 600cc03 e170610 ee6f0ce e170610 ee6f0ce e170610 600cc03 e170610 fbe2dc1 e170610 e0538f9 e170610 ee6f0ce e170610 e0538f9 e170610 e0538f9 b26e489 e0538f9 e170610 b26e489 fbe2dc1 b26e489 fbe2dc1 b26e489 e170610 b26e489 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 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()
|