tomo2chin2 commited on
Commit
e864d35
·
verified ·
1 Parent(s): 23914ff

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -35
app.py CHANGED
@@ -1,8 +1,8 @@
1
- # --- START OF FILE app.py ---
2
-
3
  import gradio as gr
4
  from fastapi import FastAPI, HTTPException, Body
5
  from fastapi.responses import StreamingResponse
 
 
6
  from pydantic import BaseModel
7
  from selenium import webdriver
8
  from selenium.webdriver.chrome.options import Options
@@ -14,7 +14,7 @@ from io import BytesIO
14
  import tempfile
15
  import time
16
  import os
17
- import logging # loggingを追加
18
 
19
  # ロギング設定
20
  logging.basicConfig(level=logging.INFO)
@@ -84,7 +84,6 @@ def render_fullpage_screenshot(html_code: str, extension_percentage: float) -> I
84
  except Exception as e:
85
  logger.warning(f"Could not hide scrollbars via JS: {e}")
86
 
87
-
88
  # 6) Get full page dimensions accurately
89
  try:
90
  scroll_width = driver.execute_script(
@@ -105,14 +104,12 @@ def render_fullpage_screenshot(html_code: str, extension_percentage: float) -> I
105
  scroll_height = 800
106
  logger.warning(f"Falling back to dimensions: width={scroll_width}, height={scroll_height}")
107
 
108
-
109
  # 7) Calculate adjusted height with user-specified margin
110
  adjusted_height = int(scroll_height * (1 + extension_percentage / 100.0))
111
  # Ensure adjusted height is not excessively large or small
112
  adjusted_height = max(adjusted_height, scroll_height, 100) # 最小高さを確保
113
  logger.info(f"Adjusted height calculated: {adjusted_height} (extension: {extension_percentage}%)")
114
 
115
-
116
  # 8) Set window size to full page dimensions (width) and adjusted height
117
  logger.info(f"Resizing window to: width={scroll_width}, height={adjusted_height}")
118
  driver.set_window_size(scroll_width, adjusted_height)
@@ -134,27 +131,10 @@ def render_fullpage_screenshot(html_code: str, extension_percentage: float) -> I
134
 
135
  # Convert to PIL Image
136
  img = Image.open(BytesIO(png))
137
- # Crop the image back to the original scroll_height plus margin
138
- # This removes extra blank space at the bottom if window resize was much larger
139
- # The screenshot captures the viewport, which we set to adjusted_height
140
- # We only need scroll_height + (scroll_height * extension_percentage / 200) top/bottom margin
141
- # However, simple approach: use adjusted_height directly or crop if needed.
142
- # Let's return the full adjusted_height capture for now.
143
- # If cropping is needed:
144
- # final_height = int(scroll_height * (1 + extension_percentage / 100.0))
145
- # if img.height > final_height:
146
- # img = img.crop((0, 0, img.width, final_height))
147
- # logger.info(f"Cropped image to final height: {final_height}")
148
-
149
  return img
150
 
151
  except Exception as e:
152
  logger.error(f"An error occurred during screenshot generation: {e}", exc_info=True)
153
- # Optionally capture a screenshot even on error for debugging
154
- # try:
155
- # if driver: driver.save_screenshot("error_screenshot.png")
156
- # except Exception as screen_err:
157
- # logger.error(f"Could not save error screenshot: {screen_err}")
158
  return Image.new('RGB', (1, 1), color=(0, 0, 0)) # Return black 1x1 image on error
159
  finally:
160
  logger.info("Cleaning up...")
@@ -174,6 +154,45 @@ def render_fullpage_screenshot(html_code: str, extension_percentage: float) -> I
174
  # --- FastAPI Setup ---
175
  app = FastAPI()
176
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  # Pydantic model for API request body validation
178
  class ScreenshotRequest(BaseModel):
179
  html_code: str
@@ -202,7 +221,6 @@ async def api_render_screenshot(request: ScreenshotRequest):
202
  # Optionally return a proper error response instead of 1x1 image
203
  # raise HTTPException(status_code=500, detail="Failed to generate screenshot")
204
 
205
-
206
  # Convert PIL Image to PNG bytes
207
  img_byte_arr = BytesIO()
208
  pil_image.save(img_byte_arr, format='PNG')
@@ -216,7 +234,6 @@ async def api_render_screenshot(request: ScreenshotRequest):
216
  raise HTTPException(status_code=500, detail=f"Internal Server Error: {e}")
217
 
218
  # --- Gradio Interface Definition ---
219
- # Note: We reuse the same core function 'render_fullpage_screenshot'
220
  iface = gr.Interface(
221
  fn=render_fullpage_screenshot,
222
  inputs=[
@@ -224,23 +241,17 @@ iface = gr.Interface(
224
  gr.Slider(minimum=0, maximum=20, step=1.0, value=8, label="上下高さ拡張率(%)")
225
  ],
226
  outputs=gr.Image(type="pil", label="ページ全体のスクリーンショット"),
227
- title="Full Page Screenshot (高さ拡張調整可能)", # APIを削除
228
  description="HTMLをヘッドレスブラウザでレンダリングし、ページ全体を1枚の画像として取得します。上下のみユーザー指定の余裕(%)を追加します。APIエンドポイントは /api/screenshot で利用可能です。",
229
- allow_flagging="never" # Hugging Face Spacesでのフラグ付けを無効化 (任意)
 
230
  )
231
 
232
  # --- Mount Gradio App onto FastAPI ---
233
- # Mount the Gradio interface at the root path "/"
234
  app = gr.mount_gradio_app(app, iface, path="/")
235
 
236
  # --- Run with Uvicorn (for local testing) ---
237
- # This part is mainly for local development.
238
- # When deploying on Hugging Face Spaces, the Spaces runtime handles launching the app.
239
  if __name__ == "__main__":
240
  import uvicorn
241
  logger.info("Starting Uvicorn server for local development...")
242
- # Host '0.0.0.0' makes it accessible on the network
243
- # Port 7860 is a common default for Gradio, but 8000 is common for FastAPI
244
- uvicorn.run(app, host="0.0.0.0", port=7860)
245
-
246
- # --- END OF FILE app.py ---
 
 
 
1
  import gradio as gr
2
  from fastapi import FastAPI, HTTPException, Body
3
  from fastapi.responses import StreamingResponse
4
+ from fastapi.staticfiles import StaticFiles
5
+ from fastapi.middleware.cors import CORSMiddleware
6
  from pydantic import BaseModel
7
  from selenium import webdriver
8
  from selenium.webdriver.chrome.options import Options
 
14
  import tempfile
15
  import time
16
  import os
17
+ import logging
18
 
19
  # ロギング設定
20
  logging.basicConfig(level=logging.INFO)
 
84
  except Exception as e:
85
  logger.warning(f"Could not hide scrollbars via JS: {e}")
86
 
 
87
  # 6) Get full page dimensions accurately
88
  try:
89
  scroll_width = driver.execute_script(
 
104
  scroll_height = 800
105
  logger.warning(f"Falling back to dimensions: width={scroll_width}, height={scroll_height}")
106
 
 
107
  # 7) Calculate adjusted height with user-specified margin
108
  adjusted_height = int(scroll_height * (1 + extension_percentage / 100.0))
109
  # Ensure adjusted height is not excessively large or small
110
  adjusted_height = max(adjusted_height, scroll_height, 100) # 最小高さを確保
111
  logger.info(f"Adjusted height calculated: {adjusted_height} (extension: {extension_percentage}%)")
112
 
 
113
  # 8) Set window size to full page dimensions (width) and adjusted height
114
  logger.info(f"Resizing window to: width={scroll_width}, height={adjusted_height}")
115
  driver.set_window_size(scroll_width, adjusted_height)
 
131
 
132
  # Convert to PIL Image
133
  img = Image.open(BytesIO(png))
 
 
 
 
 
 
 
 
 
 
 
 
134
  return img
135
 
136
  except Exception as e:
137
  logger.error(f"An error occurred during screenshot generation: {e}", exc_info=True)
 
 
 
 
 
138
  return Image.new('RGB', (1, 1), color=(0, 0, 0)) # Return black 1x1 image on error
139
  finally:
140
  logger.info("Cleaning up...")
 
154
  # --- FastAPI Setup ---
155
  app = FastAPI()
156
 
157
+ # CORS設定を追加
158
+ app.add_middleware(
159
+ CORSMiddleware,
160
+ allow_origins=["*"],
161
+ allow_credentials=True,
162
+ allow_methods=["*"],
163
+ allow_headers=["*"],
164
+ )
165
+
166
+ # 静的ファイルのサービング設定
167
+ # Gradioのディレクトリを探索してアセットを見つける
168
+ gradio_dir = os.path.dirname(gr.__file__)
169
+ logger.info(f"Gradio version: {gr.__version__}")
170
+ logger.info(f"Gradio directory: {gradio_dir}")
171
+
172
+ # 基本的な静的ファイルディレクトリをマウント
173
+ static_dir = os.path.join(gradio_dir, "templates", "frontend", "static")
174
+ if os.path.exists(static_dir):
175
+ logger.info(f"Mounting static directory: {static_dir}")
176
+ app.mount("/static", StaticFiles(directory=static_dir), name="static")
177
+
178
+ # _appディレクトリを探す(新しいSvelteKitベースのフロントエンド用)
179
+ app_dir = os.path.join(gradio_dir, "templates", "frontend", "_app")
180
+ if os.path.exists(app_dir):
181
+ logger.info(f"Mounting _app directory: {app_dir}")
182
+ app.mount("/_app", StaticFiles(directory=app_dir), name="_app")
183
+
184
+ # assetsディレクトリを探す
185
+ assets_dir = os.path.join(gradio_dir, "templates", "frontend", "assets")
186
+ if os.path.exists(assets_dir):
187
+ logger.info(f"Mounting assets directory: {assets_dir}")
188
+ app.mount("/assets", StaticFiles(directory=assets_dir), name="assets")
189
+
190
+ # cdnディレクトリがあれば追加
191
+ cdn_dir = os.path.join(gradio_dir, "templates", "cdn")
192
+ if os.path.exists(cdn_dir):
193
+ logger.info(f"Mounting cdn directory: {cdn_dir}")
194
+ app.mount("/cdn", StaticFiles(directory=cdn_dir), name="cdn")
195
+
196
  # Pydantic model for API request body validation
197
  class ScreenshotRequest(BaseModel):
198
  html_code: str
 
221
  # Optionally return a proper error response instead of 1x1 image
222
  # raise HTTPException(status_code=500, detail="Failed to generate screenshot")
223
 
 
224
  # Convert PIL Image to PNG bytes
225
  img_byte_arr = BytesIO()
226
  pil_image.save(img_byte_arr, format='PNG')
 
234
  raise HTTPException(status_code=500, detail=f"Internal Server Error: {e}")
235
 
236
  # --- Gradio Interface Definition ---
 
237
  iface = gr.Interface(
238
  fn=render_fullpage_screenshot,
239
  inputs=[
 
241
  gr.Slider(minimum=0, maximum=20, step=1.0, value=8, label="上下高さ拡張率(%)")
242
  ],
243
  outputs=gr.Image(type="pil", label="ページ全体のスクリーンショット"),
244
+ title="Full Page Screenshot (高さ拡張調整可能)",
245
  description="HTMLをヘッドレスブラウザでレンダリングし、ページ全体を1枚の画像として取得します。上下のみユーザー指定の余裕(%)を追加します。APIエンドポイントは /api/screenshot で利用可能です。",
246
+ allow_flagging="never",
247
+ theme=gr.themes.Base() # 明示的にテーマを指定
248
  )
249
 
250
  # --- Mount Gradio App onto FastAPI ---
 
251
  app = gr.mount_gradio_app(app, iface, path="/")
252
 
253
  # --- Run with Uvicorn (for local testing) ---
 
 
254
  if __name__ == "__main__":
255
  import uvicorn
256
  logger.info("Starting Uvicorn server for local development...")
257
+ uvicorn.run(app, host="0.0.0.0", port=7860)