reddit-api
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseReddit API Skill
Reddit API 技能
Load with: base.md + [language].md
For integrating Reddit data into applications - fetching posts, comments, subreddits, and user data.
加载方式:base.md + [语言].md
用于将Reddit数据集成到应用程序中——获取帖子、评论、子版块和用户数据。
Setup
设置
1. Create Reddit App
1. 创建Reddit应用
- Go to https://www.reddit.com/prefs/apps
- Click "Create App" or "Create Another App"
- Fill in:
- Name: Your app name
- App type:
- - For personal use / bots you control
script - - For server-side apps with user auth
web app - - For mobile/desktop apps
installed app
- Redirect URI: (for dev)
http://localhost:8000/callback
- Note your (under app name) and
client_idclient_secret
- 访问 https://www.reddit.com/prefs/apps
- 点击“Create App”或“Create Another App”
- 填写信息:
- 名称:你的应用名称
- 应用类型:
- - 用于个人使用/你控制的机器人
script - - 用于带用户认证的服务器端应用
web app - - 用于移动/桌面应用
installed app
- 重定向URI:(开发环境)
http://localhost:8000/callback
- 记录你的(应用名称下方)和
client_idclient_secret
2. Environment Variables
2. 环境变量
bash
undefinedbash
undefined.env
.env
REDDIT_CLIENT_ID=your_client_id
REDDIT_CLIENT_SECRET=your_client_secret
REDDIT_USER_AGENT=YourApp/1.0 by YourUsername
REDDIT_USERNAME=your_username # For script apps only
REDDIT_PASSWORD=your_password # For script apps only
**User-Agent Format**: `<platform>:<app_id>:<version> (by /u/<username>)`
---REDDIT_CLIENT_ID=your_client_id
REDDIT_CLIENT_SECRET=your_client_secret
REDDIT_USER_AGENT=YourApp/1.0 by YourUsername
REDDIT_USERNAME=your_username # 仅适用于script类型应用
REDDIT_PASSWORD=your_password # 仅适用于script类型应用
**User-Agent 格式**:`<platform>:<app_id>:<version> (by /u/<username>)`
---Rate Limits
速率限制
| Tier | Limit | Notes |
|---|---|---|
| OAuth authenticated | 100 QPM | Per OAuth client ID |
| Non-authenticated | Blocked | Must use OAuth |
- Limits averaged over 10-minute window
- Include header to avoid blocks
User-Agent - Respect response headers
X-Ratelimit-*
| 层级 | 限制 | 说明 |
|---|---|---|
| OAuth 已认证 | 100 QPM | 每个OAuth客户端ID |
| 未认证 | 被阻止 | 必须使用OAuth |
- 限制以10分钟窗口为平均值计算
- 必须包含请求头以避免被阻止
User-Agent - 遵循响应头
X-Ratelimit-*
Python: PRAW (Recommended)
Python:PRAW(推荐)
Installation
安装
bash
pip install prawbash
pip install prawor
或
uv add praw
undefineduv add praw
undefinedScript App (Personal Use / Bots)
Script类型应用(个人使用/机器人)
python
import praw
from pydantic_settings import BaseSettings
class RedditSettings(BaseSettings):
reddit_client_id: str
reddit_client_secret: str
reddit_user_agent: str
reddit_username: str
reddit_password: str
class Config:
env_file = ".env"
settings = RedditSettings()
reddit = praw.Reddit(
client_id=settings.reddit_client_id,
client_secret=settings.reddit_client_secret,
user_agent=settings.reddit_user_agent,
username=settings.reddit_username,
password=settings.reddit_password,
)python
import praw
from pydantic_settings import BaseSettings
class RedditSettings(BaseSettings):
reddit_client_id: str
reddit_client_secret: str
reddit_user_agent: str
reddit_username: str
reddit_password: str
class Config:
env_file = ".env"
settings = RedditSettings()
reddit = praw.Reddit(
client_id=settings.reddit_client_id,
client_secret=settings.reddit_client_secret,
user_agent=settings.reddit_user_agent,
username=settings.reddit_username,
password=settings.reddit_password,
)Verify authentication
验证认证
print(f"Logged in as: {reddit.user.me()}")
undefinedprint(f"已登录为:{reddit.user.me()}")
undefinedRead-Only (No User Auth)
只读模式(无需用户认证)
python
import praw
reddit = praw.Reddit(
client_id="your_client_id",
client_secret="your_client_secret",
user_agent="YourApp/1.0 by YourUsername",
)python
import praw
reddit = praw.Reddit(
client_id="your_client_id",
client_secret="your_client_secret",
user_agent="YourApp/1.0 by YourUsername",
)Read-only mode - can browse, can't post/vote
只读模式 - 可浏览,无法发帖/投票
reddit.read_only = True
undefinedreddit.read_only = True
undefinedCommon Operations
常见操作
python
undefinedpython
undefinedGet subreddit posts
获取子版块帖子
subreddit = reddit.subreddit("python")
subreddit = reddit.subreddit("python")
Hot posts
热门帖子
for post in subreddit.hot(limit=10):
print(f"{post.title} - {post.score} upvotes")
for post in subreddit.hot(limit=10):
print(f"{post.title} - {post.score} 赞")
New posts
最新帖子
for post in subreddit.new(limit=10):
print(post.title)
for post in subreddit.new(limit=10):
print(post.title)
Search posts
搜索帖子
for post in subreddit.search("pydantic", limit=5):
print(post.title)
for post in subreddit.search("pydantic", limit=5):
print(post.title)
Get specific post
获取特定帖子
submission = reddit.submission(id="abc123")
print(submission.title)
print(submission.selftext)
submission = reddit.submission(id="abc123")
print(submission.title)
print(submission.selftext)
Get comments
获取评论
submission.comments.replace_more(limit=0) # Flatten comment tree
for comment in submission.comments.list():
print(f"{comment.author}: {comment.body[:100]}")
undefinedsubmission.comments.replace_more(limit=0) # 扁平化评论树
for comment in submission.comments.list():
print(f"{comment.author}: {comment.body[:100]}")
undefinedPosting & Voting (Requires Auth)
发帖与投票(需要认证)
python
undefinedpython
undefinedSubmit text post
提交文字帖子
subreddit = reddit.subreddit("test")
submission = subreddit.submit(
title="Test Post",
selftext="This is the body of my post."
)
subreddit = reddit.subreddit("test")
submission = subreddit.submit(
title="Test Post",
selftext="This is the body of my post."
)
Submit link post
提交链接帖子
submission = subreddit.submit(
title="Check this out",
url="https://example.com"
)
submission = subreddit.submit(
title="Check this out",
url="https://example.com"
)
Vote
投票
submission.upvote()
submission.downvote()
submission.clear_vote()
submission.upvote()
submission.downvote()
submission.clear_vote()
Comment
评论
submission.reply("Great post!")
submission.reply("Great post!")
Reply to comment
回复评论
comment = reddit.comment(id="xyz789")
comment.reply("I agree!")
undefinedcomment = reddit.comment(id="xyz789")
comment.reply("I agree!")
undefinedStreaming (Real-time)
流处理(实时)
python
undefinedpython
undefinedStream new posts
流处理新帖子
for post in reddit.subreddit("python").stream.submissions():
print(f"New post: {post.title}")
# Process post...
for post in reddit.subreddit("python").stream.submissions():
print(f"新帖子:{post.title}")
# 处理帖子...
Stream new comments
流处理新评论
for comment in reddit.subreddit("python").stream.comments():
print(f"New comment by {comment.author}: {comment.body[:50]}")
undefinedfor comment in reddit.subreddit("python").stream.comments():
print(f"{comment.author}的新评论:{comment.body[:50]}")
undefinedUser Data
用户数据
python
undefinedpython
undefinedGet user info
获取用户信息
user = reddit.redditor("spez")
print(f"Karma: {user.link_karma + user.comment_karma}")
user = reddit.redditor("spez")
print(f"总 karma:{user.link_karma + user.comment_karma}")
User's posts
用户的帖子
for post in user.submissions.new(limit=5):
print(post.title)
for post in user.submissions.new(limit=5):
print(post.title)
User's comments
用户的评论
for comment in user.comments.new(limit=5):
print(comment.body[:100])
---for comment in user.comments.new(limit=5):
print(comment.body[:100])
---TypeScript / Node.js: Snoowrap
TypeScript / Node.js:Snoowrap
Installation
安装
bash
npm install snoowrapbash
npm install snoowrapor
或
pnpm add snoowrap
undefinedpnpm add snoowrap
undefinedSetup
设置
typescript
import Snoowrap from "snoowrap";
const reddit = new Snoowrap({
userAgent: "YourApp/1.0 by YourUsername",
clientId: process.env.REDDIT_CLIENT_ID!,
clientSecret: process.env.REDDIT_CLIENT_SECRET!,
username: process.env.REDDIT_USERNAME!,
password: process.env.REDDIT_PASSWORD!,
});
// Configure rate limiting
reddit.config({
requestDelay: 1000, // 1 second between requests
continueAfterRatelimitError: true,
});typescript
import Snoowrap from "snoowrap";
const reddit = new Snoowrap({
userAgent: "YourApp/1.0 by YourUsername",
clientId: process.env.REDDIT_CLIENT_ID!,
clientSecret: process.env.REDDIT_CLIENT_SECRET!,
username: process.env.REDDIT_USERNAME!,
password: process.env.REDDIT_PASSWORD!,
});Common Operations
配置速率限制
typescript
// Get hot posts from subreddit
const posts = await reddit.getSubreddit("typescript").getHot({ limit: 10 });
posts.forEach((post) => {
console.log(`${post.title} - ${post.score} upvotes`);
});
// Search posts
const results = await reddit.getSubreddit("programming").search({
query: "typescript",
sort: "relevance",
time: "month",
limit: 10,
});
// Get specific post
const submission = await reddit.getSubmission("abc123").fetch();
console.log(submission.title);
// Get comments
const comments = await submission.comments.fetchAll();
comments.forEach((comment) => {
console.log(`${comment.author.name}: ${comment.body.slice(0, 100)}`);
});reddit.config({
requestDelay: 1000, # 请求间隔1秒
continueAfterRatelimitError: true,
});
undefinedPosting
常见操作
typescript
// Submit text post
const post = await reddit.getSubreddit("test").submitSelfpost({
title: "Test Post",
text: "This is the body.",
});
// Submit link
const linkPost = await reddit.getSubreddit("test").submitLink({
title: "Check this out",
url: "https://example.com",
});
// Vote and comment
await post.upvote();
await post.reply("Great post!");typescript
undefinedDirect API (No Library)
获取子版块热门帖子
Python with httpx
—
python
import httpx
import base64
from pydantic import BaseModel
class RedditClient:
def __init__(self, client_id: str, client_secret: str, user_agent: str):
self.client_id = client_id
self.client_secret = client_secret
self.user_agent = user_agent
self.access_token: str | None = None
self.client = httpx.AsyncClient()
async def authenticate(self) -> None:
"""Get application-only OAuth token."""
auth = base64.b64encode(
f"{self.client_id}:{self.client_secret}".encode()
).decode()
response = await self.client.post(
"https://www.reddit.com/api/v1/access_token",
headers={
"Authorization": f"Basic {auth}",
"User-Agent": self.user_agent,
},
data={
"grant_type": "client_credentials",
},
)
response.raise_for_status()
self.access_token = response.json()["access_token"]
async def get_posts(self, subreddit: str, sort: str = "hot", limit: int = 10) -> list[dict]:
"""Get posts from a subreddit."""
if not self.access_token:
await self.authenticate()
response = await self.client.get(
f"https://oauth.reddit.com/r/{subreddit}/{sort}",
headers={
"Authorization": f"Bearer {self.access_token}",
"User-Agent": self.user_agent,
},
params={"limit": limit},
)
response.raise_for_status()
return [post["data"] for post in response.json()["data"]["children"]]
async def close(self) -> None:
await self.client.aclose()const posts = await reddit.getSubreddit("typescript").getHot({ limit: 10 });
posts.forEach((post) => {
console.log();
});
${post.title} - ${post.score} 赞Usage
搜索帖子
async def main():
client = RedditClient(
client_id="your_id",
client_secret="your_secret",
user_agent="YourApp/1.0",
)
try:
posts = await client.get_posts("python", limit=5)
for post in posts:
print(f"{post['title']} - {post['score']} upvotes")
finally:
await client.close()
undefinedconst results = await reddit.getSubreddit("programming").search({
query: "typescript",
sort: "relevance",
time: "month",
limit: 10,
});
TypeScript with fetch
获取特定帖子
typescript
interface RedditPost {
title: string;
score: number;
url: string;
selftext: string;
author: string;
created_utc: number;
}
class RedditClient {
private accessToken: string | null = null;
constructor(
private clientId: string,
private clientSecret: string,
private userAgent: string
) {}
async authenticate(): Promise<void> {
const auth = Buffer.from(`${this.clientId}:${this.clientSecret}`).toString("base64");
const response = await fetch("https://www.reddit.com/api/v1/access_token", {
method: "POST",
headers: {
Authorization: `Basic ${auth}`,
"User-Agent": this.userAgent,
"Content-Type": "application/x-www-form-urlencoded",
},
body: "grant_type=client_credentials",
});
const data = await response.json();
this.accessToken = data.access_token;
}
async getPosts(subreddit: string, sort = "hot", limit = 10): Promise<RedditPost[]> {
if (!this.accessToken) await this.authenticate();
const response = await fetch(
`https://oauth.reddit.com/r/${subreddit}/${sort}?limit=${limit}`,
{
headers: {
Authorization: `Bearer ${this.accessToken}`,
"User-Agent": this.userAgent,
},
}
);
const data = await response.json();
return data.data.children.map((child: any) => child.data);
}
}const submission = await reddit.getSubmission("abc123").fetch();
console.log(submission.title);
OAuth2 Web Flow (User Authorization)
获取评论
For apps where users log in with their Reddit account:
python
from fastapi import FastAPI, Request
from fastapi.responses import RedirectResponse
import httpx
import secrets
app = FastAPI()
state_store: dict[str, bool] = {}
REDDIT_CLIENT_ID = "your_client_id"
REDDIT_CLIENT_SECRET = "your_client_secret"
REDIRECT_URI = "http://localhost:8000/callback"
@app.get("/login")
async def login():
state = secrets.token_urlsafe(16)
state_store[state] = True
auth_url = (
f"https://www.reddit.com/api/v1/authorize"
f"?client_id={REDDIT_CLIENT_ID}"
f"&response_type=code"
f"&state={state}"
f"&redirect_uri={REDIRECT_URI}"
f"&duration=permanent"
f"&scope=identity read submit vote"
)
return RedirectResponse(auth_url)
@app.get("/callback")
async def callback(code: str, state: str):
if state not in state_store:
return {"error": "Invalid state"}
del state_store[state]
# Exchange code for token
async with httpx.AsyncClient() as client:
response = await client.post(
"https://www.reddit.com/api/v1/access_token",
auth=(REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET),
data={
"grant_type": "authorization_code",
"code": code,
"redirect_uri": REDIRECT_URI,
},
headers={"User-Agent": "YourApp/1.0"},
)
tokens = response.json()
# Store tokens securely, associate with user session
return {"access_token": tokens["access_token"][:10] + "..."}const comments = await submission.comments.fetchAll();
comments.forEach((comment) => {
console.log();
});
${comment.author.name}: ${comment.body.slice(0, 100)}undefinedAvailable Scopes
发帖
| Scope | Description |
|---|---|
| Access username and signup date |
| Access posts and comments |
| Submit links and comments |
| Upvote/downvote content |
| Edit posts and comments |
| Access voting history |
| Manage subreddit subscriptions |
| Access subscribed subreddits |
| Access private messages |
| Save/unsave content |
Full list: https://www.reddit.com/api/v1/scopes
typescript
undefinedProject Structure
提交文字帖子
project/
├── src/
│ ├── reddit/
│ │ ├── __init__.py
│ │ ├── client.py # Reddit client wrapper
│ │ ├── models.py # Pydantic models for posts/comments
│ │ └── scraper.py # Data collection logic
│ └── main.py
├── .env
└── pyproject.tomlconst post = await reddit.getSubreddit("test").submitSelfpost({
title: "Test Post",
text: "This is the body.",
});
Pydantic Models
提交链接帖子
python
from pydantic import BaseModel
from datetime import datetime
class RedditPost(BaseModel):
id: str
title: str
author: str
subreddit: str
score: int
upvote_ratio: float
url: str
selftext: str
created_utc: datetime
num_comments: int
is_self: bool
@classmethod
def from_praw(cls, submission) -> "RedditPost":
return cls(
id=submission.id,
title=submission.title,
author=str(submission.author),
subreddit=submission.subreddit.display_name,
score=submission.score,
upvote_ratio=submission.upvote_ratio,
url=submission.url,
selftext=submission.selftext,
created_utc=datetime.fromtimestamp(submission.created_utc),
num_comments=submission.num_comments,
is_self=submission.is_self,
)
class RedditComment(BaseModel):
id: str
author: str
body: str
score: int
created_utc: datetime
parent_id: str
is_submitter: boolconst linkPost = await reddit.getSubreddit("test").submitLink({
title: "Check this out",
url: "https://example.com",
});
Anti-Patterns
投票与评论
- No User-Agent - Reddit blocks requests without proper User-Agent
- Ignoring rate limits - Respect 100 QPM, check headers
X-Ratelimit-* - Storing credentials in code - Use environment variables
- Not handling - Use
MoreCommentsin PRAWreplace_more() - Polling instead of streaming - Use for real-time data
.stream - No error handling - Handle 429 (rate limit), 403 (forbidden), 404 (not found)
await post.upvote();
await post.reply("Great post!");
---Quick Reference
直接调用API(不使用库)
—
使用httpx的Python实现
bash
undefinedpython
import httpx
import base64
from pydantic import BaseModel
class RedditClient:
def __init__(self, client_id: str, client_secret: str, user_agent: str):
self.client_id = client_id
self.client_secret = client_secret
self.user_agent = user_agent
self.access_token: str | None = None
self.client = httpx.AsyncClient()
async def authenticate(self) -> None:
"""获取应用级OAuth令牌。"""
auth = base64.b64encode(
f"{self.client_id}:{self.client_secret}".encode()
).decode()
response = await self.client.post(
"https://www.reddit.com/api/v1/access_token",
headers={
"Authorization": f"Basic {auth}",
"User-Agent": self.user_agent,
},
data={
"grant_type": "client_credentials",
},
)
response.raise_for_status()
self.access_token = response.json()["access_token"]
async def get_posts(self, subreddit: str, sort: str = "hot", limit: int = 10) -> list[dict]:
"""获取子版块的帖子。"""
if not self.access_token:
await self.authenticate()
response = await self.client.get(
f"https://oauth.reddit.com/r/{subreddit}/{sort}",
headers={
"Authorization": f"Bearer {self.access_token}",
"User-Agent": self.user_agent,
},
params={"limit": limit},
)
response.raise_for_status()
return [post["data"] for post in response.json()["data"]["children"]]
async def close(self) -> None:
await self.client.aclose()PRAW installation
使用示例
pip install praw
async def main():
client = RedditClient(
client_id="your_id",
client_secret="your_secret",
user_agent="YourApp/1.0",
)
try:
posts = await client.get_posts("python", limit=5)
for post in posts:
print(f"{post['title']} - {post['score']} 赞")
finally:
await client.close()
undefinedSnoowrap installation
使用fetch的TypeScript实现
npm install snoowrap
typescript
interface RedditPost {
title: string;
score: number;
url: string;
selftext: string;
author: string;
created_utc: number;
}
class RedditClient {
private accessToken: string | null = null;
constructor(
private clientId: string,
private clientSecret: string,
private userAgent: string
) {}
async authenticate(): Promise<void> {
const auth = Buffer.from(`${this.clientId}:${this.clientSecret}`).toString("base64");
const response = await fetch("https://www.reddit.com/api/v1/access_token", {
method: "POST",
headers: {
Authorization: `Basic ${auth}`,
"User-Agent": this.userAgent,
"Content-Type": "application/x-www-form-urlencoded",
},
body: "grant_type=client_credentials",
});
const data = await response.json();
this.accessToken = data.access_token;
}
async getPosts(subreddit: string, sort = "hot", limit = 10): Promise<RedditPost[]> {
if (!this.accessToken) await this.authenticate();
const response = await fetch(
`https://oauth.reddit.com/r/${subreddit}/${sort}?limit=${limit}`,
{
headers: {
Authorization: `Bearer ${this.accessToken}`,
"User-Agent": this.userAgent,
},
}
);
const data = await response.json();
return data.data.children.map((child: any) => child.data);
}
}Test authentication
OAuth2 Web 流程(用户授权)
python -c "import praw; r = praw.Reddit(...); print(r.user.me())"
undefined适用于用户使用Reddit账号登录的应用:
python
from fastapi import FastAPI, Request
from fastapi.responses import RedirectResponse
import httpx
import secrets
app = FastAPI()
state_store: dict[str, bool] = {}
REDDIT_CLIENT_ID = "your_client_id"
REDDIT_CLIENT_SECRET = "your_client_secret"
REDIRECT_URI = "http://localhost:8000/callback"
@app.get("/login")
async def login():
state = secrets.token_urlsafe(16)
state_store[state] = True
auth_url = (
f"https://www.reddit.com/api/v1/authorize"
f"?client_id={REDDIT_CLIENT_ID}"
f"&response_type=code"
f"&state={state}"
f"&redirect_uri={REDIRECT_URI}"
f"&duration=permanent"
f"&scope=identity read submit vote"
)
return RedirectResponse(auth_url)
@app.get("/callback")
async def callback(code: str, state: str):
if state not in state_store:
return {"error": "无效的state"}
del state_store[state]
# 交换授权码获取令牌
async with httpx.AsyncClient() as client:
response = await client.post(
"https://www.reddit.com/api/v1/access_token",
auth=(REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET),
data={
"grant_type": "authorization_code",
"code": code,
"redirect_uri": REDIRECT_URI,
},
headers={"User-Agent": "YourApp/1.0"},
)
tokens = response.json()
# 安全存储令牌,关联到用户会话
return {"access_token": tokens["access_token"][:10] + "..."}Endpoints
可用权限范围
| Operation | Endpoint |
|---|---|
| Auth token | |
| API requests | |
| Subreddit posts | |
| Submission | |
| User info | |
| Submit post | |
| Vote | |
| 权限范围 | 描述 |
|---|---|
| 访问用户名和注册日期 |
| 访问帖子和评论 |
| 提交链接和评论 |
| 点赞/点踩内容 |
| 编辑帖子和评论 |
| 访问投票历史 |
| 管理子版块订阅 |
| 访问已订阅的子版块 |
| 访问私信 |
| 保存/取消保存内容 |
—
项目结构
—
project/
├── src/
│ ├── reddit/
│ │ ├── __init__.py
│ │ ├── client.py # Reddit客户端封装
│ │ ├── models.py # 帖子/评论的Pydantic模型
│ │ └── scraper.py # 数据收集逻辑
│ └── main.py
├── .env
└── pyproject.toml—
Pydantic 模型
—
python
from pydantic import BaseModel
from datetime import datetime
class RedditPost(BaseModel):
id: str
title: str
author: str
subreddit: str
score: int
upvote_ratio: float
url: str
selftext: str
created_utc: datetime
num_comments: int
is_self: bool
@classmethod
def from_praw(cls, submission) -> "RedditPost":
return cls(
id=submission.id,
title=submission.title,
author=str(submission.author),
subreddit=submission.subreddit.display_name,
score=submission.score,
upvote_ratio=submission.upvote_ratio,
url=submission.url,
selftext=submission.selftext,
created_utc=datetime.fromtimestamp(submission.created_utc),
num_comments=submission.num_comments,
is_self=submission.is_self,
)
class RedditComment(BaseModel):
id: str
author: str
body: str
score: int
created_utc: datetime
parent_id: str
is_submitter: bool—
反模式
—
- 未设置User-Agent - Reddit会阻止没有正确User-Agent的请求
- 忽略速率限制 - 遵循100 QPM的限制,检查响应头
X-Ratelimit-* - 在代码中存储凭证 - 使用环境变量
- 未处理- 在PRAW中使用
MoreCommentsreplace_more() - 轮询而非流处理 - 使用获取实时数据
.stream - 无错误处理 - 处理429(速率限制)、403(禁止访问)、404(未找到)错误
—
快速参考
—
bash
undefined—
PRAW安装
—
pip install praw
—
Snoowrap安装
—
npm install snoowrap
—
测试认证
—
python -c "import praw; r = praw.Reddit(...); print(r.user.me())"
undefined—
端点
—
| 操作 | 端点 |
|---|---|
| 获取认证令牌 | |
| API请求 | |
| 子版块帖子 | |
| 帖子详情 | |
| 用户信息 | |
| 提交帖子 | |
| 投票 | |