Добрый вечер!
Возник вопрос с апи'шкой вк. Мне нужно получать список всех участников сообщества за максимально короткое время. Попробовал через стандартный groups.getMembers:
Пример кода
async def get_vk_users(group_name: str) -> list:
url = f'https://api.vk.com/method/groups.getMembers?' \
f'access_token={vk_token}&' \
f'v={vk_version}&' \
f'group_id={group_name}&' \
f'fields={fields}&' \
f'offset={response}'
async with aiohttp.ClientSession() as session:
async with session.get(url=url) as req:
result = (await req.json())['response']['items']
return result
Проблема этого подхода - лимит. Максимум 3000 участников в секунду
Погуглив понял, что надо юзать
execute.
Пример кода
async def get_all_users_lists(group_names: list):
fields = ','.join(['sex', 'contacts', 'last_seen'])
async with semaphore:
users_lists = []
for group_name in group_names:
members_count = await _get_subscribers_quantity(group_name)
group_users = []
for offset_ in range(0, members_count, 25_000):
code = f"""
var count = {members_count};
var offset = {offset_};
var i = 0;
var members = [];
while (i < 25 && offset < count){{
members = members + API.groups.getMembers({{"group_id":"prog_life", "count":1000, "offset": offset, "fields": {fields}}}).items;
offset = offset + 1000;
i = i + 1;
}}
return members;
"""
async with aiohttp.ClientSession() as session:
data = {
"code": code,
"access_token": vk_token,
"v": vk_version,
}
async with session.post(url=f"https://api.vk.com/method/execute", data=data) as req:
response = await req.json()
print(response)
group_users.extend(response['response'])
await asyncio.sleep(0.35)
users_lists.append(group_users)
return users_lists
Ожидалось получить 25 000 пользователей в секунду. И действительно, это работает, но когда в code НЕ указывается аттрибут fields (то есть получаем пустые id'шки). Как только указал в fields хотя бы одно значение (contacts, например) время выполнения скрипта резко ухудшилось до ~10секунд/каждый запрос. Когда добавил еще одно значение (скажем, указал пол) ~30с/за 1 запрос.
И условно, если надо получить всех участников сообщества со 100К участниками, 4 запроса (по 25К) по 30 секунд = 2 минуты.
Не могу понять, это проблема в коде или в api? В любом из случаев, как это оптимизировать, в каком направлении копать?