by Rain Chu   | 8 月 8, 2025  | Agent , AI , Javascript , Python , RPA , 瀏覽器 , 程式開發 
想用 AI 控制網頁自動化,但程式碼又要精準可靠,同時享受自然語言,高效又方便?那你絕不能錯過由 Browserbase 團隊推出的 Stagehand  —— 這款專為 AI 時代設計的瀏覽器自動化框架,不僅支援 TypeScript 與 Python、可本地或雲端部署,還比 Browser‑Use 更快、更耐變動!
Stagehand 兼具控制力與智慧的 AI 瀏覽器自動化框架 
Stagehand 是以 Playwright 為核心構建的 AI-native 自動化工具,它加入了 LLM 判斷能力,結合程式精準控制與自然語言指令,令自動化腳本更穩定、更智慧也更高效
自然語言 + 程式碼混合操作 :你可以用程式寫明確動作,也能用「act(‘點擊第一個 Stagehand 元件’)」這樣類人語法完成UI操作 。 
接口完整,支援察看、執行與資料萃取 :核心三大命令 act、observe、extract,讓操作更透明、更可控  
容錯與自恢復能力 :UI 略有變動也不怕,Stagehand 的 observe + 快取策略讓腳本更具彈性 
完美整合 Playwright :所有 Playwright 腳本都能無縫升級 Stagehand,省心又高效 
 
核心玩法!TypeScript/JavaScript 快速上手範例 
// Use Playwright functions on the page object
const page = stagehand.page;
await page.goto("https://github.com/browserbase");
// Use act() to execute individual actions
await page.act("click on the stagehand repo");
// Use Computer Use agents for larger actions
const agent = stagehand.agent({
    provider: "openai",
    model: "computer-use-preview",
});
await agent.execute("Get to the latest PR");
// Use extract() to read data from the page
const { author, title } = await page.extract({
  instruction: "extract the author and title of the PR",
  schema: z.object({
    author: z.string().describe("The username of the PR author"),
    title: z.string().describe("The title of the PR"),
  }),
});  
這段程式完整示範了初始化、導航、AI 驅動操作到資料萃取的流程,不僅省事,也大幅提升開發效率。
Stagehand 與 Browser-Use 比較 
功能面 Stagehand(此文主角) Browser-Use 控制精準度 Token 級動作掌控 + 自然語言指令混合 攻擊角度偏自然語言,程式控制較弱 容錯能力 observe + 快取策略,對 DOM 變化更耐受缺少自恢復機制 雲端支援 原生整合 Browserbase,輕鬆雲端部署 需額外集成,無預設雲平台支援 語言支援 TypeScript / Python 主要依賴 Python AI 整合 天生結合 LLM,支援複雜任務拆解 依賴外部 LLM,不那麼一體化 
 
只要先學四個指令,快速上手 
指定去那一個網頁 
goto():
    # 初始化
    page = stagehand.page
    # 指定去那一個頁面
    await page.goto("https://rain.tips/")  
使用自然語言操作 
act():
    await page.act("點選確定按鈕");  
抓取數據資料 
extract():
    post = await page.extract("取得標題")  
預覽功能 
observe():
   links = await page.observe("找到頁面中的所有連結")  
實戰快速導覽 
安裝
# 用 pip
pip install stagehand python-dotenv
# 安裝playwright
python -m playwright install
# 裝 chromium 瀏覽器
python -m playwright install chromium  
建立 .env
export BROWSERBASE_API_KEY="your_browserbase_api_key"
export BROWSERBASE_PROJECT_ID="your_browserbase_project_id"
export MODEL_API_KEY="your_model_api_key"  # OpenAI, Anthropic, etc.  
建立程式碼 main.py
import asyncio
import os
from stagehand import Stagehand, StagehandConfig
from dotenv import load_dotenv
load_dotenv()
async def main():
    config = StagehandConfig(
        env="BROWSERBASE",
        api_key=os.getenv("BROWSERBASE_API_KEY"),
        project_id=os.getenv("BROWSERBASE_PROJECT_ID"),
        model_name="gpt-4o",
        model_api_key=os.getenv("MODEL_API_KEY")
    )
    
    stagehand = Stagehand(config)
    
    try:
        await stagehand.init()
        page = stagehand.page
        
        await page.goto("https://docs.stagehand.dev/")
        await page.act("click the quickstart link")
        
        result = await page.extract("extract the main heading of the page")
        
        print(f"Extracted: {result}")
        
    finally:
        await stagehand.close()
if __name__ == "__main__":
    asyncio.run(main())  
驗證與測試
若要用本地端的瀏覽器的話,可以改成下面的程式碼
import asyncio
import os
from dotenv import load_dotenv
from stagehand import StagehandConfig, Stagehand
load_dotenv()
async def main():
    # 检查API密钥是否设置
    api_key = os.getenv("OPENAI_API_KEY")
    config = StagehandConfig(
        env="LOCAL",  # 本地运行
        # AI模型配置 - 使用环境变量
        model_name="gpt-4o-mini",  # 使用更便宜的模型
        model_api_key=api_key,  # 从环境变量读取
        # 本地运行配置
        headless=False,  # 显示浏览器窗口
        verbose=3,  # 详细日志
        debug_dom=True,  # DOM调试
    )
    # 使用配置创建Stagehand实例
    stagehand = Stagehand(config)
    # 初始化Stagehand(启动浏览器会话)
    await stagehand.init()
    # 获取页面对象,用于后续的页面操作
    page = stagehand.page
    await page.goto("https://rain.tips/")
    # # 使用observe()取得文章的連結
    blog_links = await page.observe("取得文章中的所有連結)
    print(f"✅ Page link: {blog_links}")
    await page.act(blog_links[0]) 
    data_post_1 = await page.extract("取得文章的標題和內文")
    print(f"✅ 文章資訊如下: {data_post_1}")
if __name__ == "__main__":
    asyncio.run(main())
  
總結:為什麼 Stagehand 是下一代自動化框架? 
語言直覺更自然,人類可理解  
對 UI 變化具彈性、不易失效  
結合 LLM,自動拆解任務,效率提升數倍  
支援本地與雲端,開發與生產環境都得心應手  
 
Stagehand 正重新定義瀏覽器自動化,不再只是死板指令,而是一場「程式控+AI 智能」的完美結合,無論對開發者或 AI 自動化愛好者,都是一大利器。快一起駕馭它,打造更強、更智慧的自動化流程!
參考資料 
BrowserBase  
GitHub Stagehand 
Demo 
開發說明文件 
https://www.aivi.fyi/aiagents/introduce-stagehand 
 
				
					 
			
					
											
								 							 
					
															
					
					 by Rain Chu   | 3 月 6, 2024  | Javascript , NodeJS , web 
 
Web Push 是一種標準的 Web 協議,允許網站向使用者發送推播通知。這項功能可用於各種目的,例如:
提醒使用者有新的內容或更新 
提供即時通知,例如交易狀態或聊天訊息 
提高使用者參與度 
 
準備工作 
前端訂閱推播服務的 js 檔案 
前端訂閱推播服務的網頁,需要包含訂閱服務的 js 
後端紀錄使用者訂閱資訊的服務 
後端推播訊息的服務 
後端註冊訊息伺服器的程式碼 
 
建立前端網頁的訂閱表單 
這個檔案將包含安裝、激活、攔截請求和推播事件的處理器。創建一個名為sw.js的檔案,並將其放在你網站的根目錄下
// 安裝Service Worker
self.addEventListener('install', function(event) {
    console.log('Service Worker 安裝成功');
});
// Service Worker 激活
self.addEventListener('activate', function(event) {
    console.log('Service Worker 激活成功');
});
// 監聽推播事件
self.addEventListener('push', function(event) {
    var title = '推播通知';
    var options = {
        body: '這是一條推播消息。',
        icon: 'icon.png',
        badge: 'badge.png'
    };
    event.waitUntil(self.registration.showNotification(title, options));
});  
在你的網站上註冊一個Service Worker,這是實現Web推播的必要步驟。Service Worker將在背景執行,即使用戶沒有直接訪問你的網站也能接收通知。通常會把下面的 javascript 寫在首頁中,觸發訂閱的條件。
// 在主要的JavaScript檔案中
function urlBase64ToUint8Array(base64String) {
    const padding = '='.repeat((4 - base64String.length % 4) % 4);
    const base64 = (base64String + padding)
        .replace(/\-/g, '+')
        .replace(/_/g, '/');
    const rawData = window.atob(base64);
    const outputArray = new Uint8Array(rawData.length);
    for (let i = 0; i < rawData.length; ++i) {
        outputArray[i] = rawData.charCodeAt(i);
    }
    return outputArray;
}
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js').then(function(registration) {
    console.log('Service Worker 注册成功:', registration);
  }).catch(function(error) {
    console.log('Service Worker 注册失败:', error);
  });
}
navigator.serviceWorker.ready.then(function(registration) {
  if (!registration.pushManager) {
    alert('此瀏覽器不支持推播通知');
    return false;
  }
const applicationServerKey = 'your publice key';
  
// 訂閱推播
  registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: urlBase64ToUint8Array(applicationServerKey)
  }).then(function(subscription) {
    console.log('推播訂閱成功:', subscription);
    // 發送訂閱資訊到後端
    fetch('https://your_webpush_server/subscribe', {
      method: 'post',
      headers: {
        'Content-type': 'application/json'
      },
      body: JSON.stringify({
        subscription: subscription
      }),
    });
  }).catch(function(error) {
    console.log('推播訂閱失败:', error);
  });  
提供紀錄訂閱訊息的服務 
這一段的作法很多,通常用你原本伺服器中的解決方案,例如 php,asp.net,nodejs,python,GO等,我這邊為了方便,用nodejs示範下
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const app = express();
app.use(cors());
app.use(bodyParser.json());
const subscriptions = {}; // 在實際應用中,應使用資料庫儲存訂閱資訊
const webPush = require('web-push');
    // 設置你的VAPID鑰匙
    webPush.setVapidDetails(
        'mailto:[email protected] ',
      	'your publiec key',
      	'your private key'
      };
app.post('/subscribe', (req, res) => {
    const subscription = req.body;
    const key = subscription.endpoint; // 使用endpoint作為唯一鑰匙
    subscriptions[key] = subscription;
    console.log('subscripted');
    console.log(subscription);
    
    // subscription是從前端發送到後端的訂閱對象
    webPush.sendNotification(subscription.subscription, '消息內容')
        .then(result => console.log('推播成功'))
        .catch(err => console.log('推播失敗', err));
    res.status(200).json({message: '訂閱成功'});
});
app.listen(8060, () => console.log('伺服器運行在8060端口'));  
其中 sendNotification 平常應該是要放在 webpush service中的,這邊加入是用來測試使用
生成VAPID鑰匙 (自願應用伺服器身份驗證) 
大部分現代瀏覽器(如Chrome、Firefox、Edge)都支持Web推播API,但是如果你不用市面上的解決方案如 OneSignal 而是要直接與這些瀏覽器的推播服務交互的話,需要使用VAPID(自願應用伺服器身份驗證)鑰匙進行身份驗證。
生成 VAPID Key 的方法如下
npx web-push generate-vapid-keys  
記住保存生成的鑰匙。公鑰將在前端用於訂閱推播,私鑰將在後端用於發送推播。
 如果你無法使用npx(它通常隨npm自動安裝,作為npm 5.2.0及更高版本的一部分),那麼你可以通過下載最新版本的 nodejs
https://nodejs.org/ 
或是升級Node.js,或使用版本管理器如nvm(Node Version Manager)來管理不同版本的Node.js。
參考資料 
https://developer.mozilla.org/en-US/docs/Web/API/Push_API 
 
				
					 
			
					
				
															
					
					 by Rain Chu   | 4 月 13, 2023  | Javascript , 程式 
常常有需求要事後調整前台的畫面,尤其現在前端 javascript 的框架一大堆,只能事後處理,把元素的位置變來變去,我這邊舉利用 div 來代表,如何把元素變換位置,讓排版更簡單且容易些。
先準備有原來的 div
<div id="source">
  ....
</div>  
想要把原來的Div移動到目的地的div,id 訂為 dest
<div id="dest">
  ....
</div>  
JQuery 程式碼 appendTo(),把 div 移動到目的地 div 的裡面
$("#source").appendTo("#dest");  
除了 appendTo() 最常用,還整理幾個常用的寫法,放在下面
$("#source").insertBefore("#dest");
$("#source").insertAfter("#dest");
$("#source").prependTo("#dest");
$("#source").appendTo("#dest");  
參考資料
https://stackoverflow.com/questions/1279957/how-to-move-an-element-into-another-element 
 
				
					 
			
					
				
															
					
					 by Rain Chu   | 2 月 28, 2022  | Javascript , 程式 
// 發送email  
function sendEmail(title,text){
    var email = document.createElement("a");
    email.id = "sendemail";   
    email.href = "mailto:[email protected] ?subject="+title+"&body="+ text;
    email.click();
    }  
當使用者在網頁中,再連絡表單中填入資訊後,我們通常會寫入後端資料庫,並且發送通知,以方便管理者使用,但沒有資料庫的人,就需要仰賴使用者自己的電子郵件了,為了統一格式方便,我們還是提供聯絡表單,先幫忙使用者把資料正規化一下,然後在協助它們送出資訊給後端的管理者
 
				
					 
			
					
											
								 							 
					
															
					
					 by Rain Chu   | 2 月 20, 2022  | Javascript , React , 教育 , 線上學習 
有鑑於最近大家的一股腦兒的跟風 wordle 這款遊戲,讓我們不得不正視這款猜字或是猜東西的小遊戲如何讓大家瘋迷,並且也想要改善我們的拼字練功坊 ,看能不能讓它有趣一點,在這之前先說說我看到的5種 wordle 應用。
正統英文版的猜英文 Wordle 
這款已經紅到了被紐約時報重金買下來的遊戲版本,已經難到了讓我自我放棄的程度,上要知天文,下要知寶可夢,讓只會中文的我,放棄人生。
 
 
這款猜日文遊戲跟英文版本大同小異,但我愛的是它也有 OpenSource ,可以到 Github 上下載 mahjong-hand-guessing-game   ,
 
 
這款看起來是利用 opensource 去發展的中文注音版本,雖然說是香港人開發的,但很適合台灣人使用(因為學的是注音),一樣是會每天有不同的題庫來考考大家
同場加映,粵語版本的 wordle   
 
 
接下來就不僅僅只有猜字了,開始有人腦洞大開,加入了各種的民族元素,不過開始者是採用了日本麻將,為 14 張牌型,鍵盤上是各種萬、筒、條跟字,共有六次機會猜題機會,比較有趣的是它也有東北風的概念
 
 
大逃殺版本的 wordle ? 為什麼說他是大逃殺版本,因為你同時可以跟最多 99 人一起玩,在時間內,最後只會留下一個人為勝利者,也就是說你不僅只有要猜對字,還要能跟其他人競爭、跟時間賽跑,你每答對一題,就可以對其他人發動攻擊,扣除他們的生命力
 
 
				
					 
						
近期留言