> This page is for Платформа, version Предыдущая версия.
> For other versions, use one of these documentation indexes:
> - V4 (default): https://next.developer.frame.io/platform/v4/llms.txt
> - Версия 4 экспериментальная: https://next.developer.frame.io/platform/v4-experimental/llms.txt
> - Предыдущая версия: https://next.developer.frame.io/platform/v2/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://next.developer.frame.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://next.developer.frame.io/_mcp/server.

# Сбор всех комментариев из проекта

## Обзор




Инструмент извлечения комментариев получает все ресурсы в проекте, извлекает комментарии и выводит их в файл CSV. В этом пошаговом руководстве используются следующие ресурсы:



* [Python SDK](https://github.com/Frameio/python-frameio-client) — SDK выполняет разбивку на страницы за вас и настраивает клиент, который можно использовать с токенами разработчика (аутентификация Bearer).
* [Инструмент извлечения комментариев на Python](https://github.com/Frameio/comment-scraper-python) — пример кода, который мы используем, находится здесь.




### Попробуйте на Glitch

Glitch — это простой инструмент, который позволяет настраивать собственные приложения, тестировать и запускать их на их серверах. Если вы еще не работали с Glitch, ознакомьтесь с нашим руководством по [использованию Glitch](/other-tools/using-glitch). Если хотите увидеть, как работает инструмент извлечения комментариев на сервере, мы настроили приложение Flask на [Glitch](https://glitch.com): [инструмент извлечения комментариев Frame.io на Python](https://glitch.com/~frameio-comment-scraper).

### Необходимые области доступа




Перед началом работы с этим руководством убедитесь, что у вас есть токен, который включает как минимум следующие области доступа:




| Область доступа | Причина |
| ---------- | ---------- |
| **Проекты:** чтение | Не является строго обязательным, но необходимо для получения `root_asset_id` проекта. |
| **Ресурсы:** чтение | Необходимо для навигации по `asset_ids` через API-интерфейс |
| **Комментарии:** чтение | Необходимо для получения самих комментариев. |




### 1. Подготовка приложения

Это руководство будет следовать такой же схеме, как [чтение дерева файлов](/workflows-assets/reading-the-file-tree). Соответственно, для начала работы вам потребуется:
* `root_asset_id` проекта, который вы сканируете;
* [токен разработчика](/authentication/developer-tokens).

Также нужно импортировать `FrameioClient` в ваше приложение Python и некоторые дополнительные вспомогательные библиотеки:

**`Python`**

```python title="Python"
from frameioclient import FrameioClient
import requests, json, csv, itertools

ROOT_ASSET_ID = "<ROOT_ASSET_ID>"
TOKEN = "<DEV_TOKEN>"
```





### 2. Сканирование проекта




Теперь нужно рекурсивно получить все ресурсы, проверить их на наличие комментариев и сохранить любые ресурсы с комментариями в списке, из которого можно создать файл .csv.





При сканировании проекта нужно выполнить следующие проверки для каждого ресурса:



* Является ли ресурс файлом? (`&quot;_type&quot;: &quot;file&quot;`).

* Если это файл, есть ли у него комментарии? * **Если есть, получите их и добавьте в ваш список.**
* Является ли ресурс папкой? (`&quot;_type&quot;: &quot;folder&quot;`)

* **Если это папка, выполните рекурсивную обработку ее дочерних элементов.**
* Является ли ресурс стеком версий? (`&quot;_type&quot;: &quot;version_stack&quot;`)

* **Если это стек версий, получите все дочерние элементы и проверьте их на наличие комментариев.**

**`Python`**

```python title="Python"
def all_comments(client, asset_id, comment_list):
    files = client.get_asset_children(asset_id)

    for asset in files:
        if asset['type'] == "file":
            if asset['comment_count'] > 0:
                asset_parent_id = asset['parent_id']
                asset_name = asset['name']
                comments = client.get_comments(asset['id'])
                my_comment_list = [comment for comment in comments.results]
                for object in my_comment_list:
                    object.update({'parent_id':asset_parent_id})
                    object.update({'name':asset_name})
                comment_list.append(my_comment_list)

        if asset['type'] == "folder":
            if asset['item_count'] > 0:
                all_comments(client, asset['id'], comment_list)

        if asset['type'] == "version_stack":
            asset_name = asset['name']
            parent_id = asset['parent_id']
            vfiles = client.get_asset_children(asset['id'])

            for asset in vfiles.results:
                asset_name = asset['name']
                parent_id = asset['parent_id']
                if asset['type'] == "file":
                    if asset['comment_count'] > 0:
                        comments = client.get_comments(asset['id'])
                        my_comment_list = [comment for comment in comments.results]
                        for object in my_comment_list:
                            object.update({'parent_id':parent_id})
                            object.update({'name':asset_name})
                        comment_list.append(my_comment_list)

def get_all_project_comments(root_asset_id, token):
    comment_list = []
    client = FrameioClient(token)

    all_comments(client, root_asset_id, comment_list)

    return comment_list
```




<Info title="Не забудьте о разбивке на страницы">
  Приведенный выше пример игнорирует разбивку на страницы — но при навигации по большим коллекциям этим не следует пренебрегать! См. наше руководство [Основные концепции](/getting-started/key-concepts#pagination) для справки.
</Info>


### 3. Приведение списка комментариев к плоскому виду




Если вы не сделали этого во время сканирования, нужно будет привести список к плоскому виду для более легкой обработки.





**`Python`**

```python title="Python"
# The response list comes back as a list of lists.
# Flatten out responses to a single list so you can build your .csv file.

flat_response_list = list(itertools.chain.from_iterable(responses))
```





### 4. Отбраковка списка и создание файла .csv




Когда список приведен к плоскому виду, можно использовать генератор списков для извлечения полезных для вас элементов из каждого комментария, а затем вывести их в файл .csv. Мы рекомендуем включить как минимум:



* Комментарий — `text`
* ИД родительского элемента — `parent_id`
* ИД ресурса — `asset_id`
* Имя ресурса — `имя`
* ИД владельца — `owner_id`
* Адрес электронной почты владельца — `owner.email`
* Метка времени — `timestamp`
* Время обновления — `updated_at`




После создания нового списка с нужными данными для каждого ресурса и получением итогового результата, можно записывать данные в файл .csv.





**`Python`**

```python title="Python"
list_for_csv = [[o['text'], o['parent_id'], o['asset_id'], o['name'], o['owner_id'], o['owner']['email'], o['timestamp'], o['updated_at']] for o in flat_response_list]

# Let's write our new list out to a .csv file. We'll add a heading.
with open("output.csv", 'w') as myfile:
     wr = csv.writer(myfile, dialect='excel')
     wr.writerow(['Comment', 'Parent ID', 'Asset ID', 'Asset Name', 'Owner ID', 'Email', 'Timestamp', 'Updated At'])
     wr.writerows(list_for_csv)
```





Вот и все!Теперь у вас есть файл .csv с развернутыми комментариями из всего проекта Frame.io.