LangGraph + Scrapeless:将直播网络工具整合到您的代理图中
Expert in Web Scraping Technologies
TL;DR:
- LangGraph通过
langchain-mcp-adapters加载Scrapeless MCP服务器的工具,并将所有21个工具交给一个代理图,从scrape_markdown到完整的浏览器集。 MultiServerMCPClient.get_tools执行握手并返回工具;加载它们或直接调用其中一个不需要模型提供者密钥。langchain-mcp-adapters将每个工具结果返回为内容块的列表,因此您需要读取result[0]["text"]而不是将列表转换为字符串。- 代理本身是通过
from langchain.agents import create_agent构建的,这是被弃用的create_react_agent的当前替代品。 - 只有
create_agent图及其ainvoke运行需要模型密钥;加载和调用工具不需要。 - 从Scrapeless免费计划开始,并为您的图提供真实的网络工具。
LangGraph将代理构建为图:一个在模型和其工具之间循环的状态机,直到任务完成。该设计的有效性仅取决于图中工具的实用性,裸LangGraph代理没有能够连接到实时网络的工具。模型上下文协议填补了这个空白。将LangGraph的MCP适配器指向一个服务器,它所暴露的每个工具都变成了您的图可以调用的LangChain工具。
本指南将LangGraph连接到Scrapeless MCP服务器,加载其21个工具,实际调用其中一个,并明确指出模型提供者密钥变得必要的地方。工具加载和直接调用经过实时服务器验证;生成步骤被标记为它所需的唯一先决条件。
为什么选择Scrapeless MCP
Scrapeless MCP服务器提供了一个代理可以直接调用的网络抓取和浏览器工具,因此抓取层不是您自己构建或托管的。一个连接提供21个工具:用于内容的scrape_markdown和scrape_html,用于搜索数据的google_search和google_trends,用于捕获的scrape_screenshot,以及完整的browser_*集来驱动云浏览器。LangGraph通过langchain-mcp-adapters已经拥有一个强大的MCP故事,这将这些工具转变为标准的LangChain工具,且无需粘合代码。
browser_*工具驱动Scrapeless云浏览器,因此代理可以在Scrapeless基础设施上导航交互页面并读取渲染内容,而非在本地浏览器池。如果您使用的是普通的LangChain而不是LangGraph,LangChain + Scrapeless MCP文章从那个角度涵盖同一个服务器。
先决条件
- Python 3.10或更高版本。
- 从仪表板获取的Scrapeless API密钥,导出为
SCRAPELESS_API_KEY。 - 仅用于代理运行的模型提供者密钥(例如
OPENAI_API_KEY)。加载和调用工具不需要一个。
安装
安装LangGraph、LangChain和MCP适配器。
bash
pip install langgraph langchain langchain-mcp-adapters
在终端中设置您的Scrapeless密钥。运行时使用真实密钥,并确保源代码中没有占位符。
bash
export SCRAPELESS_API_KEY="sk_your_key_here"
加载工具
MultiServerMCPClient接受服务器名称到连接配置的映射。每个配置命名传输、URL和头;Scrapeless密钥放在x-api-token头中。get_tools执行握手并将工具作为LangChain工具返回。
python
import asyncio
import os
from langchain_mcp_adapters.client import MultiServerMCPClient
client = MultiServerMCPClient(
{
"scrapeless": {
"url": "https://api.scrapeless.com/mcp",
"transport": "streamable_http",
"headers": {"x-api-token": os.environ["SCRAPELESS_API_KEY"]},
}
}
)
async def main() -> None:
tools = await client.get_tools()
names = sorted(t.name for t in tools)
print("工具数量:", len(names))
print("工具:", ", ".join(names))
asyncio.run(main())
实时服务器返回21个工具,仅设置Scrapeless密钥即可加载。
text
工具数量: 21
工具: browser_click, browser_close, browser_create, browser_get_html, browser_get_text, browser_go_back, browser_go_forward, browser_goto, browser_press_key, browser_screenshot, browser_scroll, browser_scroll_to, browser_snapshot, browser_type, browser_wait, browser_wait_for, google_search, google_trends, scrape_html, scrape_markdown, scrape_screenshot
客户被称为MultiServerMCPClient,因为它可以同时联合多个MCP服务器;此处它持有一台服务器,添加另一台只是映射中的另一条目,而不是对代理的更改。传输和消息层遵循模型上下文协议规范,该协议基于JSON-RPC 2.0规范。
调用工具
在将工具连接到图形之前,手动调用工具。每个加载的工具都是一个具有ainvoke方法的LangChain工具,因此您可以传递参数并读取结果。有一个细节很重要:适配器返回的是内容块的列表,而不是普通字符串,因此请从第一个块中获取文本。
python
import asyncio
import os
from langchain_mcp_adapters.client import MultiServerMCPClient
client = MultiServerMCPClient(
{
"scrapeless": {
"url": "https://api.scrapeless.com/mcp",
"transport": "streamable_http",
"headers": {"x-api-token": os.environ["SCRAPELESS_API_KEY"]},
}
}
)
async def main() -> None:
tools = await client.get_tools()
scrape_markdown = next(t for t in tools if t.name == "scrape_markdown")
result = await scrape_markdown.ainvoke({"url": "https://quotes.toscrape.com/"})
# langchain-mcp-adapters 返回的是内容块的列表;提取文本块
text = result[0]["text"] if isinstance(result, list) and result else str(result)
print("markdown 字符数:", len(text))
print("包含引语:", "我们所创造的世界" in text)
asyncio.run(main())
调用返回页面的Markdown,内容检查确认存在真实的引言。
text
markdown 字符数: 4308
包含引语: True
读取result[0]["text"]是初级代码出错的地方:将整个列表字符串化将给您一个带转义序列的Python repr,而不是干净的Markdown。LangChain MCP适配器指南完整记录了客户端和结果形状。
构建代理图
工具加载后,代理只需一次调用。create_agent构建一个ReAct风格的图形,该图形在模型和工具之间循环,并且它是被弃用的create_react_agent的当前替代品。这一步需要一个模型提供者密钥:图形运行模型,而模型决定何时调用scrape_markdown或任何其他工具。
注:构建和运行图形需要一个模型提供者密钥,例如
OPENAI_API_KEY,这里并未设置。加载21个工具和直接调用scrape_markdown不需要密钥。此模块以其确切形状显示;只有模型的往返是一个先决条件。
python
from langchain.agents import create_agent
async def run_graph(tools) -> None:
agent = create_agent("openai:gpt-4o", tools)
result = await agent.ainvoke(
{"messages": [{"role": "user", "content": "用scrape_markdown获取https://quotes.toscrape.com/,并列出前三个引言及其作者。"}]}
)
print(result["messages"][-1].content)
在运行时,图形将提示传递给模型,模型使用URL调用scrape_markdown,工具返回直接调用已演示的Markdown,模型写出答案。无论是模型调用工具还是您调用工具,都是相同的对象。
结论
LangGraph加上Scrapeless MCP服务器是从一个简单图形到读取实时网络的快捷方式。MultiServerMCPClient加载21个工具,ainvoke证明一个工具有效,并显示如何读取其内容块,而create_agent将工具转化为运行中的图形。只有最后一步需要模型密钥,因此您可以先加载并测试整个工具表面。从上面的脚本开始,限制工具的范围到图形所需的内容,让模型驱动。
创建一个免费的Scrapeless账户以获取API密钥,并在计划持续代理时查看Scrapeless定价。
常见问题
问:LangGraph需要模型密钥来加载MCP工具吗?
不需要。MultiServerMCPClient.get_tools执行握手并返回工具,只需设置Scrapeless API密钥,每个工具可以直接通过ainvoke调用。只有在使用create_agent构建和运行代理图时,才需要模型提供者密钥,因为那时模型本身决定调用哪些工具。
问:为什么工具结果作为列表返回而不是字符串?
langchain-mcp-adapters 将每个 MCP 工具的结果作为内容块的列表返回,这就是 MCP 表示工具输出的方式。使用 result[0]["text"] 从第一个块读取文本;将整个列表转换为字符串会给你一个带有转义序列的 repr,而不是干净的内容。
问:我应该使用 create_react_agent 还是 create_agent?
使用 langchain.agents 中的 create_agent。create_react_agent 在 LangGraph 1.0 中被移出了 langgraph.prebuilt,现在会发出弃用警告,因此当前无警告的路径是 from langchain.agents import create_agent,并使用相同的模型和工具参数。
问:如果我只有一个服务器,MultiServerMCPClient 有什么用?
该客户端旨在一次联合多个 MCP 服务器,但它也可以配合单个服务器作为一个条目的映射。现在使用它意味着将来添加第二个服务器只需在配置中增加一个条目,而不会改变代理使用工具的方式。
问:我如何只给图形提供一些工具?
get_tools 返回一个列表,因此在传递给 create_agent 之前对其进行过滤。仅向图形提供 scrape_markdown 和 google_search 比提供完整的 21 个工具集更安全,尤其是在任务只需要内容和搜索时。
问:通过工具抓取是否受目标规则的约束?
是的。这些工具获取公共页面,您仍然有责任遵守每个目标的条款及其 机器人排除协议 指令。保持抓取量适度并确保数据公共,限制图形中工具的范围到任务实际需要的工具。
在Scrapeless,我们仅访问公开可用的数据,并严格遵循适用的法律、法规和网站隐私政策。本博客中的内容仅供演示之用,不涉及任何非法或侵权活动。我们对使用本博客或第三方链接中的信息不做任何保证,并免除所有责任。在进行任何抓取活动之前,请咨询您的法律顾问,并审查目标网站的服务条款或获取必要的许可。



