Merge pull request #39 from j93es/feat/some

Browser Use Proxy 미사용 문제 해결
This commit is contained in:
gyuu04 2025-07-13 15:52:27 +09:00 committed by GitHub
commit 20578d7f7b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 179 additions and 46 deletions

146
setup.py
View file

@ -6,21 +6,27 @@ from browser_use import BrowserProfile, Agent
from browser_use.llm import ChatGoogle
from dotenv import load_dotenv
import threading
load_dotenv(verbose=True, override=True)
os.makedirs(os.path.dirname("./data"), exist_ok=True)
def create_file_from_example(target: str, example: str) -> bool:
if not os.path.exists(target):
if os.path.exists(example):
with open(example, 'r', encoding='utf-8') as example_file, \
open(target, 'w', encoding='utf-8') as target_file:
with (
open(example, "r", encoding="utf-8") as example_file,
open(target, "w", encoding="utf-8") as target_file,
):
target_file.write(example_file.read())
#os.startfile(target)
# os.startfile(target)
print(f"{target} 파일이 {example}에서 생성되었습니다.")
return True
else:
print(f"⚠️ {example} 파일이 존재하지 않습니다. {target} 생성에 실패했습니다.")
print(
f"⚠️ {example} 파일이 존재하지 않습니다. {target} 생성에 실패했습니다."
)
else:
print(f" {target} 파일이 이미 존재합니다.")
return False
@ -30,7 +36,7 @@ def install_playwright_chrome():
print("\n🛠️ Playwright의 Chromium을 설치 중입니다...")
print("👉 이 작업은 시간이 걸릴 수 있습니다. 잠시 기다려주세요.")
try:
subprocess.run(['uv', 'run', 'playwright', 'install', 'chromium'], check=True)
subprocess.run(["uv", "run", "playwright", "install", "chromium"], check=True)
print("✅ Playwright Chrome 설치 완료.")
except subprocess.CalledProcessError as e:
if "already" in e.stdout.decode():
@ -42,23 +48,28 @@ def install_playwright_chrome():
def prompt_yes_no(message: str) -> bool:
print(message, end="")
return input().strip().lower() in ['y', 'yes']
return input().strip().lower() in ["y", "yes"]
def i_dont_like_windows():
# Windows인지 확인
if os.name != 'nt':
if os.name != "nt":
return
else:
# run (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage").ACP
try:
result = subprocess.run(
['powershell', '-Command', '(Get-ItemProperty "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage").ACP'],
[
"powershell",
"-Command",
'(Get-ItemProperty "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage").ACP',
],
capture_output=True,
text=True,
check=True
check=True,
)
acp = result.stdout.strip()
if acp == '65001':
if acp == "65001":
print("현재 Active Code Page가 UTF-8로 설정되어 있습니다.")
return
else:
@ -68,12 +79,14 @@ def i_dont_like_windows():
print("=======================================================")
print("\n⚠️ Windows에서는 인코딩 문제가 발생합니다.")
print("👉 엔터를 누르면 자동으로 intl.cpl이 열립니다.")
print("👉 자세한 내용은 README.md에서 \"윈도우 인코딩 해결\"을 참조해주세요.\n")
print("⚠️ 경고 : 이 작업은 윈도우에서 킹갓 대한민국의 프로그램들의 한글이 정상적으로 표시되지 않을 수 있습니다.")
print('👉 자세한 내용은 README.md에서 "윈도우 인코딩 해결"을 참조해주세요.\n')
print(
"⚠️ 경고 : 이 작업은 윈도우에서 킹갓 대한민국의 프로그램들의 한글이 정상적으로 표시되지 않을 수 있습니다."
)
# Pause
input("계속하려면 Enter 키를 누르세요...")
webbrowser.open('intl.cpl')
webbrowser.open("intl.cpl")
print("👉 intl.cpl가 열렸습니다.\n")
print("👉 관리자 옵션 -> 시스템 로켈 변경")
@ -82,7 +95,7 @@ def i_dont_like_windows():
print("⚠️ 이 작업은 시스템 언어 설정을 변경하므로 주의가 필요합니다.\n")
print("=======================================================")
input("계속하려면 Enter 키를 누르세요...")
async def setup_user_data():
print("\n📂 사용자 데이터 디렉토리를 설정하시겠습니까?")
@ -90,15 +103,17 @@ async def setup_user_data():
print("✅ 이 작업은 Google API Key를 설정하고 나서 진행해야만합니다.")
if prompt_yes_no("\033[1m\033[33m선택하시려면 y를 입력하세요 (y/n):\033[0m "):
if os.getenv("GOOGLE_API_KEY") is None:
print("⚠️ Google API Key가 설정되어 있지 않습니다. 먼저 Google API Key를 설정해주세요.")
print(
"⚠️ Google API Key가 설정되어 있지 않습니다. 먼저 Google API Key를 설정해주세요."
)
return
print("======================================================")
llm = ChatGoogle(
model="gemini-2.0-flash",
)
initial_actions = [
{'go_to_url': {'url': 'https://www.google.com', 'new_tab': False}},
{'wait': {'seconds': 2147483647}},
{"go_to_url": {"url": "https://www.google.com", "new_tab": False}},
{"wait": {"seconds": 2147483647}},
]
agent = Agent(
@ -108,33 +123,90 @@ async def setup_user_data():
initial_actions=initial_actions,
browser_profile=BrowserProfile(
disable_security=True,
#stealth=True,
# stealth=True,
headless=False,
device_scale_factor=1,
window_size={"width": 1600, "height": 900},
viewport={"width": 1600, "height": 900},
user_data_dir="./data/user_data",
ignore_default_args=['--enable-automation'],
)
args=[
# "--disable-features=Translate,PasswordManagerDefaultEnabled",
],
ignore_default_args=[
"--disable-datasaver-prompt",
"--disable-component-extensions-with-background-pages",
"--disable-prompt-on-repost",
"--safeBrowse-disable-auto-update",
"--install-autogenerated-theme=0,0,0",
"--disable-speech-synthesis-api",
"--ash-no-nudges",
"--test-type=gpu",
"--noerrdialogs",
"--disable-external-intent-requests",
"--disable-breakpad",
"--disable-backgrounding-occluded-windows",
"--export-tagged-pdf",
"--disable-focus-on-load",
"--suppress-message-center-popups",
"--disable-renderer-backgrounding",
"--hide-crash-restore-bubble",
"--disable-back-forward-cache",
"--allow-legacy-extension-manifests",
# "--disable-field-trial-config", # 왜 이걸 끄면 웹사이트가 압축된 형태로 보이는 진 모르곘음
"--disable-popup-blocking",
"--disable-background-networking",
"--no-first-run",
"--disable-blink-features=AutomationControlled",
"--password-store=basic",
"--enable-network-information-downlink-max",
"--allow-pre-commit-input",
"--enable-features=NetworkService,NetworkServiceInProcess",
"--metrics-recording-only",
"--silent-debugger-extension-api",
"--disable-features=AcceptCHFrame,AutoExpandDetailsElement,AvoidUnnecessaryBeforeUnloadCheckSync,CertificateTransparencyComponentUpdater,DestroyProfileOnBrowserClose,DialMediaRouteProvider,ExtensionManifestV2Disabled,GlobalMediaControls,HttpsUpgrades,ImprovedCookieControls,LazyFrameLoading,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutomationControlled,BackForwardCache,OptimizationHints,ProcessPerSiteUpToMainFrameThreshold,InterestFeedContentSuggestions,CalculateNativeWinOcclusion,HeavyAdPrivacyMitigations,PrivacySandboxSettings4,AutofillServerCommunication,CrashReporting,OverscrollHistoryNavigation,InfiniteSessionRestore,ExtensionDisableUnsupportedDeveloper",
"--disable-ipc-flooding-protection",
"--disable-hang-monitor",
"--disable-dev-shm-usage",
"--disable-client-side-phishing-detection",
"--log-level=2",
"--generate-pdf-document-outline",
"--disable-speech-api",
"--disable-search-engine-choice-screen",
"--no-service-autorun",
"--no-pings",
"--disable-component-update",
'--simulate-outdated-no-au="Tue, 31 Dec 2099 23:59:59 GMT"',
"--disable-background-timer-throttling",
"--use-mock-keychain",
"--disable-features=IsolateOrigins,site-per-process",
# 아래는 기존 예시에 있던 인자들입니다. 필요에 따라 유지하거나 제거하세요.
"--enable-automation",
"--disable-extensions",
"--hide-scrollbars",
],
),
)
print("======================================================\n")
print("👉 브라우저가 열립니다. 필요한 로그인을 완료한 후 엔터키를 눌러 다음 단계로 진행하세요.")
print(
"👉 브라우저가 열립니다. 필요한 로그인을 완료한 후 엔터키를 눌러 다음 단계로 진행하세요."
)
input("계속하려면 Enter 키를 누르세요...\n")
print("======================================================")
# 브라우저를 백그라운드에서 시작
def run_agent():
asyncio.run(agent.run())
agent_thread = threading.Thread(target=run_agent)
agent_thread.daemon = True
agent_thread.start()
# 사용자가 'n'을 입력할 때까지 대기
while True:
user_input = input("").strip().lower()
if user_input == '':
if user_input == "":
agent.stop()
break
print("======================================================")
@ -142,36 +214,44 @@ async def setup_user_data():
else:
print("🚫 설정이 취소되었습니다.")
print("======================================================")
print("⚠️ 이후에 USER_DATA_DIR을 설정하려면, .env 파일을 참고하여 USER_DATA_DIR을 설정하세요.\n")
print(
"⚠️ 이후에 USER_DATA_DIR을 설정하려면, .env 파일을 참고하여 USER_DATA_DIR을 설정하세요.\n"
)
def setup_sensitive():
print("\n🔐 Sensitive Data을 설정하시겠습니까?")
print("👉 이미 세션을 설정했다면, 이 작업은 **선택사항**입니다.")
print("⚠️ 민감 정보 파일은 오류를 유발하거나 문제가 될 수 있으므로 가급적 세션 사용을 권장합니다.")
print(
"⚠️ 민감 정보 파일은 오류를 유발하거나 문제가 될 수 있으므로 가급적 세션 사용을 권장합니다."
)
if prompt_yes_no("\033[1m\033[33m선택하시려면 y를 입력하세요 (y/n):\033[0m "):
print("======================================================")
print("👀 .sensitive.json 파일을 생성합니다.")
print("💾 Browser Use의 문서를 참조하여 수정을 수정해주세요.")
print("https://docs.browser-use.com/customize/sensitive-data")
create_file_from_example('.sensitive.json', '.sensitive.example.json')
create_file_from_example(".sensitive.json", ".sensitive.example.json")
print("======================================================")
print("✅ .sensitive.json 파일이 생성되었습니다.")
else:
print("🚫 .sensitive.json 생성이 취소되었습니다.")
print("======================================================")
print("⚠️ 이후에 민감 정보 파일을 설정하려면, .sensitive.example.json 파일을 참고하여 .sensitive.json 파일을 생성하세요.\n")
print(
"⚠️ 이후에 민감 정보 파일을 설정하려면, .sensitive.example.json 파일을 참고하여 .sensitive.json 파일을 생성하세요.\n"
)
if __name__ == "__main__":
# 1. .env 생성
create_file_from_example('.env', '.env.example')
create_file_from_example(".env", ".env.example")
print("=====================================================")
# 2. Playwright용 Chrome 설치
install_playwright_chrome()
print("=====================================================")
# 3. Windows 인코딩 문제 해결
#i_dont_like_windows()
#print("=====================================================")
# i_dont_like_windows()
# print("=====================================================")
# 4. Setup User Data
asyncio.run(setup_user_data())

View file

@ -181,7 +181,9 @@ async def _run_agent_with_retry(agent_config):
return None
# remove profile
if Profile[1]:
print(Profile)
if Profile[1] and isinstance(Profile[1], str):
print(1)
shutil.rmtree(Profile[1], ignore_errors=True)
print(f"🗑️ 임시 프로필 디렉토리 삭제 완료: {Profile[1]}")

View file

@ -13,7 +13,7 @@ async def GetProfile(headless=False):
"""브라우저 프로필을 생성하고 임시 사용자 데이터 디렉토리를 관리합니다."""
user_data_dir = None
tmp_user_data_dir = None
if USER_DATA_DIR and os.path.isdir(USER_DATA_DIR):
try:
tmp_user_data_dir = tempfile.mkdtemp(prefix="browser_use_")
@ -23,7 +23,7 @@ async def GetProfile(headless=False):
log_file = os.path.join("./data", "userdata.dump")
if not os.path.exists("./data"):
os.makedirs("./data")
# 기존 로그 파일이 있다면 해당 디렉토리 정리
if os.path.exists(log_file):
try:
@ -35,7 +35,7 @@ async def GetProfile(headless=False):
except Exception as e:
print(f"⚠️ 이전 임시 디렉토리 정리 실패: {e}")
os.remove(log_file)
# 새 임시 디렉토리 경로 로깅
with open(log_file, "w") as f:
f.write(tmp_user_data_dir)
@ -44,10 +44,10 @@ async def GetProfile(headless=False):
if os.path.exists(tmp_user_data_dir):
shutil.rmtree(tmp_user_data_dir)
shutil.copytree(
USER_DATA_DIR,
tmp_user_data_dir,
dirs_exist_ok=False,
ignore_dangling_symlinks=True
USER_DATA_DIR,
tmp_user_data_dir,
dirs_exist_ok=False,
ignore_dangling_symlinks=True,
)
user_data_dir = tmp_user_data_dir
print(f"✅ 사용자 데이터 디렉토리 복사 완료: {user_data_dir}")
@ -61,10 +61,11 @@ async def GetProfile(headless=False):
pass
tmp_user_data_dir = None
user_data_dir = None
print(proxy_url)
profile = BrowserProfile(
# Security settings
disable_security=True,
# disable_security=True,
# Display settings
headless=headless,
# Data persistence
@ -72,11 +73,61 @@ async def GetProfile(headless=False):
# Network settings
proxy={"server": proxy_url} if proxy_url else None,
# Additional arguments
args=[
"--proxy-server=" + proxy_url if proxy_url else "",
# "--disable-features=Translate,PasswordManagerDefaultEnabled",
],
ignore_default_args=[
'--enable-automation',
'--disable-extensions',
'--hide-scrollbars',
'--disable-features=AcceptCHFrame,AutoExpandDetailsElement,AvoidUnnecessaryBeforeUnloadCheckSync,CertificateTransparencyComponentUpdater,DeferRendererTasksAfterInput,DestroyProfileOnBrowserClose,DialMediaRouteProvider,ExtensionManifestV2Disabled,GlobalMediaControls,HttpsUpgrades,ImprovedCookieControls,LazyFrameLoading,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate'
# "--disable-datasaver-prompt",
# "--disable-component-extensions-with-background-pages",
# "--disable-prompt-on-repost",
# "--safeBrowse-disable-auto-update",
# "--install-autogenerated-theme=0,0,0",
# "--disable-speech-synthesis-api",
# "--ash-no-nudges",
# "--test-type=gpu",
# "--noerrdialogs",
# "--disable-external-intent-requests",
# "--disable-breakpad",
# "--disable-backgrounding-occluded-windows",
# "--export-tagged-pdf",
# "--disable-focus-on-load",
# "--suppress-message-center-popups",
# "--disable-renderer-backgrounding",
# "--hide-crash-restore-bubble",
# "--disable-back-forward-cache",
# "--allow-legacy-extension-manifests",
# # "--disable-field-trial-config", # 왜 이걸 끄면 웹사이트가 압축된 형태로 보이는 진 모르곘음
# "--disable-popup-blocking",
# "--disable-background-networking",
# "--no-first-run",
# "--disable-blink-features=AutomationControlled",
# "--password-store=basic",
# "--enable-network-information-downlink-max",
# "--allow-pre-commit-input",
# "--enable-features=NetworkService,NetworkServiceInProcess",
# "--metrics-recording-only",
# "--silent-debugger-extension-api",
# "--disable-features=AcceptCHFrame,AutoExpandDetailsElement,AvoidUnnecessaryBeforeUnloadCheckSync,CertificateTransparencyComponentUpdater,DestroyProfileOnBrowserClose,DialMediaRouteProvider,ExtensionManifestV2Disabled,GlobalMediaControls,HttpsUpgrades,ImprovedCookieControls,LazyFrameLoading,LensOverlay,MediaRouter,PaintHolding,ThirdPartyStoragePartitioning,Translate,AutomationControlled,BackForwardCache,OptimizationHints,ProcessPerSiteUpToMainFrameThreshold,InterestFeedContentSuggestions,CalculateNativeWinOcclusion,HeavyAdPrivacyMitigations,PrivacySandboxSettings4,AutofillServerCommunication,CrashReporting,OverscrollHistoryNavigation,InfiniteSessionRestore,ExtensionDisableUnsupportedDeveloper",
# "--disable-ipc-flooding-protection",
# "--disable-hang-monitor",
# "--disable-dev-shm-usage",
# "--disable-client-side-phishing-detection",
# "--log-level=2",
# "--generate-pdf-document-outline",
# "--disable-speech-api",
# "--disable-search-engine-choice-screen",
# "--no-service-autorun",
# "--no-pings",
# "--disable-component-update",
# '--simulate-outdated-no-au="Tue, 31 Dec 2099 23:59:59 GMT"',
# "--disable-background-timer-throttling",
# "--use-mock-keychain",
# "--disable-features=IsolateOrigins,site-per-process",
# 아래는 기존 예시에 있던 인자들입니다. 필요에 따라 유지하거나 제거하세요.
"--enable-automation",
"--disable-extensions",
"--hide-scrollbars",
],
)