rajthakkar123 commited on
Commit
c640d46
Β·
verified Β·
1 Parent(s): 2048081

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -144
app.py CHANGED
@@ -83,12 +83,9 @@ class SimpleChromeController:
83
  def is_chrome_accessible(self):
84
  """Check if Chrome debugging port is accessible"""
85
  try:
86
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
87
- sock.settimeout(2)
88
- result = sock.connect_ex(('127.0.0.1', 9222))
89
- sock.close()
90
- return result == 0
91
- except Exception:
92
  return False
93
 
94
  def start_chrome(self):
@@ -135,6 +132,7 @@ class SimpleChromeController:
135
  chrome_options.add_argument("--no-sandbox")
136
  chrome_options.add_argument("--disable-dev-shm-usage")
137
 
 
138
  service = Service(ChromeDriverManager().install())
139
  return webdriver.Chrome(service=service, options=chrome_options)
140
 
@@ -146,17 +144,15 @@ class SimpleChromeController:
146
  if not self.is_chrome_accessible():
147
  return "❌ Chrome is not running. Please start Chrome first."
148
 
149
- # Add protocol if missing
150
  if not url.startswith(('http://', 'https://')):
151
  url = 'https://' + url.strip()
152
 
153
  driver = None
154
  try:
155
  driver = self.get_driver()
156
- driver.set_window_size(1920, 1080)
157
  driver.get(url)
158
 
159
- # Wait for page to load
160
  WebDriverWait(driver, 10).until(
161
  lambda d: d.execute_script("return document.readyState") == "complete"
162
  )
@@ -168,10 +164,7 @@ class SimpleChromeController:
168
  return f"❌ Error navigating to URL: {str(e)}"
169
  finally:
170
  if driver:
171
- try:
172
- driver.quit()
173
- except:
174
- pass
175
 
176
  def take_screenshot(self):
177
  """Take a screenshot of the current page"""
@@ -181,9 +174,7 @@ class SimpleChromeController:
181
  driver = None
182
  try:
183
  driver = self.get_driver()
184
- driver.set_window_size(1920, 1080)
185
 
186
- # Get current page info
187
  current_url = driver.current_url
188
  if not current_url or current_url == "data:,":
189
  driver.get("https://www.google.com")
@@ -191,13 +182,9 @@ class SimpleChromeController:
191
  lambda d: d.execute_script("return document.readyState") == "complete"
192
  )
193
 
194
- # Take screenshot
195
  screenshot_data = driver.get_screenshot_as_png()
196
-
197
- # Convert to PIL Image
198
  screenshot_image = Image.open(io.BytesIO(screenshot_data))
199
 
200
- # Get page info
201
  page_title = driver.title or "Unknown"
202
  page_url = driver.current_url or "Unknown"
203
 
@@ -207,10 +194,7 @@ class SimpleChromeController:
207
  return None, f"❌ Error taking screenshot: {str(e)}"
208
  finally:
209
  if driver:
210
- try:
211
- driver.quit()
212
- except:
213
- pass
214
 
215
  def execute_javascript(self, js_code):
216
  """Execute JavaScript code in the browser"""
@@ -230,55 +214,34 @@ class SimpleChromeController:
230
  return f"❌ Error executing JavaScript: {str(e)}"
231
  finally:
232
  if driver:
233
- try:
234
- driver.quit()
235
- except:
236
- pass
237
 
238
  def kill_chrome(self):
239
  """Kill all Chrome processes"""
240
  self.is_running = False
241
-
242
- killed_processes = []
243
-
244
- # Kill Chrome processes by name
245
  try:
246
  for proc in psutil.process_iter(['pid', 'name']):
247
- if proc.info['name'] and 'chrome' in proc.info['name'].lower():
248
  try:
249
  proc.terminate()
250
- killed_processes.append(f"PID {proc.info['pid']}")
251
  except (psutil.NoSuchProcess, psutil.AccessDenied):
252
  pass
253
  except Exception:
254
  pass
255
 
256
- # Kill the main process if it exists
257
  if self.chrome_process:
258
  try:
259
- if hasattr(os, 'killpg'):
260
- os.killpg(os.getpgid(self.chrome_process.pid), 15)
261
- else:
262
- self.chrome_process.terminate()
263
-
264
- self.chrome_process.wait(timeout=5)
265
  except:
266
- try:
267
- if hasattr(os, 'killpg'):
268
- os.killpg(os.getpgid(self.chrome_process.pid), 9)
269
- else:
270
- self.chrome_process.kill()
271
- except:
272
- pass
273
  self.chrome_process = None
274
 
275
  time.sleep(1)
276
 
277
- result = "πŸ›‘ Chrome processes terminated"
278
- if killed_processes:
279
- result += f" (killed: {', '.join(killed_processes)})"
280
-
281
- return result
282
 
283
  def get_status(self):
284
  """Get current Chrome status"""
@@ -287,114 +250,72 @@ class SimpleChromeController:
287
  else:
288
  return "β­• Chrome is not running or not accessible"
289
 
290
- # Initialize the controller
291
  chrome_controller = SimpleChromeController()
292
 
293
- # Create simple Gradio interface using only basic components
294
- def create_simple_interface():
295
-
296
- with gr.Blocks(title="Chrome Controller") as demo:
297
-
298
- gr.Markdown("# 🌐 Chrome Controller for Hugging Face Spaces")
299
- gr.Markdown("Control a headless Chrome instance - Simple & Stable Version")
300
-
301
- # Browser Control Section
302
- gr.Markdown("## πŸš€ Browser Control")
303
- with gr.Row():
304
- start_btn = gr.Button("πŸš€ Start Chrome", variant="primary")
305
- status_btn = gr.Button("πŸ“Š Check Status")
306
- stop_btn = gr.Button("πŸ›‘ Stop Chrome", variant="stop")
307
-
308
- status_output = gr.Textbox(
309
- label="Status",
310
- interactive=False,
311
- lines=4,
312
- value="Chrome Controller ready. Click 'Start Chrome' to begin."
313
- )
314
-
315
- # Navigation Section
316
- gr.Markdown("## 🧭 Navigation & Screenshots")
317
- with gr.Row():
318
- url_input = gr.Textbox(
319
- label="URL to Navigate",
320
- value="google.com",
321
- lines=1
322
- )
323
- navigate_btn = gr.Button("🧭 Navigate", variant="primary")
324
- screenshot_btn = gr.Button("πŸ“Έ Take Screenshot", variant="secondary")
325
-
326
- screenshot_output = gr.Image(
327
- label="Screenshot",
328
- height=400
329
- )
330
-
331
- # JavaScript Section
332
- gr.Markdown("## ⚑ JavaScript Execution")
333
- js_input = gr.Textbox(
334
- label="JavaScript Code",
335
- lines=6,
336
- value="// Enter JavaScript code here\n// Example: document.title"
337
- )
338
- execute_btn = gr.Button("⚑ Execute JavaScript", variant="primary")
339
- js_output = gr.Textbox(
340
- label="Execution Result",
341
- interactive=False,
342
- lines=6
343
- )
344
-
345
- # Event handlers
346
- start_btn.click(
347
- fn=chrome_controller.start_chrome,
348
- outputs=status_output
349
- )
350
 
351
- status_btn.click(
352
- fn=chrome_controller.get_status,
353
- outputs=status_output
354
- )
355
 
356
  navigate_btn.click(
357
- fn=chrome_controller.navigate_to_url,
358
- inputs=url_input,
359
- outputs=status_output
360
  )
361
-
362
  screenshot_btn.click(
363
- fn=chrome_controller.take_screenshot,
364
- outputs=[screenshot_output, status_output]
365
  )
366
-
367
  execute_btn.click(
368
- fn=chrome_controller.execute_javascript,
369
  inputs=js_input,
370
  outputs=js_output
371
  )
372
-
373
- stop_btn.click(
374
- fn=chrome_controller.kill_chrome,
375
- outputs=status_output
376
- )
377
-
378
- # Help section
379
- gr.Markdown("""
380
- ### πŸ’‘ Example JavaScript Commands:
381
- - `document.title` - Get page title
382
- - `window.location.href` - Get current URL
383
- - `document.body.innerHTML` - Get page HTML
384
- - `document.querySelectorAll('a').length` - Count links
385
- - `window.scrollTo(0, document.body.scrollHeight)` - Scroll to bottom
386
- """)
387
-
388
  return demo
389
 
390
  if __name__ == "__main__":
391
- # Create and launch the interface
392
- demo = create_simple_interface()
393
-
394
- # Launch with settings that work reliably on HF Spaces
395
  demo.launch(
396
  server_name="0.0.0.0",
397
  server_port=7860,
398
- share=False,
399
- show_error=True
400
  )
 
83
  def is_chrome_accessible(self):
84
  """Check if Chrome debugging port is accessible"""
85
  try:
86
+ with socket.create_connection(("127.0.0.1", 9222), timeout=2) as sock:
87
+ return True
88
+ except (socket.timeout, ConnectionRefusedError):
 
 
 
89
  return False
90
 
91
  def start_chrome(self):
 
132
  chrome_options.add_argument("--no-sandbox")
133
  chrome_options.add_argument("--disable-dev-shm-usage")
134
 
135
+ # Use a cached driver install
136
  service = Service(ChromeDriverManager().install())
137
  return webdriver.Chrome(service=service, options=chrome_options)
138
 
 
144
  if not self.is_chrome_accessible():
145
  return "❌ Chrome is not running. Please start Chrome first."
146
 
 
147
  if not url.startswith(('http://', 'https://')):
148
  url = 'https://' + url.strip()
149
 
150
  driver = None
151
  try:
152
  driver = self.get_driver()
153
+ driver.set_page_load_timeout(20)
154
  driver.get(url)
155
 
 
156
  WebDriverWait(driver, 10).until(
157
  lambda d: d.execute_script("return document.readyState") == "complete"
158
  )
 
164
  return f"❌ Error navigating to URL: {str(e)}"
165
  finally:
166
  if driver:
167
+ driver.quit()
 
 
 
168
 
169
  def take_screenshot(self):
170
  """Take a screenshot of the current page"""
 
174
  driver = None
175
  try:
176
  driver = self.get_driver()
 
177
 
 
178
  current_url = driver.current_url
179
  if not current_url or current_url == "data:,":
180
  driver.get("https://www.google.com")
 
182
  lambda d: d.execute_script("return document.readyState") == "complete"
183
  )
184
 
 
185
  screenshot_data = driver.get_screenshot_as_png()
 
 
186
  screenshot_image = Image.open(io.BytesIO(screenshot_data))
187
 
 
188
  page_title = driver.title or "Unknown"
189
  page_url = driver.current_url or "Unknown"
190
 
 
194
  return None, f"❌ Error taking screenshot: {str(e)}"
195
  finally:
196
  if driver:
197
+ driver.quit()
 
 
 
198
 
199
  def execute_javascript(self, js_code):
200
  """Execute JavaScript code in the browser"""
 
214
  return f"❌ Error executing JavaScript: {str(e)}"
215
  finally:
216
  if driver:
217
+ driver.quit()
 
 
 
218
 
219
  def kill_chrome(self):
220
  """Kill all Chrome processes"""
221
  self.is_running = False
222
+ killed_processes = 0
223
+
 
 
224
  try:
225
  for proc in psutil.process_iter(['pid', 'name']):
226
+ if 'chrome' in proc.info['name'].lower():
227
  try:
228
  proc.terminate()
229
+ killed_processes += 1
230
  except (psutil.NoSuchProcess, psutil.AccessDenied):
231
  pass
232
  except Exception:
233
  pass
234
 
 
235
  if self.chrome_process:
236
  try:
237
+ os.killpg(os.getpgid(self.chrome_process.pid), 9)
 
 
 
 
 
238
  except:
239
+ pass
 
 
 
 
 
 
240
  self.chrome_process = None
241
 
242
  time.sleep(1)
243
 
244
+ return f"πŸ›‘ Chrome processes terminated ({killed_processes} killed)"
 
 
 
 
245
 
246
  def get_status(self):
247
  """Get current Chrome status"""
 
250
  else:
251
  return "β­• Chrome is not running or not accessible"
252
 
 
253
  chrome_controller = SimpleChromeController()
254
 
255
+ def create_interface():
256
+ with gr.Blocks(theme=gr.themes.Soft(), title="Chrome Controller") as demo:
257
+ gr.Markdown("# 🌐 Chrome Controller Pro")
258
+ gr.Markdown("Control a headless Chrome instance for advanced web automation.")
259
+
260
+ with gr.Tabs():
261
+ with gr.TabItem("πŸš€ Control & Status"):
262
+ with gr.Row():
263
+ start_btn = gr.Button("πŸš€ Start Chrome", variant="primary", scale=1)
264
+ stop_btn = gr.Button("πŸ›‘ Stop Chrome", variant="stop", scale=1)
265
+ status_btn = gr.Button("πŸ“Š Check Status", scale=1)
266
+
267
+ status_output = gr.Textbox(
268
+ label="Status",
269
+ interactive=False,
270
+ lines=5,
271
+ value="Chrome is not running. Click 'Start Chrome' to begin."
272
+ )
273
+
274
+ with gr.TabItem("🧭 Navigate & Screenshot"):
275
+ with gr.Row():
276
+ url_input = gr.Textbox(label="URL", placeholder="e.g., google.com", scale=4)
277
+ navigate_btn = gr.Button("🧭 Navigate", variant="primary", scale=1)
278
+
279
+ screenshot_btn = gr.Button("πŸ“Έ Take Screenshot", variant="secondary")
280
+
281
+ screenshot_output = gr.Image(label="Screenshot", type="pil", height=500)
282
+ screenshot_status = gr.Textbox(label="Action Status", interactive=False)
283
+
284
+ with gr.TabItem("⚑ Execute JavaScript"):
285
+ js_input = gr.Textbox(
286
+ label="JavaScript Code",
287
+ lines=8,
288
+ value="// Example: return document.title;"
289
+ )
290
+ execute_btn = gr.Button("⚑ Execute JS", variant="primary")
291
+ js_output = gr.Textbox(label="JS Execution Result", interactive=False, lines=8)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
 
293
+ # Event Handlers
294
+ start_btn.click(chrome_controller.start_chrome, outputs=status_output)
295
+ stop_btn.click(chrome_controller.kill_chrome, outputs=status_output)
296
+ status_btn.click(chrome_controller.get_status, outputs=status_output)
297
 
298
  navigate_btn.click(
299
+ chrome_controller.navigate_to_url,
300
+ inputs=url_input,
301
+ outputs=screenshot_status
302
  )
 
303
  screenshot_btn.click(
304
+ chrome_controller.take_screenshot,
305
+ outputs=[screenshot_output, screenshot_status]
306
  )
 
307
  execute_btn.click(
308
+ chrome_controller.execute_javascript,
309
  inputs=js_input,
310
  outputs=js_output
311
  )
312
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  return demo
314
 
315
  if __name__ == "__main__":
316
+ demo = create_interface()
 
 
 
317
  demo.launch(
318
  server_name="0.0.0.0",
319
  server_port=7860,
320
+ share=True # Important for Hugging Face Spaces
 
321
  )