Skip to content

joyway1978/TopicHub

Repository files navigation

Topic Hub - 多平台热搜聚合器

使用 Playwright 自动化浏览器抓取多个平台(微博、小红书等)热搜话题的 Python 工具。

功能特点

  • 多平台支持: 微博、小红书、百度、B站、GitHub、Hacker News 等
  • 统一数据模型: 所有平台数据格式统一,支持扩展字段
  • 多种输出方式: 控制台、JSON、CSV、SQLite 数据库
  • Web API 服务: FastAPI 提供的 RESTful API,支持查询、搜索、统计
  • 插件化架构: 新增平台只需添加一个文件
  • 自动登录管理: 支持 Cookie 持久化和自动重新登录
  • 并发抓取: 同时抓取多个平台提高效率
  • 数据缓存: 文件缓存系统,API 响应缓存 5 分钟

安装依赖

# 安装 Python 依赖
pip install -r requirements.txt

# 安装 Chromium 浏览器(只需执行一次)
python3 -m playwright install chromium

使用方法

基本用法

# 列出所有可用平台
python topic_hub.py --list

# 抓取微博热搜
python topic_hub.py weibo

# 抓取小红书热搜(需登录)
python topic_hub.py xiaohongshu

# 同时抓取多个平台
python topic_hub.py weibo xiaohongshu

# 只显示前10条
python topic_hub.py weibo -n 10

# 保存为 JSON 文件
python topic_hub.py weibo -o hot_topics.json

# 保存为 CSV 文件
python topic_hub.py weibo -o hot_topics.csv

# 保存到 SQLite 数据库
python topic_hub.py weibo --db

# 显示浏览器窗口(调试用)
python topic_hub.py weibo --visible

# 强制重新登录(用于需要登录的平台)
python topic_hub.py xiaohongshu --relogin

Web 服务

Topic Hub 提供 FastAPI 驱动的 Web 服务,支持通过 RESTful API 访问热搜数据。

启动 Web 服务

# 使用启动脚本(推荐)
./start.sh

# 或使用 uvicorn 直接启动
uvicorn web.backend.app.main:app --host 0.0.0.0 --port 8000 --reload

API 端点

端点 方法 说明
/ GET API 信息
/health GET 健康检查
/api/v1/topics GET 获取话题列表(支持分页、筛选)
/api/v1/topics/{id} GET 获取话题详情
/api/v1/topics/search/{query} GET 搜索话题
/api/v1/platforms GET 获取平台列表
/api/v1/stats GET 获取统计数据

API 文档

启动服务后访问:

使用示例

# 获取所有话题
curl http://localhost:8000/api/v1/topics/

# 获取特定平台的话题
curl http://localhost:8000/api/v1/topics/?platform=weibo

# 搜索话题
curl http://localhost:8000/api/v1/topics/search/科技

# 获取统计数据
curl http://localhost:8000/api/v1/stats

前端开发

项目包含基于 Next.js 14 的前端界面,使用 React Query 进行数据获取,Tailwind CSS 进行样式设计。

设计系统

前端遵循 DESIGN.md 中定义的设计系统:

  • 美学方向: 编辑数据感 (Editorial Data-Driven)
  • 配色: 深色模式优先,主色调 Indigo (#4F46E5)
  • 字体: Plus Jakarta Sans (标题) + Inter/Noto Sans SC (正文) + JetBrains Mono (数字)
  • 热力条: 垂直设计,高/中/低三档颜色区分

前端技术栈

  • 框架: Next.js 14 (App Router)
  • 样式: Tailwind CSS
  • 数据获取: TanStack Query (React Query)
  • 组件: 自定义组件库

开发命令

cd web/frontend

# 安装依赖
npm install

# 开发模式
npm run dev

# 构建生产版本
npm run build

Docker 部署

使用 Docker Compose(推荐)

# 启动服务
docker-compose up -d

# 查看日志
docker-compose logs -f

# 停止服务
docker-compose down

# 同时启动 CLI 定时抓取服务
docker-compose --profile cli up -d

使用 Docker 直接运行

# 构建镜像
docker build -t topic-hub .

# 运行容器
docker run -d \
  -p 8000:8000 \
  -v $(pwd)/data:/app/data \
  -e DATABASE_URL=sqlite:///data/topic_hub.db \
  --name topic-hub \
  topic-hub

环境变量

变量 默认值 说明
DATABASE_URL sqlite:///data/topic_hub.db 主数据库路径
QUEUE_URL sqlite:///data/queue/task_queue.db 任务队列数据库
CACHE_DIR data/cache 缓存目录
SCHEDULER_ENABLED true 启用定时任务
FETCH_INTERVAL_MINUTES 5 抓取间隔(分钟)
DATA_RETENTION_DAYS 30 数据保留天数

命令行参数

参数 说明 示例
platforms 要抓取的平台(可多个) weibo, xiaohongshu
-n, --number 限制显示数量 -n 20
-o, --output 输出文件路径 -o data.json
--db 保存到 SQLite 数据库 --db
--list 列出所有可用平台 --list
--visible 显示浏览器窗口 --visible
--relogin 强制重新登录 --relogin

作为模块导入使用

import asyncio
from platforms.discovery import get_spider_class

async def main():
    # 获取微博爬虫类
    WeiboSpider = get_spider_class("weibo")
    spider = WeiboSpider()

    # 抓取数据
    topics = await spider.fetch()

    for topic in topics[:10]:
        print(f"{topic.rank}. {topic.title} - {topic.hot_value}")

asyncio.run(main())

输出示例

控制台输出

============================================================
🔥 微博 (50 条话题)
============================================================
🥇 话题一标题 - 123万热度
🥈 话题二标题 - 98万热度
🥉 话题三标题 - 87万热度
4. 话题四标题 - 76万热度
5. 话题五标题 - 65万热度
...
============================================================

JSON 输出格式

{
  "fetch_time": "2026-03-21T14:30:25",
  "count": 50,
  "topics": [
    {
      "id": "weibo_1",
      "platform": "weibo",
      "rank": 1,
      "title": "话题标题",
      "hot_value": "123万热度",
      "url": "https://s.weibo.com/weibo?q=...",
      "category": null,
      "created_at": "2026-03-21T14:30:25",
      "extra": {}
    }
  ]
}

项目结构

.
├── topic_hub.py           # 主入口
├── cli/                   # CLI 模块
│   ├── commands/         # 子命令实现
│   ├── formatters.py     # 输出格式化
│   └── main.py           # CLI 入口
├── core/                  # 核心框架
│   ├── base.py           # BaseSpider 抽象基类
│   ├── models.py         # HotTopic 数据模型 (SQLAlchemy)
│   ├── database.py       # 数据库配置
│   ├── storage.py        # StorageManager 存储管理
│   ├── auth.py           # AuthManager 认证管理
│   ├── cache.py          # FileCache 文件缓存
│   ├── queue.py          # SQLiteQueue 任务队列
│   ├── browser_pool.py   # 浏览器连接池
│   └── context.py        # PlaywrightContext 浏览器上下文
├── platforms/             # 平台实现
│   ├── weibo.py          # 微博爬虫
│   ├── xiaohongshu.py    # 小红书爬虫
│   ├── baidu.py          # 百度热搜爬虫
│   ├── bilibili.py       # B站热门爬虫
│   ├── github.py         # GitHub Trending 爬虫
│   ├── hackernews.py     # Hacker News 爬虫
│   └── discovery.py      # 平台自动发现
├── web/                   # Web 服务
│   ├── backend/          # FastAPI 后端
│   │   └── app/
│   │       ├── main.py       # FastAPI 应用入口
│   │       ├── config.py     # 配置管理
│   │       ├── dependencies.py # 依赖注入
│   │       ├── scheduler.py  # 定时任务
│   │       ├── schemas.py    # Pydantic 模型
│   │       └── api/v1/       # API 路由
│   └── frontend/         # Next.js 前端
│       ├── src/          # 源代码
│       │   ├── app/      # 页面组件
│       │   ├── components/  # UI 组件
│       │   └── lib/      # 工具函数
│       └── public/       # 静态资源
├── data/                  # 数据目录
│   ├── topic_hub.db      # SQLite 数据库
│   ├── queue/            # 任务队列数据
│   ├── cache/            # 缓存文件
│   └── cookies/          # Cookie 存储
├── tests/                 # 测试目录
├── requirements.txt       # 依赖列表
├── Dockerfile            # Docker 镜像
├── docker-compose.yml    # Docker Compose 配置
├── start.sh              # 启动脚本
├── README.md             # 使用说明
├── CLAUDE.md             # 开发指南
├── DESIGN.md             # 设计系统
└── TODOS.md              # 待办事项

添加新平台

要添加新的平台支持,只需在 platforms/ 目录下创建一个新文件:

# platforms/douyin.py
"""Douyin hot topics spider"""

from typing import List, Dict, Any
from playwright.async_api import Page
from core.base import BaseSpider
from core.models import HotTopic

class DouyinSpider(BaseSpider):
    name = "douyin"
    display_name = "抖音"
    requires_login = False
    default_url = "https://www.douyin.com/..."

    async def extract(self, page: Page) -> List[Dict[str, Any]]:
        # 提取原始数据
        pass

    def parse(self, raw_items: List[Dict[str, Any]]) -> List[HotTopic]:
        # 解析为 HotTopic
        pass

新平台会自动被发现,无需修改核心代码。

注意事项

  1. 网络要求:需要能够访问目标平台网站
  2. 反爬机制:平台可能有反爬虫机制,如遇到失败可稍后重试
  3. 频率限制:建议每次调用间隔至少 30 秒
  4. 登录要求:小红书等平台需要登录,首次使用会弹出浏览器窗口

测试

# 运行所有单元测试
python -m pytest tests/ -v

# 运行单元测试(跳过集成测试)
python -m pytest tests/ -v -m "not integration"

# 生成代码覆盖率报告
python -m pytest tests/ -m "not integration" --cov=core --cov=platforms

免责声明

本工具仅供学习研究使用,请勿用于商业用途或高频抓取。请遵守各平台的相关使用条款和 robots.txt 规定。

About

TopicHub

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors