Bayut MCP服务器
生产准备就绪 模型上下文协议(MCP) 暴露的服务器 Bayut.com 属性搜索功能是LLM代理和n8n等工作流自动化平台的智能工具。
🎯 概述
该MCP服务器将自然语言查询转换为阿联酋领先的房地产平台Bayut上的结构化房产搜索。非常适合构建人工智能驱动的房地产经纪人、聊天机器人或自动化的房产搜索工作流程。
主要特点
- 🔍 智能搜索:使用自然语言或结构化过滤器按位置、价格、卧室搜索房产
- 📊 详细列表:获取全面的物业详细信息,包括设施、图片和代理联系人
- 🧠 NLP解析器:将自然语言查询转换为 *“JBR 2间卧室,2M以下”* 进入搜索参数
- ⚡ 异步优先:基于async/await模式构建,实现最佳性能
- 🔒 类型安全:对输入和输出进行完整的Pydantic验证
- 📝 综合录井:调试和监控的详细日志记录
- 🔄 错误处理:强大的重试逻辑和优雅的降级
📦 安装
先决条件
- Python 3.10或更高版本
- Playwright浏览器(自动安装)
设置
- 克隆存储库
git clone
cd MCP-Bayut-Crawler- 创建虚拟环境
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate- 安装依赖项
pip install -r requirements.txt- 安装Playwright浏览器
playwright install chromium- 配置环境
cp .env.example .env
# Edit .env with your preferred settings🚀 用法
启动服务器
基本启动:
python main.py使用调试日志记录:
DEBUG=true python main.py无头模式(用于生产):
BAYUT_HEADLESS=true python main.pyMCP工具
服务器提供了三个强大的工具:
1. search_bayut_listings
使用过滤器搜索Bayut属性。
输入:
{
"location": "downtown-dubai",
"purpose": "sale",
"beds": "2",
"price_min": 1500000,
"price_max": 2500000,
"max_pages": 3
}输出:
{
"status": "success",
"count": 28,
"listings": [
{
"id": "listing_123456",
"title": "Modern 2BR Apartment",
"price": 1800000,
"location": "Downtown Dubai",
"beds": 2,
"baths": 2,
"area": 1200,
"agent": "John Doe",
"brokerage": "Real Estate Co",
"url": "https://www.bayut.com/property/details/123456/",
"image_url": "https://..."
}
],
"query_used": {
"url": "https://www.bayut.com/for-sale/2-bedroom-property/dubai/downtown-dubai/?price_min=1500000&price_max=2500000",
"timestamp": "2025-11-15T10:30:00Z"
}
}2. get_listing_details
获取特定列表的全面详细信息。
输入:
{
"listing_id": "listing_123456"
}输出:
{
"status": "success",
"listing": {
"id": "listing_123456",
"title": "Modern 2BR Apartment",
"price": 1800000,
"description": "Spacious modern apartment with...",
"amenities": ["Pool", "Gym", "Parking", "Security"],
"images": ["https://...", "https://..."],
"breadcrumb": {
"country": "UAE",
"city": "Dubai",
"area": "Downtown Dubai",
"building": "Downtown Views"
},
"agent": {
"name": "John Doe",
"phone": "+971...",
"brokerage": "Real Estate Co"
}
}
}3. parse_natural_language_query
将自然语言转换为结构化搜索参数。
输入:
{
"query": "i want a 2 bedroom with 2m dhs budget in jbr"
}输出:
{
"status": "success",
"parsed": {
"beds": "2",
"price_max": 2000000,
"location": "jumeirah-beach-residence",
"purpose": "sale",
"confidence": 0.92
},
"raw_query": "i want a 2 bedroom with 2m dhs budget in jbr"
}🔗 集成示例
n8n工作流
步骤1:添加执行命令节点
{
"command": "python /path/to/MCP-Bayut-Crawler/main.py"
}步骤2:添加HTTP请求节点(与MCP服务器通信)
{
"method": "POST",
"url": "http://localhost:8000/tools/search_bayut_listings",
"body": {
"location": "{{ $json['location'] }}",
"purpose": "sale",
"beds": "{{ $json['beds'] }}",
"price_max": "{{ $json['budget'] }}"
}
}步骤3:流程结果
使用n8n的内置节点过滤、转换和路由列表数据。
Claude桌面集成
添加到您的Claude Desktop配置(~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"bayut": {
"command": "python",
"args": ["/path/to/MCP-Bayut-Crawler/main.py"],
"env": {
"BAYUT_HEADLESS": "true",
"BAYUT_CRAWLER_MAX_PAGES": "5"
}
}
}
}现在你可以问克劳德:
“在迪拜码头找到300万迪拉姆以下的三居室公寓”
Claude将自动使用MCP工具搜索Bayut并显示结果。
Python客户端示例
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def search_properties():
server_params = StdioServerParameters(
command="python",
args=["main.py"],
env={"BAYUT_HEADLESS": "true"}
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
# Call search tool
result = await session.call_tool(
"search_bayut_listings",
arguments={
"location": "downtown-dubai",
"purpose": "sale",
"beds": "2",
"price_max": 2000000,
"max_pages": 3
}
)
print(result)
asyncio.run(search_properties())🏗️ 项目结构
MCP-Bayut-Crawler/
├── mcp_server/ # MCP server implementation
│ ├── server.py # Main MCP server
│ ├── schemas.py # Pydantic models & JSON schemas
│ ├── crawler_wrapper.py # Sync/async bridge
│ └── tools/ # MCP tool handlers
│ ├── search.py # Search listings tool
│ ├── details.py # Get details tool
│ └── nlp.py # NLP parser tool
├── crawler/ # Bayut crawler implementation
│ ├── browser.py # Playwright browser manager
│ ├── search.py # Search crawler logic
│ ├── listing_parser.py # HTML parsing
│ ├── pagination.py # Pagination handler
│ ├── config.py # Configuration
│ └── utils.py # Utility functions
├── main.py # Server entry point
├── requirements.txt # Python dependencies
├── .env.example # Example environment config
└── README.md # This file⚙️ 配置
环境变量
| 变量 | 默认值 | 描述 |
|---|---|---|
BAYUT_CRAWLER_MAX_PAGES | 5 | 每次搜索可抓取的最大页面数 |
BAYUT_CRAWLER_DELAY_MIN | 1.0 | 请求之间的最小延迟(秒) |
BAYUT_CRAWLER_DELAY_MAX | 3.0 | 请求之间的最大延迟(秒) |
BAYUT_CRAWLER_TIMEOUT | 30 | 页面加载超时(秒) |
BAYUT_HEADLESS | false | 在无头模式下运行浏览器 |
BAYUT_MAX_RETRIES | 2 | 失败重试次数 |
DEBUG | false | 启用调试日志记录 |
支持的位置别名
NLP解析器识别公共区域缩写:
jbr→ 美拉海滩住宅区marina→ 迪拜码头downtown→ 迪拜市中心jvc→ 朱美拉乡村圈jlt→ 朱美拉湖塔楼difc→ 迪拜国际金融中心- 还有更多。..
🧪 测试
运行单元测试
pytest tests/ -v测试NLP解析器
python -m mcp_server.tools.nlp测试搜索
python -c "
from mcp_server.crawler_wrapper import get_crawler_wrapper
import asyncio
async def test():
wrapper = get_crawler_wrapper()
result = await wrapper.search_async(
location='downtown-dubai',
purpose='sale',
beds='2',
max_pages=1
)
print(result)
asyncio.run(test())
"📊 日志记录
服务器提供多级结构化日志记录:
- 信息:工具调用、搜索结果、页数
- 调试:爬虫内部、HTTP请求、解析详细信息
- 错误:请求失败、验证错误、崩溃
日志格式:
[2025-11-15 10:30:00] [INFO] [mcp_server.tools.search] Searching Bayut: location=downtown-dubai, purpose=sale
[2025-11-15 10:30:05] [INFO] [crawler.search] Found 28 property cards on page
[2025-11-15 10:30:05] [INFO] [mcp_server.tools.search] Search completed: 28 listings found🔥 错误处理
服务器优雅地处理各种错误情况:
- 无效的位置 → 返回区域建议错误
- 超时 → 重试一次,返回部分结果
- Cloudflare块 → 返回带有回退消息的错误
- 缺少列表 → 返回结构化404错误
- 低置信度NLP解析 → 返回置信度低的解析数据
🚦 速率限制
爬虫实现智能限速:
- 1-3秒之间的随机延迟(可配置)
- 尊重Bayut的robots.txt
- 错误时自动回退
- 每个请求最多重试2次
🤝 贡献
欢迎投稿!拜托:
- 分叉存储库
- 创建要素分支(
git checkout -b feature/amazing-feature) - 提交您的更改(
git commit -m 'Add amazing feature') - 推到分支(
git push origin feature/amazing-feature) - 打开拉取请求
📝 许可证
此项目根据MIT许可证获得许可-有关详细信息,请参阅许可证文件。
⚠️ 免责声明
此工具仅用于教育和研究目的。请遵守Bayut的服务条款并负责任地使用。始终在请求之间添加适当的延迟,避免过度抓取。
🆘 支持
对于问题、疑问或功能请求:
- 在GitHub上打开一个问题
- 检查现有文档
- 查看日志
DEBUG=true
🎉 致谢
______________________________________________________________________
由以下材料制成❤️ 面向房地产自动化社区
