mirror of
https://github.com/j93es/browser-use-oauth.git
synced 2026-06-05 00:01:28 +09:00
Browser Use 최신버전 업데이트 및 프로필 기능 유지
This commit is contained in:
parent
e1ae2dc94f
commit
2ee917408f
3 changed files with 56 additions and 100 deletions
2
login.py
2
login.py
|
|
@ -11,7 +11,7 @@ def launch_browser_with_profile():
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
browser, page, playwright = launch_browser_with_profile()
|
browser, page, playwright = launch_browser_with_profile()
|
||||||
page.goto("https://example.com")
|
page.goto("https://google.com")
|
||||||
print("Browser launched with user data profile.")
|
print("Browser launched with user data profile.")
|
||||||
|
|
||||||
# 브라우저가 열린 상태를 유지
|
# 브라우저가 열린 상태를 유지
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
# run uv run playwright open https://google.com/ --user_data_dir=~/.config/browseruse/profiles/default in shell
|
|
||||||
|
|
||||||
from playwright.sync_api import sync_playwright
|
|
||||||
import os
|
|
||||||
|
|
||||||
user_data_dir = os.path.expanduser("~/.config/browseruse/profiles/default")
|
|
||||||
|
|
||||||
with sync_playwright() as p:
|
|
||||||
browser = p.chromium.launch_persistent_context(
|
|
||||||
user_data_dir=user_data_dir,
|
|
||||||
headless=False,
|
|
||||||
)
|
|
||||||
page = browser.new_page()
|
|
||||||
page.goto("https://google.com")
|
|
||||||
|
|
||||||
# ctrl + c to exit
|
|
||||||
print("Press Ctrl+C to exit...")
|
|
||||||
try:
|
|
||||||
while True:
|
|
||||||
pass # Keep the script running
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
print("Exiting...")
|
|
||||||
finally:
|
|
||||||
browser.close()
|
|
||||||
100
main.py
100
main.py
|
|
@ -3,6 +3,7 @@ import json
|
||||||
import os
|
import os
|
||||||
import csv
|
import csv
|
||||||
import argparse
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
import requests
|
import requests
|
||||||
import time
|
import time
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
@ -12,17 +13,10 @@ from langchain_google_genai import ChatGoogleGenerativeAI
|
||||||
from langchain.callbacks.base import BaseCallbackHandler
|
from langchain.callbacks.base import BaseCallbackHandler
|
||||||
from browser_use import (
|
from browser_use import (
|
||||||
Agent,
|
Agent,
|
||||||
Browser,
|
|
||||||
BrowserConfig,
|
|
||||||
BrowserSession,
|
BrowserSession,
|
||||||
BrowserProfile,
|
BrowserProfile,
|
||||||
Controller,
|
Controller,
|
||||||
)
|
)
|
||||||
from browser_use.browser.context import BrowserContext, BrowserContextConfig
|
|
||||||
from playwright.async_api import async_playwright
|
|
||||||
|
|
||||||
# from lib import browser_config
|
|
||||||
# from lib.browser_config import browser_config_kwargs
|
|
||||||
from lib.is_html import is_html_url
|
from lib.is_html import is_html_url
|
||||||
from lib.read_txt import read_lines_between
|
from lib.read_txt import read_lines_between
|
||||||
from lib.prompt import extend_planner_system_message
|
from lib.prompt import extend_planner_system_message
|
||||||
|
|
@ -48,24 +42,18 @@ class QuotaExhaustedHandler(BaseCallbackHandler):
|
||||||
time.sleep(120)
|
time.sleep(120)
|
||||||
|
|
||||||
|
|
||||||
def create_llm_with_retry():
|
def CreateChatGoogleGenerativeAI(model: str):
|
||||||
"""재시도 로직이 포함된 LLM 생성"""
|
"""재시도 로직이 포함된 LLM 생성"""
|
||||||
|
if model == "fallback":
|
||||||
|
print("⚠️ Fallback 모델을 사용합니다. Envorinment 변수를 확인하세요.")
|
||||||
|
print("⚠️ Model Gemini-2.0-flash-lite를 사용합니다.")
|
||||||
|
model = "gemini-2.0-flash-lite"
|
||||||
return ChatGoogleGenerativeAI(
|
return ChatGoogleGenerativeAI(
|
||||||
model=os.getenv("GOOGLE_MODEL"),
|
model=model,
|
||||||
max_retries=10, # 최대 재시도 횟수 증가
|
max_retries=10, # 최대 재시도 횟수 증가
|
||||||
request_timeout=180, # 타임아웃 시간 증가 (3분)
|
model_kwargs={
|
||||||
callbacks=[QuotaExhaustedHandler()],
|
"request_timeout": 120, # 타임아웃 시간 증가 (2분)
|
||||||
# API 호출 간격 조정
|
},
|
||||||
temperature=0.1,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def create_planner_llm_with_retry():
|
|
||||||
"""플래너용 재시도 로직이 포함된 LLM 생성"""
|
|
||||||
return ChatGoogleGenerativeAI(
|
|
||||||
model=os.getenv("GOOGLE_PLANNER_MODEL"),
|
|
||||||
max_retries=10, # 최대 재시도 횟수 증가
|
|
||||||
request_timeout=180, # 타임아웃 시간 증가 (3분)
|
|
||||||
callbacks=[QuotaExhaustedHandler()],
|
callbacks=[QuotaExhaustedHandler()],
|
||||||
# API 호출 간격 조정
|
# API 호출 간격 조정
|
||||||
temperature=0.1,
|
temperature=0.1,
|
||||||
|
|
@ -82,24 +70,18 @@ class OAuthList(BaseModel):
|
||||||
oauth_providers: List[OAuth]
|
oauth_providers: List[OAuth]
|
||||||
|
|
||||||
|
|
||||||
async def clean_resources(agent, session, browser, playwright):
|
async def clean_resources(agent=None, session=None):
|
||||||
"""리소스를 정리하는 함수"""
|
"""리소스를 정리하는 함수"""
|
||||||
|
if agent:
|
||||||
try:
|
try:
|
||||||
await agent.close()
|
await agent.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ 에이전트 리소스 정리 실패: {e}")
|
print(f"⚠️ 에이전트 리소스 정리 실패: {e}")
|
||||||
|
if session:
|
||||||
try:
|
try:
|
||||||
await session.close()
|
await session.close()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ 세션 리소스 정리 실패: {e}")
|
print(f"⚠️ 세션 리소스 정리 실패: {e}")
|
||||||
try:
|
|
||||||
await browser.close()
|
|
||||||
except Exception as e:
|
|
||||||
print(f"⚠️ 브라우저 리소스 정리 실패: {e}")
|
|
||||||
try:
|
|
||||||
await playwright.stop()
|
|
||||||
except Exception as e:
|
|
||||||
print(f"⚠️ Playwright 리소스 정리 실패: {e}")
|
|
||||||
|
|
||||||
|
|
||||||
# ── URL별로 Browser를 새로 띄우는 함수 ──
|
# ── URL별로 Browser를 새로 띄우는 함수 ──
|
||||||
|
|
@ -141,11 +123,20 @@ async def scan_one_url(url: str, skip_html_check: bool = False):
|
||||||
else:
|
else:
|
||||||
print("🔗 No proxy configured, using direct connection.")
|
print("🔗 No proxy configured, using direct connection.")
|
||||||
|
|
||||||
# 2) Browser + Context 생성
|
# user_data_dir 설정
|
||||||
playwright = await async_playwright().start()
|
user_data_path = Path("./data/user_data").resolve()
|
||||||
browser = await playwright.chromium.launch(
|
user_data_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# BrowserProfile에 모든 설정 포함
|
||||||
|
profile = BrowserProfile(
|
||||||
|
disable_security=True,
|
||||||
|
stealth=True,
|
||||||
|
headless=False,
|
||||||
|
user_data_dir=str(user_data_path),
|
||||||
|
viewport={"width": 1600, "height": 900},
|
||||||
|
# 프록시 설정
|
||||||
proxy={"server": proxy_url} if proxy_url else None,
|
proxy={"server": proxy_url} if proxy_url else None,
|
||||||
headless=False, # headless 모드 사용 여부
|
# 추가 args
|
||||||
args=[
|
args=[
|
||||||
"--disable-web-security",
|
"--disable-web-security",
|
||||||
"--disable-features=VizDisplayCompositor",
|
"--disable-features=VizDisplayCompositor",
|
||||||
|
|
@ -153,31 +144,20 @@ async def scan_one_url(url: str, skip_html_check: bool = False):
|
||||||
"--disable-features=IsolateOrigins,site-per-process",
|
"--disable-features=IsolateOrigins,site-per-process",
|
||||||
"--disable-popup-blocking",
|
"--disable-popup-blocking",
|
||||||
"--disable-dev-shm-usage",
|
"--disable-dev-shm-usage",
|
||||||
f"--lang=" + os.getenv("LANG", "en_US"),
|
f"--lang={os.getenv('LANG', 'en_US')}",
|
||||||
"--ignore-certificate-errors",
|
"--ignore-certificate-errors",
|
||||||
"--ignore-ssl-errors",
|
"--ignore-ssl-errors",
|
||||||
"--allow-running-insecure-content",
|
"--allow-running-insecure-content",
|
||||||
"--restore-last-session"
|
"--restore-last-session",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
os.makedirs("./data", exist_ok=True)
|
# BrowserSession에 profile 전달
|
||||||
|
|
||||||
profile = BrowserProfile(
|
|
||||||
stealth=True,
|
|
||||||
headless=False, # headless 모드 사용 여부
|
|
||||||
user_data_dir="./data/user_data",
|
|
||||||
viewport={"width": 1600, "height": 900},
|
|
||||||
)
|
|
||||||
|
|
||||||
# BrowserSession 생성 시 headless 옵션을 명시적으로 설정
|
|
||||||
context = await browser.new_context()
|
|
||||||
|
|
||||||
session = BrowserSession(
|
session = BrowserSession(
|
||||||
browser_context=await browser.new_context(),
|
browser_profile=profile,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 3) Agent, Controller 생성
|
# Agent 생성
|
||||||
initial_actions = [
|
initial_actions = [
|
||||||
{"open_tab": {"url": target_url}},
|
{"open_tab": {"url": target_url}},
|
||||||
]
|
]
|
||||||
|
|
@ -190,15 +170,16 @@ async def scan_one_url(url: str, skip_html_check: bool = False):
|
||||||
try:
|
try:
|
||||||
agent = Agent(
|
agent = Agent(
|
||||||
browser_session=session,
|
browser_session=session,
|
||||||
browser_profile=profile,
|
|
||||||
browser_context=context,
|
|
||||||
initial_actions=initial_actions,
|
initial_actions=initial_actions,
|
||||||
task=f"Navigate to the login page, and collect the OAuth provider buttons and their login URLs. Ignore Passkey.",
|
task=f"Navigate to the login page, and collect the OAuth provider buttons and their login URLs. Ignore Passkey.",
|
||||||
llm=create_llm_with_retry(),
|
llm=CreateChatGoogleGenerativeAI(
|
||||||
planner_llm=create_planner_llm_with_retry(),
|
os.getenv("GOOGLE_MODEL") or "fallback"
|
||||||
|
),
|
||||||
|
planner_llm=CreateChatGoogleGenerativeAI(
|
||||||
|
os.getenv("GOOGLE_PLANNER_MODEL") or "fallback"
|
||||||
|
),
|
||||||
controller=controller,
|
controller=controller,
|
||||||
extend_planner_system_message=extend_planner_system_message,
|
extend_planner_system_message=extend_planner_system_message,
|
||||||
retry_delay=180, # 재시도 간격을 3분으로 증가
|
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ Agent 생성 실패: {e}")
|
print(f"⚠️ Agent 생성 실패: {e}")
|
||||||
|
|
@ -206,7 +187,7 @@ async def scan_one_url(url: str, skip_html_check: bool = False):
|
||||||
if "ResourceExhausted" in str(e) or "429" in str(e):
|
if "ResourceExhausted" in str(e) or "429" in str(e):
|
||||||
print("⚠️ API 쿼터 문제로 인한 Agent 생성 실패. 5분 대기 후 재시도...")
|
print("⚠️ API 쿼터 문제로 인한 Agent 생성 실패. 5분 대기 후 재시도...")
|
||||||
await asyncio.sleep(300)
|
await asyncio.sleep(300)
|
||||||
await clean_resources(None, session, browser, playwright)
|
await clean_resources(agent=None, session=session)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -249,14 +230,13 @@ async def scan_one_url(url: str, skip_html_check: bool = False):
|
||||||
# 실제 데이터 저장
|
# 실제 데이터 저장
|
||||||
for entry in oauth_entries:
|
for entry in oauth_entries:
|
||||||
writer.writerow([url, entry.provider, entry.oauth_uri])
|
writer.writerow([url, entry.provider, entry.oauth_uri])
|
||||||
|
await clean_resources(agent, session)
|
||||||
await clean_resources(agent, session, browser, playwright)
|
|
||||||
|
|
||||||
# 성공적으로 처리했으므로 반복문 탈출
|
# 성공적으로 처리했으므로 반복문 탈출
|
||||||
break
|
break
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await clean_resources(agent, session, browser, playwright)
|
await clean_resources(agent, session)
|
||||||
|
|
||||||
# API 쿼터 문제인지 확인
|
# API 쿼터 문제인지 확인
|
||||||
if "ResourceExhausted" in str(e) or "429" in str(e):
|
if "ResourceExhausted" in str(e) or "429" in str(e):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue