File size: 3,381 Bytes
b26e489
 
e0538f9
 
 
 
b26e489
 
e0538f9
 
 
b26e489
e170610
b26e489
 
 
 
e0538f9
 
75301b6
 
 
 
e0538f9
b26e489
 
fbe2dc1
b26e489
e0538f9
75301b6
e0538f9
 
 
e170610
 
75301b6
e170610
75301b6
 
 
 
 
 
 
 
 
e170610
600cc03
 
75301b6
e170610
 
ee6f0ce
e170610
 
ee6f0ce
e170610
75301b6
e170610
 
 
600cc03
75301b6
e170610
 
fbe2dc1
e170610
 
 
 
e0538f9
75301b6
e170610
 
 
ee6f0ce
e170610
 
 
 
e0538f9
 
 
 
b26e489
 
 
 
e0538f9
e170610
b26e489
 
fbe2dc1
b26e489
e170610
75301b6
 
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
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):
    tmp_file = tempfile.NamedTemporaryFile(suffix=".html", delete=False)
    tmp_path = tmp_file.name
    tmp_file.write(html_code.encode('utf-8'))
    tmp_file.close()

    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)
        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(2)

        # 固定要素を強制的に「static」にして、重複しにくくする
        driver.execute_script(
            """
            const elems = document.querySelectorAll('*');
            for (const e of elems) {
                const style = window.getComputedStyle(e);
                if (style.position === 'fixed' || style.position === 'sticky') {
                    e.style.position = 'static';
                }
            }
            """
        )
        time.sleep(1)

        # ページ高さを取得
        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)

        # 縦方向に結合
        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:
        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

iface = gr.Interface(
    fn=render_fullpage_screenshot,
    inputs=gr.Textbox(lines=15, label="HTMLコード入力"),
    outputs=gr.Image(type="pil", label="フルページスクリーンショット"),
    title="Scrolling Screenshot (Remove Fixed Elements)",
    description="固定要素をstaticに変更して、重複を防ぎつつページ全体をキャプチャします。"
)

if __name__ == "__main__":
    iface.launch()