> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sorsa.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 列表与社群

通过 Sorsa API 获取公开 X 列表的成员、订阅者和推文流。本页也介绍 API 参考中的社群请求格式；用于新工作流之前，请先阅读可用性说明。

> **注意：** 策略背景、成本计算和端到端监测工作流见博客上的 [X 列表 API 指南](https://api.sorsa.io/blog/x-lists-and-communities-api)。

> **社群可用性：** API 参考列出了社群端点，但当前数据可用性需要确认。构建新社群工作流前，请[联系支持团队](https://docs.sorsa.io/zh-Hans/support)确认哪些操作和结果可用。下方请求示例只是接口说明，不是实时可用性测试。

***

## 列表

X 列表是最多包含 5,000 个账号的公开集合，存在两类用户：

* **成员：** 由列表管理者加入的账号。
* **订阅者：** 订阅该列表时间线的用户。

API 无法访问私有列表。

| 端点                   | 方法  | 返回内容          | 每页数量   |
| :------------------- | :-- | :------------ | :----- |
| `/v3/list-members`   | GET | 列表内账号的用户资料    | 最多 200 |
| `/v3/list-followers` | GET | 订阅列表的用户资料     | 最多 200 |
| `/v3/list-tweets`    | GET | 列表成员按时间合并的推文流 | 约 20   |

列表 ID 是 URL 中的数字：`https://x.com/i/lists/1234567890` 对应 ID `1234567890`。

> **提示：** 新账号均有 100 次免费请求，无需信用卡、永不过期，足以完整获取中等规模列表。可在 [API Playground](https://api.sorsa.io/playground) 中无代码测试任意端点。

### 获取列表成员

`GET /v3/list-members`

| 参数            | 类型     | 必需 | 说明         |
| :------------ | :----- | :- | :--------- |
| `list_id`     | string | 是  | 数字列表 ID。   |
| `next_cursor` | string | 否  | 上一响应的分页游标。 |

```bash theme={null}
curl "https://api.sorsa.io/v3/list-members?list_id=1234567890" \
  -H "ApiKey: YOUR_API_KEY"
```

```python theme={null}
import requests

API_KEY = "YOUR_API_KEY"
BASE = "https://api.sorsa.io/v3"
HEADERS = {"ApiKey": API_KEY}


def get_list_members(list_id, max_pages=50):
    members, cursor = [], None

    for _ in range(max_pages):
        params = {"list_id": list_id}
        if cursor:
            params["next_cursor"] = cursor

        r = requests.get(f"{BASE}/list-members", headers=HEADERS, params=params, timeout=30)
        r.raise_for_status()
        data = r.json()

        members.extend(data.get("users", []))
        cursor = data.get("next_cursor")
        if not cursor:
            break

    return members


members = get_list_members("1234567890")
for u in members[:5]:
    print(f"@{u['username']} ({u['followers_count']:,} followers)")
```

完整提取 5,000 名成员的列表约需 25 次请求。

### 获取列表订阅者

`GET /v3/list-followers`

| 参数            | 类型     | 必需 | 说明             |
| :------------ | :----- | :- | :------------- |
| `list_link`   | string | 是  | 列表 URL 或数字 ID。 |
| `next_cursor` | string | 否  | 分页游标。          |

注意参数名：`/list-followers` 使用 `list_link`（URL 或 ID）；`/list-members` 和 `/list-tweets` 使用 `list_id`（仅数字 ID）。

```python theme={null}
def get_list_followers(list_link, max_pages=50):
    followers, cursor = [], None

    for _ in range(max_pages):
        params = {"list_link": list_link}
        if cursor:
            params["next_cursor"] = cursor

        r = requests.get(f"{BASE}/list-followers", headers=HEADERS, params=params, timeout=30)
        r.raise_for_status()
        data = r.json()

        followers.extend(data.get("users", []))
        cursor = data.get("next_cursor")
        if not cursor:
            break

    return followers


subs = get_list_followers("https://x.com/i/lists/1234567890")
print(f"{len(subs)} subscribers")
```

### 获取列表推文

`GET /v3/list-tweets`

将所有列表成员的近期推文合并为一个按时间排序的信息流。[实时监测](https://docs.sorsa.io/zh-Hans/real-time-monitoring)工作流使用此端点，通过一次请求追踪一组账号，无需逐个轮询。

| 参数            | 类型     | 必需 | 说明       |
| :------------ | :----- | :- | :------- |
| `list_id`     | string | 是  | 数字列表 ID。 |
| `next_cursor` | string | 否  | 分页游标。    |

```python theme={null}
def get_list_tweets(list_id, max_pages=10):
    tweets, cursor = [], None

    for _ in range(max_pages):
        params = {"list_id": list_id}
        if cursor:
            params["next_cursor"] = cursor

        r = requests.get(f"{BASE}/list-tweets", headers=HEADERS, params=params, timeout=30)
        r.raise_for_status()
        data = r.json()

        tweets.extend(data.get("tweets", []))
        cursor = data.get("next_cursor")
        if not cursor:
            break

    return tweets


feed = get_list_tweets("1234567890", max_pages=10)
for t in feed[:5]:
    print(f"@{t['user']['username']}: {t['full_text'][:80]}")
```

***

## 社群

以下格式描述 API 参考中的社群端点。依赖它们之前，请按上方说明确认可用性。

成员数据可用时，社群身份可作为受众发现信号，但不能单独证明近期活跃度。

| 端点                            | 方法   | 返回内容     | 每页数量 |
| :---------------------------- | :--- | :------- | :--- |
| `/v3/community-members`       | POST | 社群成员资料   | 约 20 |
| `/v3/community-tweets`        | POST | 社群内发布的推文 | 约 20 |
| `/v3/community-search-tweets` | POST | 社群内关键词搜索 | 约 20 |

社群 ID 是 URL 中的数字：`https://x.com/i/communities/1966045657589813686` 对应 `1966045657589813686`。

私有社群此前无法通过 API 访问。

### 获取社群成员

`POST /v3/community-members`

| 参数               | 类型     | 必需 | 说明             |
| :--------------- | :----- | :- | :------------- |
| `community_link` | string | 是  | 社群 ID 或完整 URL。 |
| `next_cursor`    | string | 否  | 分页游标。          |

返回精简成员资料，包括 ID、用户名、显示名称、头像、认证和受保护状态。

```python theme={null}
def get_community_members(community_link, max_pages=20):
    members, cursor = [], None

    for _ in range(max_pages):
        body = {"community_link": community_link}
        if cursor:
            body["next_cursor"] = cursor

        r = requests.post(
            f"{BASE}/community-members",
            headers={**HEADERS, "Content-Type": "application/json"},
            json=body,
            timeout=30,
        )
        r.raise_for_status()
        data = r.json()

        members.extend(data.get("users", []))
        cursor = data.get("next_cursor")
        if not cursor:
            break

    return members
```

### 获取社群推文

`POST /v3/community-tweets`

| 参数             | 类型     | 必需 | 说明                           |
| :------------- | :----- | :- | :--------------------------- |
| `community_id` | string | 是  | 数字社群 ID。                     |
| `order`        | string | 否  | `"latest"`（默认）或 `"popular"`。 |
| `next_cursor`  | string | 否  | 分页游标。                        |

```python theme={null}
def get_community_tweets(community_id, order="latest", max_pages=10):
    tweets, cursor = [], None

    for _ in range(max_pages):
        body = {"community_id": community_id, "order": order}
        if cursor:
            body["next_cursor"] = cursor

        r = requests.post(
            f"{BASE}/community-tweets",
            headers={**HEADERS, "Content-Type": "application/json"},
            json=body,
            timeout=30,
        )
        r.raise_for_status()
        data = r.json()

        tweets.extend(data.get("tweets", []))
        cursor = data.get("next_cursor")
        if not cursor:
            break

    return tweets
```

### 搜索社群推文

`POST /v3/community-search-tweets`

| 参数               | 类型     | 必需 | 说明                        |
| :--------------- | :----- | :- | :------------------------ |
| `community_link` | string | 是  | 社群 ID 或完整 URL。            |
| `query`          | string | 否  | 搜索关键词。省略时返回完整社群信息流。       |
| `order`          | string | 否  | `"popular"` 或 `"latest"`。 |
| `next_cursor`    | string | 否  | 分页游标。                     |

```python theme={null}
def search_community_tweets(community_link, query, order="popular", max_pages=5):
    tweets, cursor = [], None

    for _ in range(max_pages):
        body = {"community_link": community_link, "query": query, "order": order}
        if cursor:
            body["next_cursor"] = cursor

        r = requests.post(
            f"{BASE}/community-search-tweets",
            headers={**HEADERS, "Content-Type": "application/json"},
            json=body,
            timeout=30,
        )
        r.raise_for_status()
        data = r.json()

        tweets.extend(data.get("tweets", []))
        cursor = data.get("next_cursor")
        if not cursor:
            break

    return tweets
```

如果只检查某位用户的成员身份，无需分页获取完整成员列表，应使用专用的 [`/check-community-member`](https://docs.sorsa.io/zh-Hans/api-reference/verification/check-community-membership)。

***

## 导出到 CSV

上方列表端点的用户和推文流可通过一个辅助函数导出。用户示例如下：

```python theme={null}
import csv

def export_users_to_csv(users, path):
    fields = ["id", "username", "display_name", "description",
              "followers_count", "tweets_count", "verified", "location"]

    with open(path, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fields)
        writer.writeheader()
        for u in users:
            writer.writerow({
                "id": u.get("id", ""),
                "username": u.get("username", ""),
                "display_name": u.get("display_name", ""),
                "description": (u.get("description") or "").replace("\n", " "),
                "followers_count": u.get("followers_count", 0),
                "tweets_count": u.get("tweets_count", 0),
                "verified": u.get("verified", False),
                "location": u.get("location", ""),
            })


export_users_to_csv(get_list_members("1234567890"), "members.csv")
```

`/list-members` 和 `/list-followers` 在 `users` 中返回资料；`/list-tweets` 在 `tweets` 中返回推文，作者位于 `user` 下。可选资料字段可能为空。导出推文时，需要显式展开嵌套值，例如 `{"username": tweet["user"]["username"]}`；CSV 写入器不会自动解析 `user.username` 这样的点分字段名。

***

## 相关内容

* [X 列表 API 指南](https://api.sorsa.io/blog/x-lists-and-communities-api)：策略、成本和场景
* [实时监测](https://docs.sorsa.io/zh-Hans/real-time-monitoring)：`/list-tweets` 轮询方式
* [发现目标受众](https://docs.sorsa.io/zh-Hans/target-audiences-Discovery)：通过列表研究受众
* [营销活动验证](https://docs.sorsa.io/zh-Hans/Marketing-Campaign-Verification)：成员身份检查
* [优化 API 使用](https://docs.sorsa.io/zh-Hans/optimizing-api-usage)：批量请求和速率限制处理
