> 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
> - V4 实验版: 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 为您处理分页，并构建一个可与开发者令牌（持有者身份验证）配合使用的客户端。
* [Python 评论抓取工具](https://github.com/Frameio/comment-scraper-python) - 我们使用的代码示例在此处。




### 在 Glitch 上尝试

Glitch 是一个简单的工具，允许您搭建自己的应用程序，并使用他们的服务器进行测试和运行。如果您不熟悉 Glitch，请参阅我们关于[使用 Glitch](/other-tools/using-glitch) 的指南。如果您想看看评论抓取工具在服务器上运行的效果，我们在 [Glitch](https://glitch.com) 上搭建了一个 Flask 应用程序：[Frame.io Python 评论抓取工具](https://glitch.com/~frameio-comment-scraper)。

### 必需的权限范围




在开始本指南之前，您需要确保拥有一个至少包含以下权限范围的令牌：




| 权限范围 | 原因 |
| ---------- | ---------- |
| **项目：**读取 | 并非严格必须，但对于获取项目的 `root_asset_id` 是必需的。 |
| **资产：**读取 | 通过 API 导航 `asset_ids` 时必需 |
| **评论：**读取 | 检索评论本身时必需。 |




### 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`
* 主 ID - `parent_id`
* 资产 ID - `asset_id`
* 资产名称 - `name`
* 所有者 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 项目的展平后评论。