在使用 Browser-Use 进行网页自动化时,很多网站需要登录才能访问完整内容。本文档详细介绍如何在云浏览器模式下处理各种登录场景。
| 方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 手动登录 | 扫码、验证码、复杂登录 | 最灵活,成功率高 | 需要人工介入 |
| Cookie复用 | 频繁使用同一账号 | 快速,无需重复登录 | Cookie会过期 |
| 自动化登录 | 简单账号密码登录 | 完全自动化 | 容易被反爬虫检测 |
wait_for_user_action 暂停自动化import asyncio
from dotenv import load_dotenv
from agent.tools.builtin.baseClass import (
init_browser_session,
cleanup_browser_session,
navigate_to_url,
wait,
wait_for_user_action,
evaluate,
)
load_dotenv()
async def manual_login_example():
"""
手动登录示例 - 适用于所有登录场景
"""
try:
# 步骤 1: 初始化云浏览器(非无头模式)
print("🌐 启动云浏览器...")
browser, tools = await init_browser_session(
headless=False, # 关键:设置为 False
use_cloud=True,
)
print("✅ 云浏览器已启动")
print("📝 提示: 查找日志中的 '🔗 Live URL',在浏览器中打开该链接")
# 步骤 2: 导航到目标网站
print("\n📍 导航到小红书...")
await navigate_to_url("https://www.xiaohongshu.com")
await wait(3)
# 步骤 3: 检查登录状态(可选)
print("\n🔍 检查登录状态...")
check_login_js = """
(function() {
// 检查是否有用户头像或用户名
const userAvatar = document.querySelector('[class*="avatar"]');
const userName = document.querySelector('[class*="username"]');
const loginBtn = document.querySelector('[class*="login"]');
return {
isLoggedIn: !!(userAvatar || userName),
hasLoginBtn: !!loginBtn
};
})()
"""
status = await evaluate(check_login_js)
print(f" 登录状态: {status.output}")
# 步骤 4: 等待用户手动登录
print("\n👤 等待用户登录...")
print("=" * 60)
print("请按以下步骤操作:")
print("1. 在日志中找到 '🔗 Live URL'")
print("2. 复制该 URL 并在浏览器中打开")
print("3. 在 Live URL 页面中完成登录(扫码或账号密码)")
print("4. 登录成功后,回到这里按 Enter 继续")
print("=" * 60)
await wait_for_user_action(
message="请在云浏览器中完成登录,完成后按 Enter 继续",
timeout=300 # 5 分钟超时
)
print("\n✅ 用户已确认登录完成")
# 步骤 5: 验证登录状态
print("\n🔍 验证登录状态...")
status = await evaluate(check_login_js)
print(f" 登录状态: {status.output}")
# 步骤 6: 继续后续操作
print("\n🎯 开始执行后续任务...")
# 这里可以继续你的自动化任务
# 例如:搜索、爬取数据等
print("\n✅ 任务完成")
except Exception as e:
print(f"❌ 错误: {str(e)}")
finally:
await cleanup_browser_session()
if __name__ == "__main__":
asyncio.run(manual_login_example())
https://live.browser-use.com?wss=...import asyncio
import json
from pathlib import Path
from dotenv import load_dotenv
from agent.tools.builtin.baseClass import (
init_browser_session,
cleanup_browser_session,
navigate_to_url,
wait,
wait_for_user_action,
evaluate,
)
load_dotenv()
async def save_cookies_after_login():
"""
首次登录并保存 Cookie
"""
try:
# 初始化浏览器
browser, tools = await init_browser_session(
headless=False,
use_cloud=True,
)
print("✅ 云浏览器已启动")
# 导航到网站
await navigate_to_url("https://www.xiaohongshu.com")
await wait(3)
# 等待用户登录
print("\n👤 请在 Live URL 中完成登录...")
await wait_for_user_action(
message="登录完成后按 Enter 继续",
timeout=300
)
# 获取 Cookie
print("\n💾 保存 Cookie...")
get_cookies_js = """
(function() {
return document.cookie;
})()
"""
cookies_result = await evaluate(get_cookies_js)
cookies_str = cookies_result.output
# 解析 Cookie 字符串为列表
cookies = []
for cookie_str in cookies_str.split('; '):
if '=' in cookie_str:
name, value = cookie_str.split('=', 1)
cookies.append({
"name": name,
"value": value,
"domain": ".xiaohongshu.com",
"path": "/",
})
# 保存到文件
cookie_file = Path("cookies_xhs.json")
with open(cookie_file, "w", encoding="utf-8") as f:
json.dump(cookies, f, ensure_ascii=False, indent=2)
print(f"✅ Cookie 已保存到: {cookie_file}")
print(f" 共 {len(cookies)} 个 Cookie")
except Exception as e:
print(f"❌ 错误: {str(e)}")
finally:
await cleanup_browser_session()
if __name__ == "__main__":
asyncio.run(save_cookies_after_login())
import asyncio
import json
from pathlib import Path
from dotenv import load_dotenv
from browser_use import BrowserProfile
from agent.tools.builtin.baseClass import (
init_browser_session,
cleanup_browser_session,
navigate_to_url,
wait,
evaluate,
)
load_dotenv()
async def use_saved_cookies():
"""
使用保存的 Cookie 跳过登录
"""
try:
# 读取保存的 Cookie
cookie_file = Path("cookies_xhs.json")
if not cookie_file.exists():
print("❌ Cookie 文件不存在,请先运行 save_cookies_after_login()")
return
with open(cookie_file, "r", encoding="utf-8") as f:
cookies = json.load(f)
print(f"✅ 加载了 {len(cookies)} 个 Cookie")
# 创建 BrowserProfile 并预设 Cookie
profile = BrowserProfile(
cookies=cookies,
user_agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
)
# 初始化浏览器(使用 profile)
browser, tools = await init_browser_session(
headless=True, # 可以使用无头模式
use_cloud=True,
browser_profile=profile, # 传入 profile
)
print("✅ 云浏览器已启动(带 Cookie)")
# 直接访问需要登录的页面
print("\n📍 访问小红书(应该已登录)...")
await navigate_to_url("https://www.xiaohongshu.com")
await wait(3)
# 验证登录状态
print("\n🔍 验证登录状态...")
check_login_js = """
(function() {
const userAvatar = document.querySelector('[class*="avatar"]');
const userName = document.querySelector('[class*="username"]');
return {
isLoggedIn: !!(userAvatar || userName)
};
})()
"""
status = await evaluate(check_login_js)
print(f" 登录状态: {status.output}")
# 继续后续操作
print("\n🎯 开始执行任务...")
# 你的自动化任务...
print("\n✅ 任务完成")
except Exception as e:
print(f"❌ 错误: {str(e)}")
finally:
await cleanup_browser_session()
if __name__ == "__main__":
asyncio.run(use_saved_cookies())
import asyncio
from dotenv import load_dotenv
from agent.tools.builtin.baseClass import (
init_browser_session,
cleanup_browser_session,
navigate_to_url,
wait,
get_selector_map,
input_text,
click_element,
evaluate,
)
load_dotenv()
async def automated_login_example():
"""
自动化登录示例(仅适用于简单场景)
"""
try:
# 初始化浏览器
browser, tools = await init_browser_session(
headless=True,
use_cloud=True,
)
print("✅ 云浏览器已启动")
# 导航到登录页面
print("\n📍 导航到登录页面...")
await navigate_to_url("https://example.com/login")
await wait(2)
# 获取页面元素
print("\n🎯 获取页面元素...")
selector_result = await get_selector_map()
print(f" 找到 {selector_result.long_term_memory}")
# 注意:需要根据实际页面找到正确的元素索引
# 这里假设:
# - 索引 0 是用户名输入框
# - 索引 1 是密码输入框
# - 索引 2 是登录按钮
# 输入用户名
print("\n📝 输入用户名...")
await input_text(index=0, text="your_username", clear=True)
await wait(1)
# 输入密码
print("\n🔑 输入密码...")
await input_text(index=1, text="your_password", clear=True)
await wait(1)
# 点击登录按钮
print("\n🖱️ 点击登录按钮...")
await click_element(index=2)
await wait(3)
# 验证登录状态
print("\n🔍 验证登录状态...")
check_login_js = """
(function() {
// 检查是否跳转到首页或有用户信息
const currentUrl = window.location.href;
const userInfo = document.querySelector('[class*="user"]');
return {
currentUrl: currentUrl,
isLoggedIn: !!userInfo
};
})()
"""
status = await evaluate(check_login_js)
print(f" 登录状态: {status.output}")
print("\n✅ 登录完成")
except Exception as e:
print(f"❌ 错误: {str(e)}")
finally:
await cleanup_browser_session()
if __name__ == "__main__":
asyncio.run(automated_login_example())
⚠️ 警告: 自动化登录容易被检测,可能导致:
建议: 优先使用手动登录或 Cookie 复用。
这是一个完整的实战示例,展示了如何处理小红书的登录并进行搜索。
# 完整代码见 examples/cloud_browser_example.py 中的 example_6_xhs_search_save()
执行流程:
运行方式:
python examples/cloud_browser_example.py --example 6
// 方法 1: 检查用户相关元素
(function() {
const userAvatar = document.querySelector('[class*="avatar"]');
const userName = document.querySelector('[class*="username"]');
const userMenu = document.querySelector('[class*="user-menu"]');
const loginBtn = document.querySelector('[class*="login"]');
return {
isLoggedIn: !!(userAvatar || userName || userMenu),
hasLoginBtn: !!loginBtn
};
})()
// 方法 2: 检查 Cookie
(function() {
const cookies = document.cookie;
const hasSessionCookie = cookies.includes('session') ||
cookies.includes('token') ||
cookies.includes('auth');
return {
hasCookie: hasSessionCookie,
cookieCount: cookies.split(';').length
};
})()
// 方法 3: 检查 LocalStorage
(function() {
const hasToken = !!localStorage.getItem('token') ||
!!localStorage.getItem('user') ||
!!localStorage.getItem('auth');
return {
hasLocalStorageAuth: hasToken
};
})()
不同网站的登录状态检测方式不同,需要根据实际情况调整:
# 小红书
check_login_js = """
(function() {
const userAvatar = document.querySelector('.user-avatar');
return { isLoggedIn: !!userAvatar };
})()
"""
# 知乎
check_login_js = """
(function() {
const userLink = document.querySelector('.AppHeader-userInfo');
return { isLoggedIn: !!userLink };
})()
"""
# 微博
check_login_js = """
(function() {
const userName = document.querySelector('.gn_name');
return { isLoggedIn: !!userName };
})()
"""
{
"website": "xiaohongshu.com",
"saved_at": "2026-01-30T10:00:00",
"expires_at": "2026-02-30T10:00:00",
"cookies": [
{
"name": "session_id",
"value": "abc123...",
"domain": ".xiaohongshu.com",
"path": "/",
"secure": true,
"httpOnly": true
}
]
}
import json
from pathlib import Path
from datetime import datetime, timedelta
from typing import List, Dict, Optional
class CookieManager:
"""Cookie 管理器"""
def __init__(self, storage_dir: str = "cookies"):
self.storage_dir = Path(storage_dir)
self.storage_dir.mkdir(parents=True, exist_ok=True)
def save_cookies(
self,
website: str,
cookies: List[Dict],
expires_days: int = 30
):
"""保存 Cookie"""
cookie_file = self.storage_dir / f"{website}.json"
data = {
"website": website,
"saved_at": datetime.now().isoformat(),
"expires_at": (datetime.now() + timedelta(days=expires_days)).isoformat(),
"cookies": cookies
}
with open(cookie_file, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f"✅ Cookie 已保存: {cookie_file}")
def load_cookies(self, website: str) -> Optional[List[Dict]]:
"""加载 Cookie"""
cookie_file = self.storage_dir / f"{website}.json"
if not cookie_file.exists():
print(f"❌ Cookie 文件不存在: {cookie_file}")
return None
with open(cookie_file, "r", encoding="utf-8") as f:
data = json.load(f)
# 检查是否过期
expires_at = datetime.fromisoformat(data["expires_at"])
if datetime.now() > expires_at:
print(f"⚠️ Cookie 已过期: {cookie_file}")
return None
print(f"✅ Cookie 已加载: {len(data['cookies'])} 个")
return data["cookies"]
def is_valid(self, website: str) -> bool:
"""检查 Cookie 是否有效"""
cookies = self.load_cookies(website)
return cookies is not None
# 使用示例
cookie_manager = CookieManager()
# 保存 Cookie
cookie_manager.save_cookies(
website="xiaohongshu",
cookies=[...],
expires_days=30
)
# 加载 Cookie
cookies = cookie_manager.load_cookies("xiaohongshu")
if cookies:
# 使用 Cookie
profile = BrowserProfile(cookies=cookies)
async def auto_refresh_cookies(website: str, cookie_manager: CookieManager):
"""自动刷新 Cookie"""
# 检查 Cookie 是否有效
if cookie_manager.is_valid(website):
print("✅ Cookie 有效,直接使用")
cookies = cookie_manager.load_cookies(website)
return cookies
# Cookie 无效,重新登录
print("⚠️ Cookie 无效,需要重新登录")
# 启动浏览器并等待用户登录
browser, tools = await init_browser_session(
headless=False,
use_cloud=True,
)
await navigate_to_url(f"https://www.{website}.com")
await wait(3)
await wait_for_user_action(
message="请完成登录,然后按 Enter",
timeout=300
)
# 获取新的 Cookie
get_cookies_js = "(function() { return document.cookie; })()"
cookies_result = await evaluate(get_cookies_js)
# 解析并保存
cookies = parse_cookies(cookies_result.output, website)
cookie_manager.save_cookies(website, cookies)
await cleanup_browser_session()
return cookies
A: 云浏览器启动时会在日志中输出,格式如下:
INFO [cloud] 🔗 Live URL: https://live.browser-use.com?wss=https%3A%2F%2F...
复制这个 URL 并在浏览器中打开即可。
A: 可能的原因:
A: 不同网站的 Cookie 过期时间不同:
A: 验证码必须手动处理:
wait_for_user_action 暂停A: 可以,但需要:
A:
cleanup_browser_session()# ❌ 不要硬编码密码
password = "my_password"
# ✅ 使用环境变量
import os
password = os.getenv("MY_PASSWORD")
# ✅ 使用配置文件(不提交到 Git)
import json
with open("config.json") as f:
config = json.load(f)
password = config["password"]
# .gitignore 中添加
cookies/
*.cookies.json
config.json
.env
from browser_use.browser.profile import ProxySettings
proxy = ProxySettings(
server="http://proxy.example.com:8080",
username="user",
password="pass"
)
profile = BrowserProfile(proxy=proxy)
import time
# 避免频繁登录
last_login_time = 0
MIN_LOGIN_INTERVAL = 3600 # 1小时
def should_login():
global last_login_time
current_time = time.time()
if current_time - last_login_time < MIN_LOGIN_INTERVAL:
return False
last_login_time = current_time
return True
需要登录?
├─ 是
│ ├─ 有保存的 Cookie?
│ │ ├─ 是 → 使用 Cookie 复用(方式2)
│ │ └─ 否 → 继续
│ ├─ 是扫码/验证码登录?
│ │ ├─ 是 → 使用手动登录(方式1)
│ │ └─ 否 → 继续
│ └─ 是简单账号密码?
│ ├─ 是 → 可尝试自动化登录(方式3)
│ └─ 否 → 使用手动登录(方式1)
└─ 否 → 直接访问
更新时间: 2026-01-30 相关文档: CLOUD_BROWSER_GUIDE.md