发布时间:2026-02-02 22:11:35编辑:123阅读(254)
LangChain 1.0 的核心价值是让大模型自主决策是否使用工具、使用哪种工具完成任务,Playwright 工具结合 Agent 后,可实现模型自主访问网页、提取所需信息、完成任务。
代码如下:
import asyncio
from playwright.async_api import async_playwright
from langchain_ollama import ChatOllama
from langchain.agents import create_agent
from langchain.tools import tool
from langchain_core.tools import ToolException
# ====================== 1. 浏览器状态 ======================
def create_browser_state():
return {
"playwright": None,
"browser": None,
"context": None,
"page": None,
}
# ====================== 2. 初始化浏览器 ======================
async def init_browser(state: dict):
state["playwright"] = await async_playwright().start()
state["browser"] = await state["playwright"].chromium.launch(headless=False)
state["context"] = await state["browser"].new_context()
state["page"] = await state["context"].new_page()
print("✅ 异步浏览器初始化成功")
# ====================== 3. 关闭浏览器 ======================
async def close_browser(state: dict):
if state.get("browser"):
await state["browser"].close()
if state.get("playwright"):
await state["playwright"].stop()
print("❌ 异步浏览器已关闭")
# ====================== 4. LangChain Tools(函数式) ======================
def create_browser_tools(state: dict):
@tool
async def open_url(url: str) -> str:
"""打开目标 URL"""
page = state.get("page")
if not page:
raise ToolException("浏览器未初始化")
try:
await page.goto(url, wait_until="networkidle")
title = await page.title()
return f"成功打开 URL:{url},页面标题:{title}"
except Exception as e:
raise ToolException(str(e))
@tool
async def click_element(selector: str) -> str:
"""点击页面元素(CSS / XPath)"""
page = state.get("page")
if not page:
raise ToolException("浏览器未初始化")
try:
if selector.startswith("//"):
await page.wait_for_selector(f"xpath={selector}", state="visible", timeout=10000)
await page.click(f"xpath={selector}")
else:
await page.wait_for_selector(selector, state="visible", timeout=10000)
await page.click(selector)
return f"成功点击元素:{selector}"
except Exception as e:
raise ToolException(str(e))
@tool
async def input_text(selector: str, text: str) -> str:
"""输入文本"""
page = state.get("page")
if not page:
raise ToolException("浏览器未初始化")
try:
if selector.startswith("//"):
await page.fill(f"xpath={selector}", text)
else:
await page.fill(selector, text)
return f"已输入文本:{text}"
except Exception as e:
raise ToolException(str(e))
@tool
async def extract_page_text() -> str:
"""提取页面文本"""
page = state.get("page")
if not page:
raise ToolException("浏览器未初始化")
try:
text = await page.text_content("body")
cleaned = "\n".join(
line.strip() for line in text.split("\n") if line.strip()
)
return cleaned[:2000]
except Exception as e:
raise ToolException(str(e))
return [
open_url,
click_element,
input_text,
extract_page_text,
]
# ====================== 5. 初始化 Agent ======================
def init_agent(tools):
model = ChatOllama(
model="llama3.1:8b",
temperature=0,
)
system_prompt = """
你是一个网页自动化 AI Agent,只能使用提供的工具完成任务:
1. 先打开 URL
2. 再执行点击 / 输入
3. 必要时提取页面文本
4. 不允许编造操作
"""
return create_agent(
model=model,
tools=tools,
system_prompt=system_prompt,
# debug=True,
)
# ====================== 6. 主入口 ======================
async def main():
state = create_browser_state()
await init_browser(state)
tools = create_browser_tools(state)
agent = init_agent(tools)
try:
task = "打开 https://www.py3study.com 返回标题"
print("🚀 开始执行任务")
result = await agent.ainvoke(
{"messages": [{"role": "user", "content": task}]}
)
print("\n🎯 执行结果:\n", result['messages'][-1].content)
finally:
await close_browser(state)
# ====================== 7. 程序入口 ======================
if __name__ == "__main__":
asyncio.run(main())运行结果:
✅ 异步浏览器初始化成功
🚀 开始执行任务
🎯 执行结果:
页面标题为:Run博客 - 首页 - python3学习
❌ 异步浏览器已关闭
52131
52011
42220
39064
33575
30532
29173
24188
24091
22428
218°
245°
254°
241°
266°
255°
284°
283°
287°
293°