iter_participants

可以在文档中搜索此方法

关于iter_participants

iter_participants 是 Telethon 库中一个用来获取某个聊天(如频道、群组等)中的所有参与者(用户)信息的迭代器。它可以逐个返回指定聊天中的用户,通常用在需要获取大规模用户信息时。

方法签名

iter_participants(entity: hints.EntityLike, limit: float = None, *, search: str = '', filter: types.TypeChannelParticipantsFilter = None, aggressive: bool = False)

参数说明:

  • entity: 这是你想获取参与者的聊天实体。entity 可以是一个 chat 的 ID 或者一个 User 对象,表示你要查询的聊天。比如,可以是某个频道、群组的对象或其 ID。
  • limit: 这是你希望获取的最大参与者数量。比如,设置为 100 则表示最多返回 100 个参与者。若未指定,默认为 None,意味着没有限制。
  • search: 这是一个字符串,允许你根据用户名称进行筛选。只有用户名称中包含该字符串的用户才会被返回。例如,设置为 "john" 可能会返回所有用户名中包含 "john" 的参与者。
  • filter: 这是一个可选参数,允许你指定对参与者进行进一步筛选的条件。Telethon 提供了几种内建的筛选器类型(如 FilterAdminsFilterBots 等)。这些筛选器可以帮助你只获取特定类型的用户,比如只获取管理员或机器人等。
  • aggressive: 默认为 False,是否在遍历参与者时更加“激进”地去获取更多的用户。这个参数的具体作用是如何控制请求的行为,通常用于大量用户的场景。

返回值:

  • 该方法返回一个 _ParticipantsIter 对象,这是一个迭代器,你可以通过迭代这个对象来获取每一个参与者的详细信息。

作用:

  • iter_participants 用于从一个指定的聊天中逐个获取所有参与者的信息。这个方法非常适合需要处理大量聊天成员数据的场景,比如你想要获取一个大型群组的所有成员信息,或者筛选某个频道中的管理员、成员等。
  • 函数文档中的“顺序未指定”意味着返回的用户列表没有特定的顺序。返回的参与者顺序可能会因为 Telegram 服务器的变化或其他因素而有所不同。你不应该依赖顺序来处理数据。

用法

from telethon.sync import TelegramClient
from telethon.tl.types import PeerChannel

# 假设你已经正确设置并连接到 Telegram Client
client = TelegramClient('session_name', api_id, api_hash)

# 获取某个频道的所有成员
entity = PeerChannel(channel_id)  # 你可以替换为频道的 ID 或者 Channel 对象
participants = client.iter_participants(entity, limit=100)

# 输出每个参与者的信息
for participant in participants:
    print(participant.username, participant.id)

总结

iter_participants 是一个非常有用的函数,能够帮助你从一个指定的 Telegram 聊天(群组或频道)中获取所有参与者的信息。你可以控制获取的数量、筛选特定用户(如管理员、机器人等)以及根据用户名进行搜索等。返回的结果顺序不固定,适用于你需要迭代和处理大量数据的场景。

PeerChannel

关于PeerChannel,请查看:

https://czjdwy.xyz/index.php/archives/15/

异步生成器

  1. 按需拉取数据
    iter_participants 是一种懒加载机制,它不会一次性加载所有成员到内存,而是在迭代时根据需要从 Telegram API 分页获取数据。这对于大群组(成员数量可能达几千或更多)非常重要,可以避免:

    • 内存占用过高
    • API 超时
    • 数据获取不完整
  2. 分页自动处理
    async for 的每次循环会触发生成器内部发送请求并接收一批成员数据,直到所有数据获取完成。您不需要手动处理分页(比如计算 offset),生成器会帮您完成这些工作。
  3. 控制逻辑
    使用 async for 允许在每次获取数据后插入控制逻辑,例如:

    • 动态延迟(await asyncio.sleep(delay)),防止触发速率限制。
    • 处理异常(如 FloodWaitError)。
    • 逐步处理成员数据,避免一次性加载所有数据到内存。

participants = client.iter_participants(entity) 中,participants 是一个生成器,它还没有真正获取数据,只有在 async for 中逐步迭代时才会真正拉取成员数据。因此,async for 是关键,它不仅负责触发数据拉取,还允许您动态控制和处理数据,从而提高代码的灵活性和效率。

        entity = PeerChannel(11111111)
        participants = client.iter_participants(entity, limit=100)

        all_members = []
        try:
            async for participant in participants:
                print(f"ID: {participant.id}, 用户名: {participant.username}")
                all_members.append(participant)
                await asyncio.sleep(2)  # 动态延迟,防止触发速率限制
        except FloodWaitError as e:
            print(f"Flood wait triggered. Sleeping for {e.seconds} seconds.")
            await asyncio.sleep(e.seconds)

client.iter_participants(entity, limit=100) 只是生成了一个异步迭代器,而实际的 API 请求是在 async for participant in participants 中逐条触发的。因此,limit=100 并不会直接影响 async for 的请求行为,它只是限制了迭代器返回的参与者总数。

减少FloodWaitError的风险

可以增加一个参数batch_size 去控制请求的频率

async def sync_group_members(group_id: int):
    entity = PeerChannel(group_id)
    bot_group = await botGroup.get_or_none(group_id=group_id)
  
    # 一次性获取所有参与者
    participants = await client.get_participants(entity, limit=200)
  
    # 分批处理用户,每批处理 10 个用户
    batch_size = 10
    try:
        for i in range(0, len(participants), batch_size):
            batch = participants[i:i + batch_size]
            await process_batch(batch, bot_group)
            await asyncio.sleep(random.uniform(5, 10))  # 随机等待 5-10 秒
  
    except FloodWaitError as e:
        await asyncio.sleep(e.seconds)
        return False

async def process_batch(participants, bot_group):
    for participant in participants:
        业务逻辑
      

关于 limitbatch_size 的关系

  • limit 的作用limit=100 表示你最多只会获取 100 个参与者。即使群组中有超过 100 个成员,iter_participants 也只会返回前 100 个。这个参数的作用是限制迭代器的返回数量,而不是控制 API 请求的频率。
  • batch_size 的作用batch_size 是你自己定义的分批处理的大小。它决定了你在每次处理多少个参与者后等待一段时间。batch_sizelimit 是独立的,batch_size 不会影响 limit 的行为。

为什么 limitbatch_size 看起来没有直接关系?

  • limit 控制的是总数limit=100 表示你最多只会获取 100 个参与者。
  • batch_size 控制的是处理频率batch_size=10 表示你每处理 10 个参与者后等待一段时间。

既然 limitbatch_size 是独立的,那就可以根据实际需求调整这两个参数:

  • limit:如果你只关心前 100 个参与者,可以保留 limit=100。如果你需要获取更多参与者,可以增加 limit 的值。
  • batch_size:如果你希望减少 API 请求的频率,可以增加 batch_size 的值,比如每批处理 20 个参与者。

QA:

如果要使用分页可以查看

https://czjdwy.xyz/index.php/archives/14/
需要查看字段解释请看:
https://czjdwy.xyz/index.php/archives/17/
分类: telethon 标签: pythontelethon

评论

全部评论 1

  1. Mrjun
    Mrjun
    Google Chrome MacOS
    更新了部分关于异步生成器的内容

目录