You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python msgraph API获取会议室日历的技术问题求助

使用新版Python Microsoft Graph SDK获取会议室日历(应用权限模式)

问题背景

已完成操作:

  • 在Azure AD中为应用配置了Bookings.Read.All、Calendars.Read、Calendars.ReadBasic.All、Group.Read.All、Place.Read.All、User.Read应用权限并获得管理员同意
  • 通过证书认证成功登录Microsoft Graph,已获取到会议室列表
    需求:
  • 获取每个会议室过去一周的日历事件,包含已预订会议及参会人员
    遇到的问题:
  • 使用graph_client.users.by_user_id(room_id).calendar.events.get()无法获取数据,且教程中client.me端点不适用于应用权限模式

解决方案

核心要点

  1. 会议室的本质是资源账户:在Microsoft Graph中,会议室属于特殊的用户(资源账户),因此可以通过users端点访问其日历,使用会议室的ID或邮箱地址均可作为user_id参数。
  2. 添加时间筛选条件:通过$filter参数筛选过去一周的事件,避免返回全部历史数据。
  3. 处理分页结果:Graph API默认返回最多100条数据,需循环获取所有分页结果。
  4. 权限验证:确保Calendars.Read应用权限已被管理员同意(此权限足够读取会议室日历)。

修改后的代码

#!/usr/bin/env python3
import asyncio
from datetime import datetime, timedelta
from msgraph.generated.models.room import Room
from msgraph import GraphServiceClient
from azure.identity import CertificateCredential

config = {
    'client_id': '<your-client-id>',
    'tenant_id': '<your-tenant-id>',
    'certificate_path': 'msal_crt_n_key.pem',
    'scope': ['https://graph.microsoft.com/.default'],
}

async def get_schedule_for_room(graph_client, room_identifier):
    # 计算过去一周的UTC时间范围
    one_week_ago = (datetime.utcnow() - timedelta(weeks=1)).isoformat() + 'Z'
    now = datetime.utcnow().isoformat() + 'Z'

    # 构建请求参数:筛选时间范围+展开参会人员信息
    query_params = {
        '$filter': f"start/dateTime ge '{one_week_ago}' and end/dateTime le '{now}'",
        '$expand': 'attendees'
    }

    all_events = []
    result = await graph_client.users.by_user_id(room_identifier).calendar.events.get(query_parameters=query_params)
    
    # 处理分页,获取所有事件
    while result:
        if result.value:
            all_events.extend(result.value)
        if result.odata_next_link:
            result = await graph_client.users.by_user_id(room_identifier).calendar.events.get(url=result.odata_next_link)
        else:
            break
    return all_events

async def get_rooms(graph_client):
    return await graph_client.places.graph_room.get()

async def main():
    print("Login using certificate")
    credential = CertificateCredential(
        tenant_id=config['tenant_id'],
        client_id=config['client_id'],
        certificate_path=config['certificate_path']
    )

    graph_client = GraphServiceClient(credential, config['scope'])
    print("Get list of rooms")
    rooms = await get_rooms(graph_client)
    print(f"Found {len(rooms.value) if rooms.value else 0} rooms")

    if rooms.value:
        for room in rooms.value:
            print(f"\nProcessing room: {room.display_name} ({room.email_address})")
            # 使用会议室邮箱地址作为标识符(也可替换为room.id)
            events = await get_schedule_for_room(graph_client, room.email_address)
            print(f"Found {len(events)} events in the past week:")
            for event in events:
                attendee_count = len(event.attendees) if event.attendees else 0
                print(f"- {event.subject} | Start: {event.start.date_time} | Attendees: {attendee_count}")

asyncio.run(main())

关键修改说明

  1. 时间筛选:用UTC时间格式限定过去一周的事件范围,避免时区偏差导致的筛选错误。
  2. 参会人员展开:通过$expand=attendees直接获取参会人员数据,无需额外接口请求。
  3. 分页处理:循环读取所有分页结果,确保不会遗漏超出默认返回数量的事件。
  4. 变量修复:修正了原代码中print(calendars)的变量名错误,改用会议室邮箱作为请求标识符(比ID更直观)。
  5. 日志优化:增加了结构化的输出信息,便于快速查看会议室的预订情况。

内容的提问来源于stack exchange,提问作者Kodsama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 23:15:35