File size: 3,424 Bytes
b26e489
 
e0538f9
e6532da
 
 
da755ee
 
e6532da
 
 
26b8c3d
e6532da
 
 
 
 
 
 
 
 
 
 
 
 
26b8c3d
 
e6532da
da755ee
e6532da
 
 
da755ee
e6532da
 
 
 
 
 
da755ee
e6532da
da755ee
e6532da
 
 
 
 
 
 
 
 
 
 
 
 
 
da755ee
e6532da
 
 
 
da755ee
e6532da
 
 
 
 
 
 
 
 
 
da755ee
26b8c3d
da755ee
e6532da
 
 
 
 
da755ee
e6532da
 
 
 
 
 
 
b26e489
 
 
e6532da
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
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) 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")
    options.add_argument("--force-device-scale-factor=1")

    try:
        driver = webdriver.Chrome(options=options)

        # 3) まずはある程度のウィンドウサイズでページを開く
        driver.set_window_size(1200, 800)
        driver.get("file://" + tmp_path)

        # 4) ページのロードを待機
        WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.TAG_NAME, "body"))
        )
        # 外部リソース読み込み等の安定化のため余分に待機
        time.sleep(2)

        # 5) スクロールバーを写したくない場合はCSSで非表示にする
        driver.execute_script(
            "document.documentElement.style.overflow = 'hidden';"
            "document.body.style.overflow = 'hidden';"
        )

        # 6) ページ全体の幅・高さを正確に取得
        #    bodyとdocumentElementの値を比較し、より大きい方を使用
        scroll_width = driver.execute_script(
            "return Math.max("
            "document.body.scrollWidth, document.documentElement.scrollWidth)"
        )
        scroll_height = driver.execute_script(
            "return Math.max("
            "document.body.scrollHeight, document.documentElement.scrollHeight)"
        )

        # 7) ウィンドウサイズをページ全体に合わせる
        #    少し余裕をもたせるため+50などしてもOK
        driver.set_window_size(scroll_width, scroll_height)
        time.sleep(2)  # レイアウトが変わるので少し待つ

        # 念のためページ最上部にスクロール
        driver.execute_script("window.scrollTo(0, 0)")
        time.sleep(1)

        # 8) スクリーンショットを取得
        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)

    # 9) PNGバイナリをPIL.Imageに変換して返す
    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()