Просмотр исходного кода

v3.5.0: 新增了一些功能,详细见【更新日志】

sansan 5 месяцев назад
Родитель
Сommit
e6b95ada77
13 измененных файлов с 2630 добавлено и 398 удалено
  1. 84 9
      .github/workflows/docker.yml
  2. 863 64
      README-EN.md
  3. 844 73
      README.md
  4. 27 9
      config/config.yaml
  5. 35 9
      docker/.env
  6. 18 19
      docker/Dockerfile
  7. 23 0
      docker/Dockerfile.mcp
  8. 26 0
      docker/docker-compose-build.yml
  9. 24 0
      docker/docker-compose.yml
  10. 7 1
      docker/entrypoint.sh
  11. 167 14
      docker/manage.py
  12. 511 199
      main.py
  13. 1 1
      version

+ 84 - 9
.github/workflows/docker.yml

@@ -1,17 +1,33 @@
-name: Build and Push Multi-Arch Docker Images
+name: Build and Push Docker Images
 
 
 on:
 on:
   push:
   push:
-    tags: ["v*"]
+    tags:
+      - "v*" # 主项目版本
+      - "mcp-v*" # MCP 版本
   workflow_dispatch:
   workflow_dispatch:
+    inputs:
+      image:
+        description: "选择要构建的镜像"
+        required: true
+        default: "all"
+        type: choice
+        options:
+          - all
+          - crawler
+          - mcp
 
 
 env:
 env:
   REGISTRY: docker.io
   REGISTRY: docker.io
-  IMAGE_NAME: wantcat/trendradar
 
 
 jobs:
 jobs:
-  build:
+  build-crawler:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
+    # 条件:v* 标签(排除 mcp-v*)或手动触发选择 all/crawler
+    if: |
+      (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && !startsWith(github.ref, 'refs/tags/mcp-v')) ||
+      (github.event_name == 'workflow_dispatch' && (github.event.inputs.image == 'all' || github.event.inputs.image == 'crawler'))
+
     steps:
     steps:
       - name: Checkout
       - name: Checkout
         uses: actions/checkout@v4
         uses: actions/checkout@v4
@@ -35,12 +51,11 @@ jobs:
         id: meta
         id: meta
         uses: docker/metadata-action@v5
         uses: docker/metadata-action@v5
         with:
         with:
-          images: ${{ env.IMAGE_NAME }}
+          images: wantcat/trendradar
           tags: |
           tags: |
-            type=ref,event=branch
             type=semver,pattern={{version}}
             type=semver,pattern={{version}}
             type=semver,pattern={{major}}.{{minor}}
             type=semver,pattern={{major}}.{{minor}}
-            type=raw,value=latest,enable={{is_default_branch}}
+            type=raw,value=latest
 
 
       - name: Build and push
       - name: Build and push
         uses: docker/build-push-action@v5
         uses: docker/build-push-action@v5
@@ -55,5 +70,65 @@ jobs:
           labels: ${{ steps.meta.outputs.labels }}
           labels: ${{ steps.meta.outputs.labels }}
           cache-from: type=gha
           cache-from: type=gha
           cache-to: type=gha,mode=max
           cache-to: type=gha,mode=max
-          build-args: |
-            BUILDKIT_INLINE_CACHE=1
+
+  build-mcp:
+    runs-on: ubuntu-latest
+    # 条件:mcp-v* 标签 或手动触发选择 all/mcp
+    if: |
+      (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/mcp-v')) ||
+      (github.event_name == 'workflow_dispatch' && (github.event.inputs.image == 'all' || github.event.inputs.image == 'mcp'))
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+
+      - name: Set up QEMU
+        uses: docker/setup-qemu-action@v3
+
+      - name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v3
+        with:
+          driver-opts: |
+            network=host
+
+      - name: Login to Docker Hub
+        uses: docker/login-action@v3
+        with:
+          username: ${{ secrets.DOCKERHUB_USERNAME }}
+          password: ${{ secrets.DOCKERHUB_TOKEN }}
+
+      - name: Extract version from tag
+        id: version
+        run: |
+          if [[ "${{ github.ref }}" == refs/tags/mcp-v* ]]; then
+            VERSION="${GITHUB_REF#refs/tags/mcp-v}"
+            echo "version=${VERSION}" >> $GITHUB_OUTPUT
+            echo "major_minor=$(echo $VERSION | cut -d. -f1,2)" >> $GITHUB_OUTPUT
+          else
+            echo "version=latest" >> $GITHUB_OUTPUT
+            echo "major_minor=latest" >> $GITHUB_OUTPUT
+          fi
+
+      - name: Extract metadata
+        id: meta
+        uses: docker/metadata-action@v5
+        with:
+          images: wantcat/trendradar-mcp
+          tags: |
+            type=raw,value=${{ steps.version.outputs.version }}
+            type=raw,value=${{ steps.version.outputs.major_minor }}
+            type=raw,value=latest
+
+      - name: Build and push
+        uses: docker/build-push-action@v5
+        env:
+          BUILDKIT_PROGRESS: plain
+        with:
+          context: .
+          file: ./docker/Dockerfile.mcp
+          platforms: linux/amd64,linux/arm64
+          push: true
+          tags: ${{ steps.meta.outputs.tags }}
+          labels: ${{ steps.meta.outputs.labels }}
+          cache-from: type=gha
+          cache-to: type=gha,mode=max

+ 863 - 64
README-EN.md

@@ -4,7 +4,7 @@
   <img src="/_image/banner.webp" alt="TrendRadar Banner" width="80%">
   <img src="/_image/banner.webp" alt="TrendRadar Banner" width="80%">
 </a>
 </a>
 
 
-🚀 Deploy in <strong>30 seconds</strong> — Your Smart Trending News Assistant
+🚀 Deploy in <strong>30 seconds</strong> — Say goodbye to endless scrolling, only see the news you truly care about
 
 
 <a href="https://trendshift.io/repositories/14726" target="_blank"><img src="https://trendshift.io/api/badge/repositories/14726" alt="sansan0%2FTrendRadar | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
 <a href="https://trendshift.io/repositories/14726" target="_blank"><img src="https://trendshift.io/api/badge/repositories/14726" alt="sansan0%2FTrendRadar | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
 
 
@@ -14,7 +14,7 @@
 [![GitHub Stars](https://img.shields.io/github/stars/sansan0/TrendRadar?style=flat-square&logo=github&color=yellow)](https://github.com/sansan0/TrendRadar/stargazers)
 [![GitHub Stars](https://img.shields.io/github/stars/sansan0/TrendRadar?style=flat-square&logo=github&color=yellow)](https://github.com/sansan0/TrendRadar/stargazers)
 [![GitHub Forks](https://img.shields.io/github/forks/sansan0/TrendRadar?style=flat-square&logo=github&color=blue)](https://github.com/sansan0/TrendRadar/network/members)
 [![GitHub Forks](https://img.shields.io/github/forks/sansan0/TrendRadar?style=flat-square&logo=github&color=blue)](https://github.com/sansan0/TrendRadar/network/members)
 [![License](https://img.shields.io/badge/license-GPL--3.0-blue.svg?style=flat-square)](LICENSE)
 [![License](https://img.shields.io/badge/license-GPL--3.0-blue.svg?style=flat-square)](LICENSE)
-[![Version](https://img.shields.io/badge/version-v3.4.1-blue.svg)](https://github.com/sansan0/TrendRadar)
+[![Version](https://img.shields.io/badge/version-v3.5.0-blue.svg)](https://github.com/sansan0/TrendRadar)
 [![MCP](https://img.shields.io/badge/MCP-v1.0.3-green.svg)](https://github.com/sansan0/TrendRadar)
 [![MCP](https://img.shields.io/badge/MCP-v1.0.3-green.svg)](https://github.com/sansan0/TrendRadar)
 
 
 [![WeWork](https://img.shields.io/badge/WeWork-Notification-00D4AA?style=flat-square)](https://work.weixin.qq.com/)
 [![WeWork](https://img.shields.io/badge/WeWork-Notification-00D4AA?style=flat-square)](https://work.weixin.qq.com/)
@@ -44,6 +44,34 @@
 
 
 > This project is designed to be lightweight and easy to deploy
 > This project is designed to be lightweight and easy to deploy
 
 
+<details>
+<summary>⚠️ Click to expand: <strong>Fork Guide: Docs, Resource Limits & Deployment Options</strong></summary>
+<br>
+
+**📄 Documentation Version:**
+
+If you use this project via **Fork**, you might be viewing outdated documentation. Fork copies the documentation version at that time, but the original project may have been updated.
+
+**👉 [Click to View Latest Official Documentation](https://github.com/sansan0/TrendRadar?tab=readme-ov-file)**
+
+**How to Tell?** Check the repository address at the top of the page:
+- `github.com/your-username/TrendRadar` ← Your forked version
+- `github.com/sansan0/TrendRadar` ← Latest official version
+
+---
+
+**🛡️ Resource Limits & Safety Tips:**
+
+GitHub provides limited Actions resources per account. To avoid being flagged for abuse and risking account suspension:
+
+- **Platform Count**: Keep it around **10 platforms** — more platforms consume more resources
+- **Run Frequency**: Minimum interval of **30 minutes** — more frequent runs are unnecessary
+- **Fair Use**: GitHub Actions is designed for lightweight scheduled tasks, not high-frequency crawlers
+
+💡 **Want more freedom?** Try [🐳 Docker Deployment](#6-docker-deployment) on your own server with no restrictions.
+
+</details>
+
 <br>
 <br>
 
 
 ## 📑 Quick Navigation
 ## 📑 Quick Navigation
@@ -156,23 +184,25 @@ Default monitoring of 11 mainstream platforms, with support for adding custom pl
 >
 >
 > For detailed comparison and configuration, see [Configuration Guide - Push Mode Details](#3-push-mode-details)
 > For detailed comparison and configuration, see [Configuration Guide - Push Mode Details](#3-push-mode-details)
 
 
-**Additional Feature - Push Time Window Control** (Optional):
+**Additional Features** (Optional):
 
 
-- Set push time range (e.g., 09:00-18:00), push only within specified time
-- Configure multiple pushes within window or once per day
-- Avoid notifications during non-work hours
+| Feature | Description | Default |
+|---------|-------------|---------|
+| **Push Time Window Control** | Set push time range (e.g., 09:00-18:00) to avoid non-work hours notifications | Disabled |
+| **Content Order Configuration** | Adjust display order of "Trending Keywords Stats" and "New Trending News" (v3.5.0 new) | Stats first |
 
 
-> 💡 This feature is disabled by default, see [Quick Start](#-quick-start) for configuration
+> 💡 For detailed configuration, see [Configuration Guide - Report Configuration](#7-report-configuration) and [Configuration Guide - Push Window](#8-push-window-configuration)
 
 
 ### **Precise Content Filtering**
 ### **Precise Content Filtering**
 
 
 Set personal keywords (e.g., AI, BYD, Education Policy) to receive only relevant trending news, filtering out noise.
 Set personal keywords (e.g., AI, BYD, Education Policy) to receive only relevant trending news, filtering out noise.
 
 
-**Basic Syntax** (4 types):
+**Basic Syntax** (5 types):
 - Normal words: Basic matching
 - Normal words: Basic matching
 - Required words `+`: Narrow scope
 - Required words `+`: Narrow scope
 - Filter words `!`: Exclude noise
 - Filter words `!`: Exclude noise
 - Count limit `@`: Control display count (v3.2.0 new)
 - Count limit `@`: Control display count (v3.2.0 new)
+- Global filter `[GLOBAL_FILTER]`: Globally exclude specified content (v3.5.0 new)
 
 
 **Advanced Features** (v3.2.0 new):
 **Advanced Features** (v3.2.0 new):
 - 🔢 **Keyword Sorting Control**: Sort by popularity or config order
 - 🔢 **Keyword Sorting Control**: Sort by popularity or config order
@@ -214,6 +244,14 @@ No longer controlled by platform algorithms, TrendRadar reorganizes all trending
 
 
 Supports **WeWork** (+ WeChat push solution), **Feishu**, **DingTalk**, **Telegram**, **Email**, **ntfy**, **Bark**, **Slack** — messages delivered directly to phone and email.
 Supports **WeWork** (+ WeChat push solution), **Feishu**, **DingTalk**, **Telegram**, **Email**, **ntfy**, **Bark**, **Slack** — messages delivered directly to phone and email.
 
 
+**📌 Multi-Account Push Notes (v3.5.0 New Feature):**
+
+- ✅ **Multi-Account Configuration Support**: All push channels (Feishu, DingTalk, WeWork, Telegram, ntfy, Bark, Slack) support configuring multiple accounts
+- ✅ **Configuration Method**: Use English semicolon `;` to separate multiple account values
+- ✅ **Example**: Set `FEISHU_WEBHOOK_URL` Secret value to `https://webhook1;https://webhook2`
+- ⚠️ **Paired Configuration**: Telegram and ntfy require paired parameter quantities to match (e.g., token and chat_id both have 2 values)
+- ⚠️ **Quantity Limit**: Default maximum 3 accounts per channel, exceeded values will be truncated
+
 ### **Multi-Platform Support**
 ### **Multi-Platform Support**
 - **GitHub Pages**: Auto-generate beautiful web reports, PC/mobile adapted
 - **GitHub Pages**: Auto-generate beautiful web reports, PC/mobile adapted
 - **Docker Deployment**: Supports multi-architecture containerized operation
 - **Docker Deployment**: Supports multi-architecture containerized operation
@@ -272,6 +310,62 @@ Transform from "algorithm recommendation captivity" to "actively getting the inf
 - **Major Version Upgrade**: Upgrading from v1.x to v2.y, recommend deleting existing fork and re-forking to save effort and avoid config conflicts
 - **Major Version Upgrade**: Upgrading from v1.x to v2.y, recommend deleting existing fork and re-forking to save effort and avoid config conflicts
 
 
 
 
+### 2025/12/03 - v3.5.0
+
+**🎉 Core Feature Enhancements**
+
+1. **Multi-Account Push Support**
+   - All push channels (Feishu, DingTalk, WeWork, Telegram, ntfy, Bark, Slack) support multiple account configuration
+   - Use semicolon `;` to separate multiple accounts, e.g., `FEISHU_WEBHOOK_URL=url1;url2`
+   - Automatic validation for paired configurations (e.g., Telegram's token and chat_id)
+
+2. **Configurable Push Content Order**
+   - Added `reverse_content_order` configuration option
+   - Customize display order of trending keywords stats and new trending news
+
+3. **Global Filter Keywords**
+   - Added `[GLOBAL_FILTER]` region marker for filtering unwanted content globally
+   - Use cases: Filter ads, marketing, low-quality content, etc.
+
+**🐳 Docker Dual-Path HTML Generation Optimization**
+
+- **Bug Fix**: Resolved issue where `index.html` could not sync to host in Docker environment
+- **Dual-Path Generation**: Daily summary HTML is generated to two locations simultaneously
+  - `index.html` (project root): For GitHub Pages access
+  - `output/index.html`: Accessible on host via Docker Volume mount
+- **Compatibility**: Ensures web reports are accessible in Docker, GitHub Actions, and local environments
+
+**🐳 Docker MCP Image Support**
+
+- Added independent MCP service image `wantcat/trendradar-mcp`
+- Supports Docker deployment of AI analysis features via HTTP interface (port 3333)
+- Dual-container architecture: News push service and MCP service run independently, can be scaled and restarted separately
+- See [Docker Deployment - MCP Service](#6-docker-deployment) for details
+
+**🌐 Web Server Support**
+
+- Added built-in web server for browser access to generated reports
+- Control via `manage.py` commands: `docker exec -it trend-radar python manage.py start_webserver`
+- Access URL: `http://localhost:8080` (port configurable)
+- Security features: Static file service, directory restriction, localhost binding
+- Supports both auto-start and manual control modes
+
+**📖 Documentation Optimization**
+
+- Added [Report Configuration](#7-report-configuration) section: report-related parameter details
+- Added [Push Window Configuration](#8-push-window-configuration) section: push_window configuration tutorial
+- Added [Execution Frequency Configuration](#9-execution-frequency-configuration) section: Cron expression explanation and common examples
+- Added [Multi-Account Push Configuration](#10-multiple-account-push-configuration) section: multi-account push configuration details
+- Optimized all configuration sections: Unified "Configuration Location" instructions
+- Simplified Quick Start configuration: Three core files at a glance
+- Optimized [Docker Deployment](#6-docker-deployment) section: Added image description, recommended git clone deployment, reorganized deployment methods
+
+**🔧 Upgrade Instructions**:
+- **GitHub Fork Users**: Update `main.py`, `config/config.yaml` (Added multi-account push support, existing single-account configuration unaffected)
+- **Docker Users**: Update `.env`, `docker-compose.yml` or set environment variables `REVERSE_CONTENT_ORDER`, `MAX_ACCOUNTS_PER_CHANNEL`
+- **Multi-Account Push**: New feature, disabled by default, existing single-account configuration unaffected
+
+
 ### 2025/11/28 - v3.4.1
 ### 2025/11/28 - v3.4.1
 
 
 **🔧 Format Optimization**
 **🔧 Format Optimization**
@@ -705,6 +799,24 @@ frequency_words.txt file added **required word** feature, using + sign
    - ⚠️ **DO NOT Create Custom Names**: The Secret Name must **strictly use** the names listed below (e.g., `WEWORK_WEBHOOK_URL`, `FEISHU_WEBHOOK_URL`, etc.). Do not modify or create new names arbitrarily, or the system will not recognize them
    - ⚠️ **DO NOT Create Custom Names**: The Secret Name must **strictly use** the names listed below (e.g., `WEWORK_WEBHOOK_URL`, `FEISHU_WEBHOOK_URL`, etc.). Do not modify or create new names arbitrarily, or the system will not recognize them
    - 💡 **Can Configure Multiple Platforms**: The system will send notifications to all configured platforms
    - 💡 **Can Configure Multiple Platforms**: The system will send notifications to all configured platforms
 
 
+   **📌 Multi-Account Push Notes (v3.5.0 New Feature):**
+
+   - ✅ **Multi-Account Configuration Support**: All push channels (Feishu, DingTalk, WeWork, Telegram, ntfy, Bark, Slack) support configuring multiple accounts
+   - ✅ **Configuration Method**: Use English semicolon `;` to separate multiple account values
+   - ✅ **Example**: Set `FEISHU_WEBHOOK_URL` Secret value to `https://webhook1;https://webhook2`
+   - ⚠️ **Paired Configuration**: Telegram and ntfy require paired parameter quantities to match (e.g., token and chat_id both have 2 values)
+   - ⚠️ **Quantity Limit**: Default maximum 3 accounts per channel, exceeded values will be truncated
+
+   **Multi-Account Configuration Examples**:
+
+   | Name | Secret (Value) Example |
+   |------|------------------------|
+   | `FEISHU_WEBHOOK_URL` | `https://webhook1;https://webhook2;https://webhook3` |
+   | `TELEGRAM_BOT_TOKEN` | `token1;token2` |
+   | `TELEGRAM_CHAT_ID` | `chatid1;chatid2` |
+   | `NTFY_TOPIC` | `topic1;topic2` |
+   | `NTFY_TOKEN` | `;token2` (1st has no token, use empty string as placeholder) |
+
    **Configuration Example:**
    **Configuration Example:**
 
 
    <img src="_image/secrets.png" alt="GitHub Secrets Configuration Example"/>
    <img src="_image/secrets.png" alt="GitHub Secrets Configuration Example"/>
@@ -1316,15 +1428,21 @@ frequency_words.txt file added **required word** feature, using + sign
    3. Click **"Run workflow"** button on the right to run
    3. Click **"Run workflow"** button on the right to run
    4. Wait about 1 minute, messages will be pushed to your configured platform
    4. Wait about 1 minute, messages will be pushed to your configured platform
 
 
+   > ⏱️ **Testing Tips**:
+   > - Don't test too frequently to avoid triggering GitHub Actions limits
+   > - After clicking Run workflow, you need to **refresh the browser page** to see the new run record
+
 4. **Configuration Notes (Optional)**:
 4. **Configuration Notes (Optional)**:
 
 
-    > 💡 Default configuration works normally, only adjust if you need personalization
+    > 💡 **Default configuration works normally**, only adjust if you need personalization, understand these three files:
 
 
-    - **Push Settings**: Configure push mode and notification options in [config/config.yaml](config/config.yaml) → [Push Mode Details](#3-push-mode-details)
-    - **Keyword Settings**: Add your interested keywords in [config/frequency_words.txt](config/frequency_words.txt) → [Keyword Configuration Tutorial](#2-keyword-configuration)
-    - **Push Frequency Adjustment**: In [.github/workflows/crawler.yml](.github/workflows/crawler.yml) adjust carefully, don't be greedy
+    | File | Purpose |
+    |------|---------|
+    | `config/config.yaml` | Main config file: push mode, time window, platform list, hotspot weights, etc. |
+    | `config/frequency_words.txt` | Keyword file: set your interested keywords, filter push content |
+    | `.github/workflows/crawler.yml` | Execution frequency: control how often to run (⚠️ modify carefully) |
 
 
-    **Note**: Suggest only adjusting explicitly documented config items, other options mainly for author's development testing
+    👉 **Detailed Configuration Tutorial**: [Configuration Guide](#configuration-guide)
 
 
 5. **🎉 Deployment Success! Share Your Experience**
 5. **🎉 Deployment Success! Share Your Experience**
 
 
@@ -1365,6 +1483,8 @@ frequency_words.txt file added **required word** feature, using + sign
 <summary>👉 Click to expand: <strong>Custom Monitoring Platforms</strong></summary>
 <summary>👉 Click to expand: <strong>Custom Monitoring Platforms</strong></summary>
 <br>
 <br>
 
 
+**Configuration Location:** `platforms` section in `config/config.yaml`
+
 This project's news data comes from [newsnow](https://github.com/ourongxing/newsnow). You can click the [website](https://newsnow.busiyi.world/), click [More], to see if there are platforms you want.
 This project's news data comes from [newsnow](https://github.com/ourongxing/newsnow). You can click the [website](https://newsnow.busiyi.world/), click [More], to see if there are platforms you want.
 
 
 For specific additions, visit [project source code](https://github.com/ourongxing/newsnow/tree/main/server/sources), based on the file names there, modify the `platforms` configuration in `config/config.yaml` file:
 For specific additions, visit [project source code](https://github.com/ourongxing/newsnow/tree/main/server/sources), based on the file names there, modify the `platforms` configuration in `config/config.yaml` file:
@@ -1379,13 +1499,18 @@ platforms:
     name: "Wallstreetcn"
     name: "Wallstreetcn"
   # Add more platforms...
   # Add more platforms...
 ```
 ```
-If you don't know how to look, you can directly copy the partially organized [Platform Configuration](https://github.com/sansan0/TrendRadar/issues/95)
+
+> 💡 **Shortcut**: If you don't know how to read source code, you can copy from others' organized [Platform Configuration Summary](https://github.com/sansan0/TrendRadar/issues/95)
+
+> ⚠️ **Note**: More platforms is not always better, suggest choosing 10-15 core platforms. Too many platforms will cause information overload and actually reduce user experience.
 
 
 </details>
 </details>
 
 
 ### 2. Keyword Configuration
 ### 2. Keyword Configuration
 
 
-Configure monitoring keywords in `frequency_words.txt` with four syntax types and grouping features.
+**Configuration Location:** `config/frequency_words.txt`
+
+Configure monitoring keywords in `frequency_words.txt` with five syntax types, region markers, and grouping features.
 
 
 | Syntax Type | Symbol | Purpose | Example | Matching Logic |
 | Syntax Type | Symbol | Purpose | Example | Matching Logic |
 |------------|--------|---------|---------|----------------|
 |------------|--------|---------|---------|----------------|
@@ -1393,6 +1518,7 @@ Configure monitoring keywords in `frequency_words.txt` with four syntax types an
 | **Required** | `+` | Scope limiting | `+phone` | Must include both |
 | **Required** | `+` | Scope limiting | `+phone` | Must include both |
 | **Filter** | `!` | Noise exclusion | `!ad` | Exclude if included |
 | **Filter** | `!` | Noise exclusion | `!ad` | Exclude if included |
 | **Count Limit** | `@` | Control display count | `@10` | Max 10 news (v3.2.0 new) |
 | **Count Limit** | `@` | Control display count | `@10` | Max 10 news (v3.2.0 new) |
+| **Global Filter** | `[GLOBAL_FILTER]` | Globally exclude content | See example below | Filter under any circumstances (v3.5.0 new) |
 
 
 #### 2.1 Basic Syntax
 #### 2.1 Basic Syntax
 
 
@@ -1437,6 +1563,55 @@ Musk
 
 
 **Priority:** `@number` > Global config > Unlimited
 **Priority:** `@number` > Global config > Unlimited
 
 
+##### 5. **Global Filter** `[GLOBAL_FILTER]` - Globally Exclude Content (v3.5.0 new)
+```txt
+[GLOBAL_FILTER]
+advertisement
+promotion
+marketing
+shocking
+clickbait
+
+[WORD_GROUPS]
+technology
+AI
+
+Huawei
+HarmonyOS
+!car
+```
+**Effect:** Filters news containing specified words under **any circumstances**, with **highest priority**
+
+**Use Cases:**
+- Filter low-quality content: shocking, clickbait, breaking news, etc.
+- Filter marketing content: advertisement, promotion, sponsorship, etc.
+- Filter specific topics: entertainment, gossip (based on needs)
+
+**Filter Priority:** Global Filter > Group Filter(`!`) > Group Matching
+
+**Region Markers:**
+- `[GLOBAL_FILTER]`: Global filter region, words are filtered under any circumstances
+- `[WORD_GROUPS]`: Keyword groups region, maintains existing syntax (`!`, `+`, `@`)
+- If no region markers are used, all content is treated as keyword groups (backward compatible)
+
+**Matching Examples:**
+```txt
+[GLOBAL_FILTER]
+advertisement
+
+[WORD_GROUPS]
+technology
+AI
+```
+- ❌ "Advertisement: Latest tech product launch" ← Contains global filter word "advertisement", rejected
+- ✅ "Tech company launches new AI product" ← No global filter words, matches "technology" group
+- ✅ "AI technology breakthrough draws attention" ← No global filter words, matches "AI" in "technology" group
+
+**Important Notes:**
+- Use global filter words carefully to avoid over-filtering and missing valuable content
+- Recommended to keep global filter words under 5-15
+- For group-specific filtering, prioritize using group filter words (`!` prefix)
+
 ---
 ---
 
 
 #### 🔗 Group Feature - Importance of Empty Lines
 #### 🔗 Group Feature - Importance of Empty Lines
@@ -1625,6 +1800,15 @@ BYD
 <summary>👉 Click to expand: <strong>Three Push Modes Detailed Comparison</strong></summary>
 <summary>👉 Click to expand: <strong>Three Push Modes Detailed Comparison</strong></summary>
 <br>
 <br>
 
 
+**Configuration Location:** `report.mode` in `config/config.yaml`
+
+```yaml
+report:
+  mode: "daily"  # Options: "daily" | "incremental" | "current"
+```
+
+**Docker Environment Variable:** `REPORT_MODE=incremental`
+
 #### Detailed Comparison Table
 #### Detailed Comparison Table
 
 
 | Mode | Target Users | Push Timing | Display Content | Typical Use Case |
 | Mode | Target Users | Push Timing | Display Content | Typical Use Case |
@@ -1678,6 +1862,15 @@ Assume you monitor "Apple" keyword, execute once per hour:
 <summary>👉 Click to expand: <strong>Hotspot Weight Adjustment</strong></summary>
 <summary>👉 Click to expand: <strong>Hotspot Weight Adjustment</strong></summary>
 <br>
 <br>
 
 
+**Configuration Location:** `weight` section in `config/config.yaml`
+
+```yaml
+weight:
+  rank_weight: 0.6       # Ranking weight
+  frequency_weight: 0.3  # Frequency weight
+  hotness_weight: 0.1    # Hotness weight
+```
+
 Current default configuration is balanced.
 Current default configuration is balanced.
 
 
 #### Two Core Scenarios
 #### Two Core Scenarios
@@ -1775,50 +1968,33 @@ Updated: 2025-01-15 12:30:15
 <summary>👉 Click to expand: <strong>Complete Docker Deployment Guide</strong></summary>
 <summary>👉 Click to expand: <strong>Complete Docker Deployment Guide</strong></summary>
 <br>
 <br>
 
 
-#### Method 1: Quick Experience (One-Line Command)
+**Image Description:**
 
 
-**Linux/macOS System:**
-```bash
-# Create config directory and download config files
-mkdir -p config output
-wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/config/config.yaml -P config/
-wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/config/frequency_words.txt -P config/
-```
-Or **Manual Creation**:
-1. Create `config` folder in current directory
-2. Download config files:
-   - Visit https://raw.githubusercontent.com/sansan0/TrendRadar/master/config/config.yaml → Right-click "Save As" → Save to `config\config.yaml`
-   - Visit https://raw.githubusercontent.com/sansan0/TrendRadar/master/config/frequency_words.txt → Right-click "Save As" → Save to `config\frequency_words.txt`
+TrendRadar provides two independent Docker images, deploy according to your needs:
 
 
-Final directory structure should be:
-```
-current directory/
-└── config/
-    ├── config.yaml
-    └── frequency_words.txt
-```
+| Image Name | Purpose | Description |
+|---------|------|------|
+| `wantcat/trendradar` | News Push Service | Scheduled news crawling, push notifications (Required) |
+| `wantcat/trendradar-mcp` | AI Analysis Service | MCP protocol support, AI dialogue analysis (Optional) |
 
 
-```bash
-docker run -d --name trend-radar \
-  -v ./config:/app/config:ro \
-  -v ./output:/app/output \
-  -e FEISHU_WEBHOOK_URL="your feishu webhook" \
-  -e DINGTALK_WEBHOOK_URL="your dingtalk webhook" \
-  -e WEWORK_WEBHOOK_URL="your wework webhook" \
-  -e TELEGRAM_BOT_TOKEN="your telegram_bot_token" \
-  -e TELEGRAM_CHAT_ID="your telegram_chat_id" \
-  -e EMAIL_FROM="your sender email" \
-  -e EMAIL_PASSWORD="your email password or auth code" \
-  -e EMAIL_TO="recipient email" \
-  -e CRON_SCHEDULE="*/30 * * * *" \
-  -e RUN_MODE="cron" \
-  -e IMMEDIATE_RUN="true" \
-  wantcat/trendradar:latest
-```
-
-#### Method 2: Using docker-compose (Recommended)
+> 💡 **Recommendations**:
+> - Only need push functionality: Deploy `wantcat/trendradar` image only
+> - Need AI analysis: Deploy both images
+
+---
+
+#### Method 1: Using docker-compose (Recommended)
 
 
 1. **Create Project Directory and Config**:
 1. **Create Project Directory and Config**:
+
+   **Method 1-A: Using git clone (Recommended, Simplest)**
+   ```bash
+   # Clone project to local
+   git clone https://github.com/sansan0/TrendRadar.git
+   cd TrendRadar
+   ```
+
+   **Method 1-B: Using wget to download config files**
    ```bash
    ```bash
    # Create directory structure
    # Create directory structure
    mkdir -p trendradar/{config,docker}
    mkdir -p trendradar/{config,docker}
@@ -1829,11 +2005,11 @@ docker run -d --name trend-radar \
    wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/config/frequency_words.txt -P config/
    wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/config/frequency_words.txt -P config/
 
 
    # Download docker-compose config
    # Download docker-compose config
-   wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/docker/.env
-   wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/docker/docker-compose.yml
+   wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/docker/.env -P docker/
+   wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/docker/docker-compose.yml -P docker/
    ```
    ```
 
 
-Final directory structure should be:
+   > 💡 **Note**: Key directory structure required for Docker deployment:
 ```
 ```
 current directory/
 current directory/
 ├── config/
 ├── config/
@@ -1858,10 +2034,13 @@ current directory/
    | `ENABLE_CRAWLER` | `crawler.enable_crawler` | `true` / `false` | Enable crawler |
    | `ENABLE_CRAWLER` | `crawler.enable_crawler` | `true` / `false` | Enable crawler |
    | `ENABLE_NOTIFICATION` | `notification.enable_notification` | `true` / `false` | Enable notification |
    | `ENABLE_NOTIFICATION` | `notification.enable_notification` | `true` / `false` | Enable notification |
    | `REPORT_MODE` | `report.mode` | `daily` / `incremental` / `current`| Report mode |
    | `REPORT_MODE` | `report.mode` | `daily` / `incremental` / `current`| Report mode |
+   | `MAX_ACCOUNTS_PER_CHANNEL` | `notification.max_accounts_per_channel` | `3` | Maximum accounts per channel |
    | `PUSH_WINDOW_ENABLED` | `notification.push_window.enabled` | `true` / `false` | Push time window switch |
    | `PUSH_WINDOW_ENABLED` | `notification.push_window.enabled` | `true` / `false` | Push time window switch |
    | `PUSH_WINDOW_START` | `notification.push_window.time_range.start` | `08:00` | Push start time |
    | `PUSH_WINDOW_START` | `notification.push_window.time_range.start` | `08:00` | Push start time |
    | `PUSH_WINDOW_END` | `notification.push_window.time_range.end` | `22:00` | Push end time |
    | `PUSH_WINDOW_END` | `notification.push_window.time_range.end` | `22:00` | Push end time |
-   | `FEISHU_WEBHOOK_URL` | `notification.webhooks.feishu_url` | `https://...` | Feishu Webhook |
+   | `ENABLE_WEBSERVER` | - | `true` / `false` | Auto-start web server |
+   | `WEBSERVER_PORT` | - | `8080` | Web server port (default 8080) |
+   | `FEISHU_WEBHOOK_URL` | `notification.webhooks.feishu_url` | `https://...` | Feishu Webhook (supports multi-account, use `;` separator) |
 
 
    **Config Priority**: Environment Variables > config.yaml
    **Config Priority**: Environment Variables > config.yaml
 
 
@@ -1872,22 +2051,52 @@ current directory/
 
 
 
 
 3. **Start Service**:
 3. **Start Service**:
+
+   **Option A: Start All Services (Push + AI Analysis)**
    ```bash
    ```bash
-   # Pull latest image and start
+   # Pull latest images
    docker-compose pull
    docker-compose pull
+
+   # Start all services (trend-radar + trend-radar-mcp)
    docker-compose up -d
    docker-compose up -d
    ```
    ```
 
 
+   **Option B: Start News Push Service Only**
+   ```bash
+   # Start trend-radar only (scheduled crawling and push)
+   docker-compose pull trend-radar
+   docker-compose up -d trend-radar
+   ```
+
+   **Option C: Start MCP AI Analysis Service Only**
+   ```bash
+   # Start trend-radar-mcp only (AI analysis interface)
+   docker-compose pull trend-radar-mcp
+   docker-compose up -d trend-radar-mcp
+   ```
+
+   > 💡 **Tips**:
+   > - Most users only need to start `trend-radar` for news push functionality
+   > - Only start `trend-radar-mcp` when using Claude/ChatGPT for AI dialogue analysis
+   > - Both services are independent and can be flexibly combined
+
 4. **Check Running Status**:
 4. **Check Running Status**:
    ```bash
    ```bash
-   # View logs
+   # View news push service logs
    docker logs -f trend-radar
    docker logs -f trend-radar
 
 
-   # View container status
+   # View MCP AI analysis service logs
+   docker logs -f trend-radar-mcp
+
+   # View all container status
    docker ps | grep trend-radar
    docker ps | grep trend-radar
+
+   # Stop specific service
+   docker-compose stop trend-radar      # Stop push service
+   docker-compose stop trend-radar-mcp  # Stop MCP service
    ```
    ```
 
 
-#### Method 3: Local Build (Developer Option)
+#### Method 2: Local Build (Developer Option)
 
 
 If you need custom code modifications or build your own image:
 If you need custom code modifications or build your own image:
 
 
@@ -1903,17 +2112,38 @@ vim config/frequency_words.txt
 # Use build version docker-compose
 # Use build version docker-compose
 cd docker
 cd docker
 cp docker-compose-build.yml docker-compose.yml
 cp docker-compose-build.yml docker-compose.yml
+```
+
+**Build and Start Services**:
 
 
-# Build and start
+```bash
+# Option A: Build and start all services
 docker-compose build
 docker-compose build
 docker-compose up -d
 docker-compose up -d
+
+# Option B: Build and start news push service only
+docker-compose build trend-radar
+docker-compose up -d trend-radar
+
+# Option C: Build and start MCP AI analysis service only
+docker-compose build trend-radar-mcp
+docker-compose up -d trend-radar-mcp
 ```
 ```
 
 
+> 💡 **Architecture Parameter Notes**:
+> - Default builds `amd64` architecture images (suitable for most x86_64 servers)
+> - To build `arm64` architecture (Apple Silicon, Raspberry Pi, etc.), set environment variable:
+>   ```bash
+>   export DOCKER_ARCH=arm64
+>   docker-compose build
+>   ```
+
 #### Image Update
 #### Image Update
 
 
 ```bash
 ```bash
-# Method 1: Manual update
+# Method 1: Manual update (Crawler + MCP images)
 docker pull wantcat/trendradar:latest
 docker pull wantcat/trendradar:latest
+docker pull wantcat/trendradar-mcp:latest
 docker-compose down
 docker-compose down
 docker-compose up -d
 docker-compose up -d
 
 
@@ -1922,6 +2152,13 @@ docker-compose pull
 docker-compose up -d
 docker-compose up -d
 ```
 ```
 
 
+**Available Images**:
+
+| Image Name | Purpose | Description |
+|---------|------|---------|
+| `wantcat/trendradar` | News Push Service | Scheduled news crawling, push notifications |
+| `wantcat/trendradar-mcp` | MCP Service | AI analysis features (optional) |
+
 #### Service Management Commands
 #### Service Management Commands
 
 
 ```bash
 ```bash
@@ -1940,6 +2177,11 @@ docker exec -it trend-radar python manage.py config
 # Display output files
 # Display output files
 docker exec -it trend-radar python manage.py files
 docker exec -it trend-radar python manage.py files
 
 
+# Web server management (for browser access to generated reports)
+docker exec -it trend-radar python manage.py start_webserver   # Start web server
+docker exec -it trend-radar python manage.py stop_webserver    # Stop web server
+docker exec -it trend-radar python manage.py webserver_status  # Check web server status
+
 # View help info
 # View help info
 docker exec -it trend-radar python manage.py help
 docker exec -it trend-radar python manage.py help
 
 
@@ -1953,10 +2195,52 @@ docker stop trend-radar
 docker rm trend-radar
 docker rm trend-radar
 ```
 ```
 
 
+> 💡 **Web Server Notes**:
+> - After starting, access latest report at `http://localhost:8080`
+> - Access historical reports via directory navigation (e.g., `http://localhost:8080/2025年xx月xx日/`)
+> - Port can be configured in `.env` file with `WEBSERVER_PORT` parameter
+> - Auto-start: Set `ENABLE_WEBSERVER=true` in `.env`
+> - Security: Static files only, limited to output directory, localhost binding only
+
 #### Data Persistence
 #### Data Persistence
 
 
 Generated reports and data are saved in `./output` directory by default. Data persists even if container is restarted or removed.
 Generated reports and data are saved in `./output` directory by default. Data persists even if container is restarted or removed.
 
 
+**📊 Web Report Access Paths**:
+
+TrendRadar generates daily summary HTML reports to two locations simultaneously:
+
+| File Location | Access Method | Use Case |
+|--------------|---------------|----------|
+| `output/index.html` | Direct host access | **Docker Deployment** (via Volume mount, visible on host) |
+| `index.html` | Root directory access | **GitHub Pages** (repository root, auto-detected by Pages) |
+| `output/YYYY年MM月DD日/html/当日汇总.html` | Historical reports | All environments (archived by date) |
+
+**Local Access Examples**:
+```bash
+# Method 1: Via Web Server (recommended, Docker environment)
+# 1. Start web server
+docker exec -it trend-radar python manage.py start_webserver
+# 2. Access in browser
+http://localhost:8080                           # Access latest report (default index.html)
+http://localhost:8080/2025年xx月xx日/            # Access reports for specific date
+http://localhost:8080/2025年xx月xx日/html/       # Browse all HTML files for that date
+
+# Method 2: Direct file access (local environment)
+open ./output/index.html             # macOS
+start ./output/index.html            # Windows
+xdg-open ./output/index.html         # Linux
+
+# Method 3: Access historical archives
+open ./output/2025年xx月xx日/html/当日汇总.html
+```
+
+**Why two index.html files?**
+- `output/index.html`: Docker Volume mounted to host, can be opened locally
+- `index.html`: Pushed to repository by GitHub Actions, auto-deployed by GitHub Pages
+
+> 💡 **Tip**: Both files have identical content, choose either one to access.
+
 #### Troubleshooting
 #### Troubleshooting
 
 
 ```bash
 ```bash
@@ -1973,6 +2257,521 @@ docker exec -it trend-radar /bin/bash
 docker exec -it trend-radar ls -la /app/config/
 docker exec -it trend-radar ls -la /app/config/
 ```
 ```
 
 
+#### MCP Service Deployment (AI Analysis Feature)
+
+If you need to use AI analysis features, you can deploy the standalone MCP service container.
+
+**Architecture Description**:
+
+```mermaid
+flowchart TB
+    subgraph trend-radar["trend-radar"]
+        A1[Scheduled News Fetching]
+        A2[Push Notifications]
+    end
+    
+    subgraph trend-radar-mcp["trend-radar-mcp"]
+        B1[127.0.0.1:3333]
+        B2[AI Analysis API]
+    end
+    
+    subgraph shared["Shared Volume"]
+        C1["config/ (ro)"]
+        C2["output/ (ro)"]
+    end
+    
+    trend-radar --> shared
+    trend-radar-mcp --> shared
+```
+
+**Quick Start**:
+
+Use docker-compose to start both news push and MCP services:
+
+```bash
+# Download latest docker-compose.yml (includes MCP service config)
+wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/docker/docker-compose.yml
+
+# Start all services
+docker-compose up -d
+
+# Check running status
+docker ps | grep trend-radar
+```
+
+**Start MCP Service Separately**:
+
+```bash
+docker run -d --name trend-radar-mcp \
+  -p 127.0.0.1:3333:3333 \
+  -v ./config:/app/config:ro \
+  -v ./output:/app/output:ro \
+  -e TZ=Asia/Shanghai \
+  wantcat/trendradar-mcp:latest
+```
+
+**Verify Service**:
+
+```bash
+# Check if MCP service is running properly
+curl http://127.0.0.1:3333/mcp
+
+# View MCP service logs
+docker logs -f trend-radar-mcp
+```
+
+**Configure in AI Clients**:
+
+After MCP service starts, configure in Claude Desktop, Cherry Studio, Cursor, etc.:
+
+```json
+{
+  "mcpServers": {
+    "trendradar": {
+      "url": "http://127.0.0.1:3333/mcp",
+      "description": "TrendRadar News Trending Analysis"
+    }
+  }
+}
+```
+
+> 💡 **Tip**: MCP service only listens on local port (127.0.0.1) for security. For remote access, configure reverse proxy and authentication yourself.
+
+</details>
+
+### 7. Report Configuration
+
+<details>
+<summary>👉 Click to expand: <strong>Report-Related Parameter Configuration</strong></summary>
+<br>
+
+**Configuration Location:** `report` section in `config/config.yaml`
+
+```yaml
+report:
+  mode: "daily"                    # Push mode
+  rank_threshold: 5                # Ranking highlight threshold
+  sort_by_position_first: false    # Sorting priority
+  max_news_per_keyword: 0          # Maximum display count per keyword
+  reverse_content_order: false     # Content order configuration
+```
+
+#### Configuration Details
+
+| Config Item | Type | Default | Description |
+|------------|------|---------|-------------|
+| `mode` | string | `daily` | Push mode, options: `daily`/`incremental`/`current`, see [Push Mode Details](#3-push-mode-details) |
+| `rank_threshold` | int | `5` | Ranking highlight threshold, news with rank ≤ this value will be displayed in bold |
+| `sort_by_position_first` | bool | `false` | Sorting priority: `false`=sort by news count, `true`=sort by config position |
+| `max_news_per_keyword` | int | `0` | Maximum display count per keyword, `0`=unlimited |
+| `reverse_content_order` | bool | `false` | Content order: `false`=trending keywords stats first, `true`=new trending news first |
+
+#### Content Order Configuration (v3.5.0 New)
+
+Controls display order of two content sections in push messages and HTML reports:
+
+| Config Value | Display Order |
+|-------------|--------------|
+| `false` (default) | ① Trending Keywords Stats → ② New Trending News |
+| `true` | ① New Trending News → ② Trending Keywords Stats |
+
+**Use Cases:**
+- `false` (default): Suitable for users focusing on keyword match results, view categorized stats first
+- `true`: Suitable for users focusing on latest updates, prioritize viewing new trending topics
+
+**Docker Environment Variable:**
+```bash
+REVERSE_CONTENT_ORDER=true
+```
+
+#### Sorting Priority Configuration
+
+**Example Scenario:** Config order A, B, C, news count A(3), B(10), C(5)
+
+| Config Value | Display Order | Use Case |
+|-------------|--------------|----------|
+| `false` (default) | B(10) → C(5) → A(3) | Focus on popularity trends |
+| `true` | A(3) → B(10) → C(5) | Focus on personal priority |
+
+**Docker Environment Variables:**
+```bash
+SORT_BY_POSITION_FIRST=true
+MAX_NEWS_PER_KEYWORD=10
+```
+
+</details>
+
+### 8. Push Window Configuration
+
+<details>
+<summary>👉 Click to expand: <strong>Push Time Window Control Details</strong></summary>
+<br>
+
+**Configuration Location:** `notification.push_window` section in `config/config.yaml`
+
+```yaml
+notification:
+  push_window:
+    enabled: false                    # Whether to enable
+    time_range:
+      start: "20:00"                  # Start time (Beijing time)
+      end: "22:00"                    # End time (Beijing time)
+    once_per_day: true                # Push only once per day
+    push_record_retention_days: 7     # Push record retention days
+```
+
+#### Configuration Details
+
+| Config Item | Type | Default | Description |
+|------------|------|---------|-------------|
+| `enabled` | bool | `false` | Whether to enable push time window control |
+| `time_range.start` | string | `"20:00"` | Push window start time (Beijing time, HH:MM format) |
+| `time_range.end` | string | `"22:00"` | Push window end time (Beijing time, HH:MM format) |
+| `once_per_day` | bool | `true` | `true`=push only once per day within window, `false`=push every execution within window |
+| `push_record_retention_days` | int | `7` | Push record retention days (used to determine if already pushed) |
+
+#### Use Cases
+
+| Scenario | Configuration Example |
+|----------|---------------------|
+| **Working Hours Push** | `start: "09:00"`, `end: "18:00"`, `once_per_day: false` |
+| **Evening Summary Push** | `start: "20:00"`, `end: "22:00"`, `once_per_day: true` |
+| **Lunch Break Push** | `start: "12:00"`, `end: "13:00"`, `once_per_day: true` |
+
+#### Important Notice
+
+> ⚠️ **GitHub Actions Users Note:**
+> - GitHub Actions execution time is unstable, may have ±15 minutes deviation
+> - Time range should be at least **2 hours** wide
+> - For precise timed push, recommend **Docker deployment** on personal server
+
+#### Docker Environment Variables
+
+```bash
+PUSH_WINDOW_ENABLED=true
+PUSH_WINDOW_START=09:00
+PUSH_WINDOW_END=18:00
+PUSH_WINDOW_ONCE_PER_DAY=false
+PUSH_WINDOW_RETENTION_DAYS=7
+```
+
+#### Complete Configuration Examples
+
+**Scenario: Push once between 8-10 PM daily**
+
+```yaml
+notification:
+  push_window:
+    enabled: true
+    time_range:
+      start: "20:00"
+      end: "22:00"
+    once_per_day: true
+    push_record_retention_days: 7
+```
+
+**Scenario: Push every hour during working hours**
+
+```yaml
+notification:
+  push_window:
+    enabled: true
+    time_range:
+      start: "09:00"
+      end: "18:00"
+    once_per_day: false
+    push_record_retention_days: 7
+```
+
+</details>
+
+### 9. Execution Frequency Configuration
+
+<details>
+<summary>👉 Click to expand: <strong>Automatic Execution Frequency Settings</strong></summary>
+<br>
+
+**Configuration Location:** `schedule` section in `.github/workflows/crawler.yml`
+
+```yaml
+on:
+  schedule:
+    - cron: "0 * * * *"  # Run every hour
+```
+
+#### What is a Cron Expression?
+
+Cron is a time-based job scheduler format, consisting of 5 parts: `minute hour day month weekday`
+
+```
+┌───────────── minute (0-59)
+│ ┌───────────── hour (0-23)
+│ │ ┌───────────── day (1-31)
+│ │ │ ┌───────────── month (1-12)
+│ │ │ │ ┌───────────── weekday (0-6, 0=Sunday)
+│ │ │ │ │
+* * * * *
+```
+
+#### Common Configuration Examples
+
+| Desired Effect | Cron Expression | Description |
+|---------------|----------------|-------------|
+| Every hour | `0 * * * *` | Run at minute 0 of every hour (default) |
+| Every 30 minutes | `*/30 * * * *` | Run every 30 minutes |
+| Daily at 8 AM | `0 0 * * *` | UTC 0:00 = Beijing 8:00 AM |
+| Working hours | `*/30 0-14 * * *` | Beijing 8:00-22:00, every 30 minutes |
+| 3 times daily | `0 0,6,12 * * *` | Beijing 8:00, 14:00, 20:00 |
+
+#### Important Notes
+
+> ⚠️ **Time Zone Note**: GitHub Actions uses **UTC time**, Beijing time needs to **subtract 8 hours**
+> - Want Beijing 8:00 AM run → Set UTC 0:00
+> - Want Beijing 8:00 PM run → Set UTC 12:00
+
+> ⚠️ **Frequency Limit**: GitHub has a limit on Actions execution count per account
+> - **Recommendation**: Don't set intervals shorter than 30 minutes
+> - **Reason**: Too frequent may be considered abuse, facing account ban risk
+> - **Reality**: GitHub Actions execution time has inherent deviation, setting too precise is meaningless
+
+#### Modification Method
+
+1. Open your forked repository
+2. Find `.github/workflows/crawler.yml` file
+3. Click edit (pencil icon)
+4. Modify the expression in `cron: "0 * * * *"`
+5. Click "Commit changes" to save
+
+</details>
+
+### 10. Multiple Account Push Configuration
+
+<details>
+<summary>👉 Click to expand: <strong>Multiple Account Push Configuration Guide</strong></summary>
+<br>
+
+**Configuration Location:** `notification` section in `config/config.yaml`
+
+> ### ⚠️ **Security Warning**
+> **GitHub Fork Users: DO NOT configure push information in `config.yaml`!**
+>
+> - **Risk**: `config.yaml` will be committed to public Git repositories. Configuring push information (Webhook URLs, Tokens, etc.) will expose sensitive data
+> - **Recommended Methods**:
+>   - **GitHub Actions Users** → Use GitHub Secrets environment variables
+>   - **Docker Users** → Use [`.env` file configuration](#6-docker-deployment) (`.env` is in `.gitignore` and won't be committed)
+> - **Local Development Users**: Can configure in `config.yaml` (ensure it won't be pushed to public repositories)
+
+#### Supported Channels
+
+| Channel | Configuration Item | Pairing Required | Description |
+|---------|-------------------|-----------------|-------------|
+| **Feishu** | `feishu_url` | No | Multiple webhook URLs |
+| **DingTalk** | `dingtalk_url` | No | Multiple webhook URLs |
+| **WeWork** | `wework_url` | No | Multiple webhook URLs |
+| **Telegram** | `telegram_bot_token` + `telegram_chat_id` | ✅ Yes | Token and chat_id quantities must match |
+| **ntfy** | `ntfy_topic` + `ntfy_token` | ✅ Yes | Topic and token quantities must match (token optional) |
+| **Bark** | `bark_url` | No | Multiple push URLs |
+| **Slack** | `slack_webhook_url` | No | Multiple webhook URLs |
+| **Email** | `email_to` | - | Already supports multiple recipients (comma-separated), no modification needed |
+
+#### Recommended Method 1: GitHub Actions Environment Variables
+
+**Configuration Location**: GitHub Repo → Settings → Secrets and variables → Actions → Repository secrets
+
+**Basic Configuration Example**:
+```bash
+# Multi-account quantity limit
+MAX_ACCOUNTS_PER_CHANNEL=3
+
+# Feishu multi-account (3 groups)
+FEISHU_WEBHOOK_URL=https://hook1.feishu.cn/xxx;https://hook2.feishu.cn/yyy;https://hook3.feishu.cn/zzz
+
+# DingTalk multi-account (2 groups)
+DINGTALK_WEBHOOK_URL=https://oapi.dingtalk.com/xxx;https://oapi.dingtalk.com/yyy
+
+# WeWork multi-account (2 groups)
+WEWORK_WEBHOOK_URL=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx;https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=yyy
+
+# Bark multi-account (2 devices)
+BARK_URL=https://api.day.app/key1;https://api.day.app/key2
+
+# Slack multi-account (2 channels)
+SLACK_WEBHOOK_URL=https://hooks.slack.com/xxx;https://hooks.slack.com/yyy
+```
+
+**Paired Configuration Examples (Telegram and ntfy)**:
+
+<details>
+<summary><strong>Telegram Paired Configuration</strong></summary>
+
+```bash
+# ✅ Correct: 2 tokens correspond to 2 chat_ids
+TELEGRAM_BOT_TOKEN=123456:AAA-BBB;789012:CCC-DDD
+TELEGRAM_CHAT_ID=-100111;-100222
+
+# ❌ Incorrect: quantities don't match, push will be skipped
+TELEGRAM_BOT_TOKEN=token1;token2;token3
+TELEGRAM_CHAT_ID=id1;id2
+```
+
+**Note**: The quantities of `token` and `chat_id` must match exactly, otherwise the channel push will be skipped.
+
+</details>
+
+<details>
+<summary><strong>ntfy Paired Configuration</strong></summary>
+
+```bash
+# ✅ Correct: 3 topics, only the 2nd needs a token
+NTFY_TOPIC=topic1;topic2;topic3
+NTFY_TOKEN=;token_for_topic2;
+
+# ✅ Correct: 2 topics both need tokens
+NTFY_TOPIC=topic1;topic2
+NTFY_TOKEN=token1;token2
+
+# ❌ Incorrect: topic and token quantities don't match
+NTFY_TOPIC=topic1;topic2
+NTFY_TOKEN=token1;token2;token3
+```
+
+**Notes**:
+- If a topic doesn't need a token, leave it empty at the corresponding position (between two semicolons)
+- The quantities of `topic` and `token` must match
+
+</details>
+
+---
+
+#### Recommended Method 2: Docker Environment Variables (.env)
+
+**Configuration Location**: `docker/.env` file in project root directory
+
+**Basic Configuration Example**:
+```bash
+# Multi-account quantity limit
+MAX_ACCOUNTS_PER_CHANNEL=3
+
+# Feishu multi-account (3 groups)
+FEISHU_WEBHOOK_URL=https://hook1.feishu.cn/xxx;https://hook2.feishu.cn/yyy;https://hook3.feishu.cn/zzz
+
+# DingTalk multi-account (2 groups)
+DINGTALK_WEBHOOK_URL=https://oapi.dingtalk.com/xxx;https://oapi.dingtalk.com/yyy
+
+# WeWork multi-account (2 groups)
+WEWORK_WEBHOOK_URL=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx;https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=yyy
+
+# Bark multi-account (2 devices)
+BARK_URL=https://api.day.app/key1;https://api.day.app/key2
+
+# Slack multi-account (2 channels)
+SLACK_WEBHOOK_URL=https://hooks.slack.com/xxx;https://hooks.slack.com/yyy
+```
+
+**Paired Configuration Examples (Telegram and ntfy)**:
+
+<details>
+<summary><strong>Telegram Paired Configuration</strong></summary>
+
+```bash
+# ✅ Correct: 2 tokens correspond to 2 chat_ids
+TELEGRAM_BOT_TOKEN=123456:AAA-BBB;789012:CCC-DDD
+TELEGRAM_CHAT_ID=-100111;-100222
+
+# ❌ Incorrect: quantities don't match, push will be skipped
+TELEGRAM_BOT_TOKEN=token1;token2;token3
+TELEGRAM_CHAT_ID=id1;id2
+```
+
+**Note**: The quantities of `token` and `chat_id` must match exactly, otherwise the channel push will be skipped.
+
+</details>
+
+<details>
+<summary><strong>ntfy Paired Configuration</strong></summary>
+
+```bash
+# ✅ Correct: 3 topics, only the 2nd needs a token
+NTFY_TOPIC=topic1;topic2;topic3
+NTFY_TOKEN=;token_for_topic2;
+
+# ✅ Correct: 2 topics both need tokens
+NTFY_TOPIC=topic1;topic2
+NTFY_TOKEN=token1;token2
+
+# ❌ Incorrect: topic and token quantities don't match
+NTFY_TOPIC=topic1;topic2
+NTFY_TOKEN=token1;token2;token3
+```
+
+**Notes**:
+- If a topic doesn't need a token, leave it empty at the corresponding position (between two semicolons)
+- The quantities of `topic` and `token` must match
+
+</details>
+
+---
+
+#### Push Behavior Description
+
+1. **Independent Push**: Each account sends independently, one failure doesn't affect other accounts
+2. **Partial Success**: As long as one account sends successfully, the overall result is considered successful
+3. **Log Differentiation**: Multi-account logs show "Account 1", "Account 2", etc.
+4. **Batch Interval**: Multi-account increases total send time (each account independently calculates batch interval)
+
+---
+
+#### FAQ
+
+<details>
+<summary><strong>Q1: What happens if more than 3 accounts are configured?</strong></summary>
+<br>
+
+The system will automatically truncate to the configured maximum quantity and output warning logs. You can adjust the limit via `max_accounts_per_channel`.
+
+**⚠️ Special Note for GitHub Actions Users**:
+- **Not recommended to configure too many accounts** (suggest no more than 3), which may cause:
+  - **Trigger GitHub Actions rate limits**: Frequent network requests may be identified as abnormal behavior
+  - **Affect Workflow execution time**: Multi-account pushing will extend runtime and may exceed free quotas
+  - **Potential account risks**: Excessive use of GitHub Actions resources may affect account status
+- **Recommended Practices**:
+  - Use `max_accounts_per_channel: 3` or lower values
+  - Adjust Cron execution frequency (e.g., change from hourly to every 2-3 hours)
+  - Prioritize the most important push channels and avoid configuring too many accounts
+
+</details>
+
+<details>
+<summary><strong>Q2: Will multi-accounts affect push speed?</strong></summary>
+<br>
+
+Yes. Each account sends independently, total time = number of accounts × single account send time. Recommend controlling the number of accounts.
+
+</details>
+
+<details>
+<summary><strong>Q3: How can local development users configure in config.yaml?</strong></summary>
+<br>
+
+If you are doing local development and **will not push code to public repositories**, you can configure directly in `config/config.yaml`:
+
+```yaml
+notification:
+  enable_notification: true
+  max_accounts_per_channel: 3
+
+  webhooks:
+    feishu_url: "https://hook1.feishu.cn/xxx;https://hook2.feishu.cn/yyy"
+    telegram_bot_token: "token1;token2"
+    telegram_chat_id: "id1;id2"
+```
+
+**⚠️ Important Reminder**:
+- Ensure `config/config.yaml` is in `.gitignore` (if you will commit code)
+- Or only use in local development environment, **never commit to public repositories**
+
+</details>
+
 </details>
 </details>
 
 
 <br>
 <br>

+ 844 - 73
README.md

@@ -14,7 +14,7 @@
 [![GitHub Stars](https://img.shields.io/github/stars/sansan0/TrendRadar?style=flat-square&logo=github&color=yellow)](https://github.com/sansan0/TrendRadar/stargazers)
 [![GitHub Stars](https://img.shields.io/github/stars/sansan0/TrendRadar?style=flat-square&logo=github&color=yellow)](https://github.com/sansan0/TrendRadar/stargazers)
 [![GitHub Forks](https://img.shields.io/github/forks/sansan0/TrendRadar?style=flat-square&logo=github&color=blue)](https://github.com/sansan0/TrendRadar/network/members)
 [![GitHub Forks](https://img.shields.io/github/forks/sansan0/TrendRadar?style=flat-square&logo=github&color=blue)](https://github.com/sansan0/TrendRadar/network/members)
 [![License](https://img.shields.io/badge/license-GPL--3.0-blue.svg?style=flat-square)](LICENSE)
 [![License](https://img.shields.io/badge/license-GPL--3.0-blue.svg?style=flat-square)](LICENSE)
-[![Version](https://img.shields.io/badge/version-v3.4.1-blue.svg)](https://github.com/sansan0/TrendRadar)
+[![Version](https://img.shields.io/badge/version-v3.5.0-blue.svg)](https://github.com/sansan0/TrendRadar)
 [![MCP](https://img.shields.io/badge/MCP-v1.0.3-green.svg)](https://github.com/sansan0/TrendRadar)
 [![MCP](https://img.shields.io/badge/MCP-v1.0.3-green.svg)](https://github.com/sansan0/TrendRadar)
 
 
 [![企业微信通知](https://img.shields.io/badge/企业微信-通知-00D4AA?style=flat-square)](https://work.weixin.qq.com/)
 [![企业微信通知](https://img.shields.io/badge/企业微信-通知-00D4AA?style=flat-square)](https://work.weixin.qq.com/)
@@ -44,14 +44,12 @@
 > 本项目以轻量,易部署为目标
 > 本项目以轻量,易部署为目标
 
 
 <details>
 <details>
-<summary>⚠️ 点击展开:<strong>查看最新文档</strong>(Fork 用户必读)</summary>
+<summary>⚠️ 点击展开:<strong>Fork 须知:文档更新、资源限制与部署建议</strong></summary>
 <br>
 <br>
 
 
-最近有很多第一次接触 GitHub 的新用户使用本项目,因此特别补充这个说明。
+**📄 文档版本说明:**
 
 
-**问题**:如果你是通过 **Fork** 使用本项目,你看到的可能是旧版文档。
-
-**原因**:Fork 时会复制当时的文档版本,但原项目可能已更新。
+如果你是通过 **Fork** 使用本项目,你看到的可能是旧版文档。因为 Fork 时会复制当时的文档版本,但原项目可能已更新。
 
 
 **👉 [点击查看最新官方文档](https://github.com/sansan0/TrendRadar?tab=readme-ov-file)**
 **👉 [点击查看最新官方文档](https://github.com/sansan0/TrendRadar?tab=readme-ov-file)**
 
 
@@ -59,6 +57,18 @@
 - `github.com/你的用户名/TrendRadar` ← 你 fork 的版本
 - `github.com/你的用户名/TrendRadar` ← 你 fork 的版本
 - `github.com/sansan0/TrendRadar` ← 最新官方版本
 - `github.com/sansan0/TrendRadar` ← 最新官方版本
 
 
+---
+
+**🛡️ 资源限制与安全提示:**
+
+GitHub 为每个账号提供的 Actions 资源是有限额的。为了避免被官方判定为滥用而面临封号风险,请注意:
+
+- **监控平台数量**:建议控制在 **10 个左右**,过多平台会消耗更多资源
+- **执行频率**:建议最短间隔为 **30 分钟**,过于频繁无实际意义
+- **合理使用**:GitHub Actions 适合轻量级定时任务,而非高频爬虫
+
+💡 **想要更自由地使用?** 推荐 [🐳 Docker 部署](#6-docker-部署),在自己的服务器上运行。
+
 </details>
 </details>
 
 
 <br>
 <br>
@@ -222,23 +232,25 @@
 >
 >
 > 详细对比和配置教程见 [配置详解 - 推送模式详解](#3-推送模式详解)
 > 详细对比和配置教程见 [配置详解 - 推送模式详解](#3-推送模式详解)
 
 
-**附加功能 - 推送时间窗口控制**(可选):
+**附加功能**(可选):
 
 
-- 设定推送时间范围(如 09:00-18:00),只在指定时间内推送
-- 可配置窗口内多次推送或每天仅推送一次
-- 避免非工作时间打扰
+| 功能 | 说明 | 默认 |
+|------|------|------|
+| **推送时间窗口控制** | 设定推送时间范围(如 09:00-18:00),避免非工作时间打扰 | 关闭 |
+| **内容顺序配置** | 调整"热点词汇统计"和"新增热点新闻"的显示顺序(v3.5.0 新增) | 统计在前 |
 
 
-> 💡 此功能默认关闭,配置方法见 [快速开始](#-快速开始)
+> 💡 详细配置教程见 [配置详解 - 报告配置](#7-报告配置) 和 [配置详解 - 推送时间窗口](#8-推送时间窗口配置)
 
 
 ### **精准内容筛选**
 ### **精准内容筛选**
 
 
 设置个人关键词(如:AI、比亚迪、教育政策),只推送相关热点,过滤无关信息
 设置个人关键词(如:AI、比亚迪、教育政策),只推送相关热点,过滤无关信息
 
 
-**基础语法**(4种):
+**基础语法**(5种):
 - 普通词:基础匹配
 - 普通词:基础匹配
 - 必须词 `+`:限定范围
 - 必须词 `+`:限定范围
 - 过滤词 `!`:排除干扰
 - 过滤词 `!`:排除干扰
 - 数量限制 `@`:控制显示数量(v3.2.0 新增)
 - 数量限制 `@`:控制显示数量(v3.2.0 新增)
+- 全局过滤 `[GLOBAL_FILTER]`:全局排除指定内容(v3.5.0 新增)
 
 
 **高级功能**(v3.2.0 新增):
 **高级功能**(v3.2.0 新增):
 - 🔢 **关键词排序控制**:按热度优先 or 配置顺序优先
 - 🔢 **关键词排序控制**:按热度优先 or 配置顺序优先
@@ -279,6 +291,14 @@
 
 
 支持**企业微信**(+ 微信推送方案)、**飞书**、**钉钉**、**Telegram**、**邮件**、**ntfy**、**Bark**、**Slack**,消息直达手机和邮箱
 支持**企业微信**(+ 微信推送方案)、**飞书**、**钉钉**、**Telegram**、**邮件**、**ntfy**、**Bark**、**Slack**,消息直达手机和邮箱
 
 
+**📌 多账号推送说明(v3.5.0 新增):**
+
+- ✅ **支持多账号配置**:所有推送渠道(飞书、钉钉、企业微信、Telegram、ntfy、Bark、Slack)均支持配置多个账号
+- ✅ **配置方式**:使用英文分号 `;` 分隔多个账号值
+- ✅ **示例**:`FEISHU_WEBHOOK_URL` 的 Secret 值填写 `https://webhook1;https://webhook2`
+- ⚠️ **配对配置**:Telegram 和 ntfy 需要保证配对参数数量一致(如 token 和 chat_id 都是 2 个)
+- ⚠️ **数量限制**:默认每个渠道最多 3 个账号,超出会被截断
+
 ### **多端适配**
 ### **多端适配**
 - **GitHub Pages**:自动生成精美网页报告,PC/移动端适配
 - **GitHub Pages**:自动生成精美网页报告,PC/移动端适配
 - **Docker部署**:支持多架构容器化运行
 - **Docker部署**:支持多架构容器化运行
@@ -337,6 +357,61 @@ GitHub 一键 Fork 即可使用,无需编程基础。
 - **大版本升级**:从 v1.x 升级到 v2.y,建议删除现有 fork 后重新 fork,这样更省力且避免配置冲突
 - **大版本升级**:从 v1.x 升级到 v2.y,建议删除现有 fork 后重新 fork,这样更省力且避免配置冲突
 
 
 
 
+### 2025/12/03 - v3.5.0
+
+**🎉 核心功能增强**
+
+1. **多账号推送支持**
+   - 所有推送渠道(飞书、钉钉、企业微信、Telegram、ntfy、Bark、Slack)支持多账号配置
+   - 使用分号 `;` 分隔多个账号,例如:`FEISHU_WEBHOOK_URL=url1;url2`
+   - 自动验证配对配置(如 Telegram 的 token 和 chat_id)数量一致性
+
+2. **推送内容顺序可配置**
+   - 新增 `reverse_content_order` 配置项
+   - 支持自定义热点词汇统计与新增热点新闻的显示顺序
+
+3. **全局过滤关键词**
+   - 新增 `[GLOBAL_FILTER]` 区域标记,支持全局过滤不想看到的内容
+   - 适用场景:过滤广告、营销、低质内容等
+
+**🐳 Docker 双路径 HTML 生成优化**
+
+- **问题修复**:解决 Docker 环境下 `index.html` 无法同步到宿主机的问题
+- **双路径生成**:当日汇总 HTML 同时生成到两个位置
+  - `index.html`(项目根目录):供 GitHub Pages 访问
+  - `output/index.html`:通过 Docker Volume 挂载,宿主机可直接访问
+- **兼容性**:确保 Docker、GitHub Actions、本地运行环境均能正常访问网页版报告
+
+**🐳 Docker MCP 镜像支持**
+
+- 新增独立的 MCP 服务镜像 `wantcat/trendradar-mcp`
+- 支持 Docker 部署 AI 分析功能,通过 HTTP 接口(端口 3333)提供服务
+- 双容器架构:新闻推送服务与 MCP 服务独立运行,可分别扩展和重启
+- 详见 [Docker 部署 - MCP 服务](#6-docker-部署)
+
+**🌐 Web 服务器支持**
+
+- 新增内置 Web 服务器,支持通过浏览器访问生成的报告
+- 通过 `manage.py` 命令控制启动/停止:`docker exec -it trend-radar python manage.py start_webserver`
+- 访问地址:`http://localhost:8080`(端口可配置)
+- 安全特性:静态文件服务、目录限制、本地访问
+- 支持自动启动和手动控制两种模式
+
+**📖 文档优化**
+
+- 新增 [报告配置](#7-报告配置) 章节:report 相关参数详解
+- 新增 [推送时间窗口配置](#8-推送时间窗口配置) 章节:push_window 配置教程
+- 新增 [执行频率配置](#9-执行频率配置) 章节:Cron 表达式说明和常用示例
+- 新增 [多账号推送配置](#10-多账号推送配置) 章节:多账号推送配置详解
+- 优化各配置章节:统一添加"配置位置"说明
+- 简化快速开始配置说明:三个核心文件一目了然
+- 优化 [Docker 部署](#6-docker-部署) 章节:新增镜像说明、推荐 git clone 部署、重组部署方式
+
+**🔧 升级说明**:
+- **GitHub Fork 用户**:更新 `main.py`、`config/config.yaml`(新增多账号推送支持,无需修改现有配置)
+- **多账号推送**:新功能,默认不启用,现有单账号配置不受影响
+
+
 ### 2025/11/26 - mcp-v1.0.3
 ### 2025/11/26 - mcp-v1.0.3
 
 
   **MCP 模块更新:**
   **MCP 模块更新:**
@@ -344,6 +419,11 @@ GitHub 一键 Fork 即可使用,无需编程基础。
   - 支持自然语言日期表达式解析(本周、最近7天、上月等)
   - 支持自然语言日期表达式解析(本周、最近7天、上月等)
   - 工具总数从 13 个增加到 14 个
   - 工具总数从 13 个增加到 14 个
 
 
+
+<details>
+<summary>👉 点击展开:<strong>历史更新</strong></summary>
+
+
 ### 2025/11/28 - v3.4.1
 ### 2025/11/28 - v3.4.1
 
 
 **🔧 格式优化**
 **🔧 格式优化**
@@ -366,10 +446,6 @@ GitHub 一键 Fork 即可使用,无需编程基础。
 - **GitHub Fork 用户**:更新 `main.py`,`config.yaml`
 - **GitHub Fork 用户**:更新 `main.py`,`config.yaml`
 
 
 
 
-<details>
-<summary>👉 点击展开:<strong>历史更新</strong></summary>
-
-
 ### 2025/11/25 - v3.4.0
 ### 2025/11/25 - v3.4.0
 
 
 **🎉 新增 Slack 推送支持**
 **🎉 新增 Slack 推送支持**
@@ -760,6 +836,24 @@ frequency_words.txt 文件增加了一个【必须词】功能,使用 + 号
    - ⚠️ **严禁自创名称**:Secret 的 Name(名称)必须**严格使用**下方列出的名称(如 `WEWORK_WEBHOOK_URL`、`FEISHU_WEBHOOK_URL` 等),不能自己随意修改或创造新名称,否则系统无法识别
    - ⚠️ **严禁自创名称**:Secret 的 Name(名称)必须**严格使用**下方列出的名称(如 `WEWORK_WEBHOOK_URL`、`FEISHU_WEBHOOK_URL` 等),不能自己随意修改或创造新名称,否则系统无法识别
    - 💡 **可以同时配置多个平台**:系统会向所有配置的平台发送通知
    - 💡 **可以同时配置多个平台**:系统会向所有配置的平台发送通知
 
 
+   **📌 多账号推送说明(v3.5.0 新增):**
+
+   - ✅ **支持多账号配置**:所有推送渠道(飞书、钉钉、企业微信、Telegram、ntfy、Bark、Slack)均支持配置多个账号
+   - ✅ **配置方式**:使用英文分号 `;` 分隔多个账号值
+   - ✅ **示例**:`FEISHU_WEBHOOK_URL` 的 Secret 值填写 `https://webhook1;https://webhook2`
+   - ⚠️ **配对配置**:Telegram 和 ntfy 需要保证配对参数数量一致(如 token 和 chat_id 都是 2 个)
+   - ⚠️ **数量限制**:默认每个渠道最多 3 个账号,超出部分被截断
+
+   **多账号配置示例**:
+
+   | Name(名称) | Secret(值)示例 |
+   |-------------|-----------------|
+   | `FEISHU_WEBHOOK_URL` | `https://webhook1;https://webhook2;https://webhook3` |
+   | `TELEGRAM_BOT_TOKEN` | `token1;token2` |
+   | `TELEGRAM_CHAT_ID` | `chatid1;chatid2` |
+   | `NTFY_TOPIC` | `topic1;topic2` |
+   | `NTFY_TOKEN` | `;token2`(第一个无 token 时留空占位) |
+
    **配置示例:**
    **配置示例:**
 
 
    <img src="_image/secrets.png" alt="GitHub Secrets 配置示例"/>
    <img src="_image/secrets.png" alt="GitHub Secrets 配置示例"/>
@@ -1364,15 +1458,21 @@ frequency_words.txt 文件增加了一个【必须词】功能,使用 + 号
    3. 点击右侧的 **"Run workflow"** 按钮运行
    3. 点击右侧的 **"Run workflow"** 按钮运行
    4. 等待 1 分钟左右,消息会推送到你配置的平台
    4. 等待 1 分钟左右,消息会推送到你配置的平台
 
 
+   > ⏱️ **测试提示**:
+   > - 手动测试不要太频繁,避免触发 GitHub Actions 限制
+   > - 点击 Run workflow 后需要**刷新浏览器页面**才能看到新的运行记录
+
 4. **配置说明(可选)**:
 4. **配置说明(可选)**:
 
 
-    > 💡 默认配置已可正常使用,如需个性化调整,可参考以下选项
+    > 💡 **默认配置已可正常使用**,如需个性化调整,了解以下三个文件即可
 
 
-    - **推送设置**:在 [config/config.yaml](config/config.yaml) 中配置推送模式和通知选项 → [推送模式详解](#3-推送模式详解)
-    - **关键词设置**:在 [config/frequency_words.txt](config/frequency_words.txt) 中添加你关心的关键词 → [关键词配置教程](#2-关键词配置)
-    - **推送频率调整**:在 [.github/workflows/crawler.yml](.github/workflows/crawler.yml) 请谨慎调整,别贪心
+    | 文件 | 作用 |
+    |------|------|
+    | `config/config.yaml` | 主配置文件:推送模式、时间窗口、平台列表、热点权重等 |
+    | `config/frequency_words.txt` | 关键词文件:设置你关心的词汇,筛选推送内容 |
+    | `.github/workflows/crawler.yml` | 执行频率:控制多久运行一次(⚠️ 谨慎修改) |
 
 
-    **注意**:建议只调整文档中明确说明的配置项,其他选项主要供作者开发时测试使用
+    👉 **详细配置教程**:[配置详解](#配置详解)
 
 
 5. **🎉 部署成功!分享你的使用体验**
 5. **🎉 部署成功!分享你的使用体验**
 
 
@@ -1413,6 +1513,8 @@ frequency_words.txt 文件增加了一个【必须词】功能,使用 + 号
 <summary>👉 点击展开:<strong>自定义监控平台</strong></summary>
 <summary>👉 点击展开:<strong>自定义监控平台</strong></summary>
 <br>
 <br>
 
 
+**配置位置:** `config/config.yaml` 的 `platforms` 部分
+
 本项目的资讯数据来源于 [newsnow](https://github.com/ourongxing/newsnow) ,你可以点击[网站](https://newsnow.busiyi.world/),点击[更多],查看是否有你想要的平台。
 本项目的资讯数据来源于 [newsnow](https://github.com/ourongxing/newsnow) ,你可以点击[网站](https://newsnow.busiyi.world/),点击[更多],查看是否有你想要的平台。
 
 
 具体添加可访问 [项目源代码](https://github.com/ourongxing/newsnow/tree/main/server/sources),根据里面的文件名,在 `config/config.yaml` 文件中修改 `platforms` 配置:
 具体添加可访问 [项目源代码](https://github.com/ourongxing/newsnow/tree/main/server/sources),根据里面的文件名,在 `config/config.yaml` 文件中修改 `platforms` 配置:
@@ -1427,15 +1529,16 @@ platforms:
     name: "华尔街见闻"
     name: "华尔街见闻"
   # 添加更多平台...
   # 添加更多平台...
 ```
 ```
-如果不会看的话,可以有选择的复制他人整理好的部分[平台配置](https://github.com/sansan0/TrendRadar/issues/95)
 
 
-> 💡 平台不是越多越好,别贪心大量信息,你要进行筛选,否则依然只会被大量信息淹没。
+> 💡 **快捷方式**:如果不会看源代码,可以复制他人整理好的 [平台配置汇总](https://github.com/sansan0/TrendRadar/issues/95)
+
+> ⚠️ **注意**:平台不是越多越好,建议选择 10-15 个核心平台。过多平台会导致信息过载,反而降低使用体验。
 
 
 </details>
 </details>
 
 
 ### 2. 关键词配置
 ### 2. 关键词配置
 
 
-在 `frequency_words.txt` 文件中配置监控的关键词,支持四种语法和词组功能。
+在 `frequency_words.txt` 文件中配置监控的关键词,支持五种语法、区域标记和词组功能。
 
 
 | 语法类型 | 符号 | 作用 | 示例 | 匹配逻辑 |
 | 语法类型 | 符号 | 作用 | 示例 | 匹配逻辑 |
 |---------|------|------|------|---------|
 |---------|------|------|------|---------|
@@ -1443,6 +1546,7 @@ platforms:
 | **必须词** | `+` | 限定范围 | `+手机` | 必须同时包含 |
 | **必须词** | `+` | 限定范围 | `+手机` | 必须同时包含 |
 | **过滤词** | `!` | 排除干扰 | `!广告` | 包含则直接排除 |
 | **过滤词** | `!` | 排除干扰 | `!广告` | 包含则直接排除 |
 | **数量限制** | `@` | 控制显示数量 | `@10` | 最多显示10条新闻(v3.2.0新增) |
 | **数量限制** | `@` | 控制显示数量 | `@10` | 最多显示10条新闻(v3.2.0新增) |
+| **全局过滤** | `[GLOBAL_FILTER]` | 全局排除指定内容 | 见下方示例 | 任何情况下都过滤(v3.5.0新增) |
 
 
 #### 2.1 基础语法
 #### 2.1 基础语法
 
 
@@ -1452,6 +1556,8 @@ platforms:
 <summary>👉 点击展开:<strong>基础语法教程</strong></summary>
 <summary>👉 点击展开:<strong>基础语法教程</strong></summary>
 <br>
 <br>
 
 
+**配置位置:** `config/frequency_words.txt`
+
 ##### 1. **普通关键词** - 基础匹配
 ##### 1. **普通关键词** - 基础匹配
 ```txt
 ```txt
 华为
 华为
@@ -1487,6 +1593,55 @@ OPPO
 
 
 **配置优先级:** `@数字` > 全局配置 > 不限制
 **配置优先级:** `@数字` > 全局配置 > 不限制
 
 
+##### 5. **全局过滤** `[GLOBAL_FILTER]` - 全局排除指定内容(v3.5.0 新增)
+```txt
+[GLOBAL_FILTER]
+广告
+推广
+营销
+震惊
+标题党
+
+[WORD_GROUPS]
+科技
+AI
+
+华为
+鸿蒙
+!车
+```
+**作用:** 在任何情况下过滤包含指定词的新闻,**优先级最高**
+
+**使用场景:**
+- 过滤低质内容:震惊、标题党、爆料等
+- 过滤营销内容:广告、推广、赞助等
+- 过滤特定主题:娱乐、八卦(根据需求)
+
+**过滤优先级:** 全局过滤 > 词组内过滤(`!`) > 词组匹配
+
+**区域说明:**
+- `[GLOBAL_FILTER]`:全局过滤区,包含的词在任何情况下都会被过滤
+- `[WORD_GROUPS]`:词组区,保持现有语法(`!`、`+`、`@`)
+- 如果不使用区域标记,默认全部作为词组处理(向后兼容)
+
+**匹配示例:**
+```txt
+[GLOBAL_FILTER]
+广告
+
+[WORD_GROUPS]
+科技
+AI
+```
+- ❌ "广告:最新科技产品发布" ← 包含全局过滤词"广告",直接拒绝
+- ✅ "科技公司发布AI新产品" ← 不包含全局过滤词,匹配"科技"词组
+- ✅ "AI技术突破引发关注" ← 不包含全局过滤词,匹配"科技"词组中的"AI"
+
+**注意事项:**
+- 全局过滤词应谨慎使用,避免过度过滤导致遗漏有价值内容
+- 建议全局过滤词控制在 5-15 个以内
+- 对于特定词组的过滤,优先使用词组内过滤词(`!` 前缀)
+
 ---
 ---
 
 
 #### 🔗 词组功能 - 空行分隔的重要作用
 #### 🔗 词组功能 - 空行分隔的重要作用
@@ -1672,6 +1827,15 @@ report:
 <summary>👉 点击展开:<strong>三种推送模式详细对比</strong></summary>
 <summary>👉 点击展开:<strong>三种推送模式详细对比</strong></summary>
 <br>
 <br>
 
 
+**配置位置:** `config/config.yaml` 的 `report.mode`
+
+```yaml
+report:
+  mode: "daily"  # 可选: "daily" | "incremental" | "current"
+```
+
+**Docker 环境变量:** `REPORT_MODE=incremental`
+
 #### 详细对比表格
 #### 详细对比表格
 
 
 | 模式 | 适用人群 | 推送时机 | 显示内容 | 典型使用场景 |
 | 模式 | 适用人群 | 推送时机 | 显示内容 | 典型使用场景 |
@@ -1725,6 +1889,15 @@ report:
 <summary>👉 点击展开:<strong>热点权重调整</strong></summary>
 <summary>👉 点击展开:<strong>热点权重调整</strong></summary>
 <br>
 <br>
 
 
+**配置位置:** `config/config.yaml` 的 `weight` 部分
+
+```yaml
+weight:
+  rank_weight: 0.6       # 排名权重
+  frequency_weight: 0.3  # 频次权重
+  hotness_weight: 0.1    # 热度权重
+```
+
 当前默认的配置是平衡性配置
 当前默认的配置是平衡性配置
 
 
 #### 两个核心场景
 #### 两个核心场景
@@ -1822,50 +1995,33 @@ weight:
 <summary>👉 点击展开:<strong>Docker 部署完整指南</strong></summary>
 <summary>👉 点击展开:<strong>Docker 部署完整指南</strong></summary>
 <br>
 <br>
 
 
-#### 方式一:快速体验(一行命令)
+**镜像说明:**
 
 
-**Linux/macOS 系统:**
-```bash
-# 创建配置目录并下载配置文件
-mkdir -p config output
-wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/config/config.yaml -P config/
-wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/config/frequency_words.txt -P config/
-```
-或者**手动创建**:
-1. 在当前目录创建 `config` 文件夹
-2. 下载配置文件:
-   - 访问 https://raw.githubusercontent.com/sansan0/TrendRadar/master/config/config.yaml → 右键"另存为" → 保存到 `config\config.yaml`
-   - 访问 https://raw.githubusercontent.com/sansan0/TrendRadar/master/config/frequency_words.txt → 右键"另存为" → 保存到 `config\frequency_words.txt`
+TrendRadar 提供两个独立的 Docker 镜像,可根据需求选择部署:
 
 
-完成后的目录结构应该是:
-```
-当前目录/
-└── config/
-    ├── config.yaml
-    └── frequency_words.txt
-```
+| 镜像名称 | 用途 | 说明 |
+|---------|------|------|
+| `wantcat/trendradar` | 新闻推送服务 | 定时抓取新闻、推送通知(必选) |
+| `wantcat/trendradar-mcp` | AI 分析服务 | MCP 协议支持、AI 对话分析(可选) |
 
 
-```bash
-docker run -d --name trend-radar \
-  -v ./config:/app/config:ro \
-  -v ./output:/app/output \
-  -e FEISHU_WEBHOOK_URL="你的飞书webhook" \
-  -e DINGTALK_WEBHOOK_URL="你的钉钉webhook" \
-  -e WEWORK_WEBHOOK_URL="你的企业微信webhook" \
-  -e TELEGRAM_BOT_TOKEN="你的telegram_bot_token" \
-  -e TELEGRAM_CHAT_ID="你的telegram_chat_id" \
-  -e EMAIL_FROM="你的发件邮箱" \
-  -e EMAIL_PASSWORD="你的邮箱密码或授权码" \
-  -e EMAIL_TO="收件人邮箱" \
-  -e CRON_SCHEDULE="*/30 * * * *" \
-  -e RUN_MODE="cron" \
-  -e IMMEDIATE_RUN="true" \
-  wantcat/trendradar:latest
-```
-
-#### 方式二:使用 docker-compose(推荐)
+> 💡 **建议**:
+> - 只需要推送功能:仅部署 `wantcat/trendradar` 镜像
+> - 需要 AI 分析功能:同时部署两个镜像
+
+---
+
+#### 方式一:使用 docker-compose(推荐)
 
 
 1. **创建项目目录和配置**:
 1. **创建项目目录和配置**:
+
+   **方式 1-A:使用 git clone(推荐,最简单)**
+   ```bash
+   # 克隆项目到本地
+   git clone https://github.com/sansan0/TrendRadar.git
+   cd TrendRadar
+   ```
+
+   **方式 1-B:使用 wget 下载配置文件**
    ```bash
    ```bash
    # 创建目录结构
    # 创建目录结构
    mkdir -p trendradar/{config,docker}
    mkdir -p trendradar/{config,docker}
@@ -1876,11 +2032,11 @@ docker run -d --name trend-radar \
    wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/config/frequency_words.txt -P config/
    wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/config/frequency_words.txt -P config/
 
 
    # 下载 docker-compose 配置
    # 下载 docker-compose 配置
-   wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/docker/.env
-   wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/docker/docker-compose.yml
+   wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/docker/.env  -P docker/
+   wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/docker/docker-compose.yml  -P docker/
    ```
    ```
 
 
-完成后的目录结构应该是
+   > 💡 **说明**:Docker 部署需要的关键目录结构如下
 ```
 ```
 当前目录/
 当前目录/
 ├── config/
 ├── config/
@@ -1905,10 +2061,13 @@ docker run -d --name trend-radar \
    | `ENABLE_CRAWLER` | `crawler.enable_crawler` | `true` / `false` | 是否启用爬虫 |
    | `ENABLE_CRAWLER` | `crawler.enable_crawler` | `true` / `false` | 是否启用爬虫 |
    | `ENABLE_NOTIFICATION` | `notification.enable_notification` | `true` / `false` | 是否启用通知 |
    | `ENABLE_NOTIFICATION` | `notification.enable_notification` | `true` / `false` | 是否启用通知 |
    | `REPORT_MODE` | `report.mode` | `daily` / `incremental` / `current`| 报告模式 |
    | `REPORT_MODE` | `report.mode` | `daily` / `incremental` / `current`| 报告模式 |
+   | `MAX_ACCOUNTS_PER_CHANNEL` | `notification.max_accounts_per_channel` | `3` | 每个渠道最大账号数 |
    | `PUSH_WINDOW_ENABLED` | `notification.push_window.enabled` | `true` / `false` | 推送时间窗口开关 |
    | `PUSH_WINDOW_ENABLED` | `notification.push_window.enabled` | `true` / `false` | 推送时间窗口开关 |
    | `PUSH_WINDOW_START` | `notification.push_window.time_range.start` | `08:00` | 推送开始时间 |
    | `PUSH_WINDOW_START` | `notification.push_window.time_range.start` | `08:00` | 推送开始时间 |
    | `PUSH_WINDOW_END` | `notification.push_window.time_range.end` | `22:00` | 推送结束时间 |
    | `PUSH_WINDOW_END` | `notification.push_window.time_range.end` | `22:00` | 推送结束时间 |
-   | `FEISHU_WEBHOOK_URL` | `notification.webhooks.feishu_url` | `https://...` | 飞书 Webhook |
+   | `ENABLE_WEBSERVER` | - | `true` / `false` | 是否自动启动 Web 服务器 |
+   | `WEBSERVER_PORT` | - | `8080` | Web 服务器端口(默认 8080) |
+   | `FEISHU_WEBHOOK_URL` | `notification.webhooks.feishu_url` | `https://...` | 飞书 Webhook(支持多账号,用 `;` 分隔) |
 
 
    **配置优先级**:环境变量 > config.yaml
    **配置优先级**:环境变量 > config.yaml
 
 
@@ -1919,22 +2078,52 @@ docker run -d --name trend-radar \
 
 
 
 
 3. **启动服务**:
 3. **启动服务**:
+
+   **选项 A:启动所有服务(推送 + AI 分析)**
    ```bash
    ```bash
-   # 拉取最新镜像并启动
+   # 拉取最新镜像
    docker-compose pull
    docker-compose pull
+
+   # 启动所有服务(trend-radar + trend-radar-mcp)
    docker-compose up -d
    docker-compose up -d
    ```
    ```
 
 
+   **选项 B:仅启动新闻推送服务**
+   ```bash
+   # 只启动 trend-radar(定时抓取和推送)
+   docker-compose pull trend-radar
+   docker-compose up -d trend-radar
+   ```
+
+   **选项 C:仅启动 MCP AI 分析服务**
+   ```bash
+   # 只启动 trend-radar-mcp(提供 AI 分析接口)
+   docker-compose pull trend-radar-mcp
+   docker-compose up -d trend-radar-mcp
+   ```
+
+   > 💡 **提示**:
+   > - 大多数用户只需启动 `trend-radar` 即可实现新闻推送功能
+   > - 只有需要使用 Claude/ChatGPT 进行 AI 对话分析时,才需启动 `trend-radar-mcp`
+   > - 两个服务相互独立,可根据需求灵活组合
+
 4. **查看运行状态**:
 4. **查看运行状态**:
    ```bash
    ```bash
-   # 查看日志
+   # 查看新闻推送服务日志
    docker logs -f trend-radar
    docker logs -f trend-radar
 
 
-   # 查看容器状态
+   # 查看 MCP AI 分析服务日志
+   docker logs -f trend-radar-mcp
+
+   # 查看所有容器状态
    docker ps | grep trend-radar
    docker ps | grep trend-radar
+
+   # 停止特定服务
+   docker-compose stop trend-radar      # 停止推送服务
+   docker-compose stop trend-radar-mcp  # 停止 MCP 服务
    ```
    ```
 
 
-#### 方式三:本地构建(开发者选项)
+#### 方式:本地构建(开发者选项)
 
 
 如果需要自定义修改代码或构建自己的镜像:
 如果需要自定义修改代码或构建自己的镜像:
 
 
@@ -1950,17 +2139,38 @@ vim config/frequency_words.txt
 # 使用构建版本的 docker-compose
 # 使用构建版本的 docker-compose
 cd docker
 cd docker
 cp docker-compose-build.yml docker-compose.yml
 cp docker-compose-build.yml docker-compose.yml
+```
+
+**构建并启动服务**:
 
 
-# 构建并启动
+```bash
+# 选项 A:构建并启动所有服务
 docker-compose build
 docker-compose build
 docker-compose up -d
 docker-compose up -d
+
+# 选项 B:仅构建并启动新闻推送服务
+docker-compose build trend-radar
+docker-compose up -d trend-radar
+
+# 选项 C:仅构建并启动 MCP AI 分析服务
+docker-compose build trend-radar-mcp
+docker-compose up -d trend-radar-mcp
 ```
 ```
 
 
+> 💡 **架构参数说明**:
+> - 默认构建 `amd64` 架构镜像(适用于大多数 x86_64 服务器)
+> - 如需构建 `arm64` 架构(Apple Silicon、树莓派等),设置环境变量:
+>   ```bash
+>   export DOCKER_ARCH=arm64
+>   docker-compose build
+>   ```
+
 #### 镜像更新
 #### 镜像更新
 
 
 ```bash
 ```bash
-# 方式一:手动更新
+# 方式一:手动更新(爬虫 + MCP 镜像)
 docker pull wantcat/trendradar:latest
 docker pull wantcat/trendradar:latest
+docker pull wantcat/trendradar-mcp:latest
 docker-compose down
 docker-compose down
 docker-compose up -d
 docker-compose up -d
 
 
@@ -1969,6 +2179,13 @@ docker-compose pull
 docker-compose up -d
 docker-compose up -d
 ```
 ```
 
 
+**可用镜像**:
+
+| 镜像名称 | 用途 | 说明 |
+|---------|------|------|
+| `wantcat/trendradar` | 新闻推送服务 | 定时抓取新闻、推送通知 |
+| `wantcat/trendradar-mcp` | MCP 服务 | AI 分析功能(可选) |
+
 #### 服务管理命令
 #### 服务管理命令
 
 
 ```bash
 ```bash
@@ -1987,6 +2204,11 @@ docker exec -it trend-radar python manage.py config
 # 显示输出文件
 # 显示输出文件
 docker exec -it trend-radar python manage.py files
 docker exec -it trend-radar python manage.py files
 
 
+# Web 服务器管理(用于浏览器访问生成的报告)
+docker exec -it trend-radar python manage.py start_webserver   # 启动 Web 服务器
+docker exec -it trend-radar python manage.py stop_webserver    # 停止 Web 服务器
+docker exec -it trend-radar python manage.py webserver_status  # 查看 Web 服务器状态
+
 # 查看帮助信息
 # 查看帮助信息
 docker exec -it trend-radar python manage.py help
 docker exec -it trend-radar python manage.py help
 
 
@@ -2000,10 +2222,52 @@ docker stop trend-radar
 docker rm trend-radar
 docker rm trend-radar
 ```
 ```
 
 
+> 💡 **Web 服务器说明**:
+> - 启动后可通过浏览器访问 `http://localhost:8080` 查看最新报告
+> - 通过目录导航访问历史报告(如:`http://localhost:8080/2025年xx月xx日/`)
+> - 端口可在 `.env` 文件中配置 `WEBSERVER_PORT` 参数
+> - 自动启动:在 `.env` 中设置 `ENABLE_WEBSERVER=true`
+> - 安全提示:仅提供静态文件访问,限制在 output 目录,只绑定本地访问
+
 #### 数据持久化
 #### 数据持久化
 
 
 生成的报告和数据默认保存在 `./output` 目录下,即使容器重启或删除,数据也会保留。
 生成的报告和数据默认保存在 `./output` 目录下,即使容器重启或删除,数据也会保留。
 
 
+**📊 网页版报告访问路径**:
+
+TrendRadar 生成的当日汇总 HTML 报告会同时保存到两个位置:
+
+| 文件位置 | 访问方式 | 适用场景 |
+|---------|---------|---------|
+| `output/index.html` | 宿主机直接访问 | **Docker 部署**(通过 Volume 挂载,宿主机可见) |
+| `index.html` | 根目录访问 | **GitHub Pages**(仓库根目录,Pages 自动识别) |
+| `output/YYYY年MM月DD日/html/当日汇总.html` | 历史报告访问 | 所有环境(按日期归档) |
+
+**本地访问示例**:
+```bash
+# 方式 1:通过 Web 服务器访问(推荐,Docker 环境)
+# 1. 启动 Web 服务器
+docker exec -it trend-radar python manage.py start_webserver
+# 2. 在浏览器访问
+http://localhost:8080                           # 访问最新报告(默认 index.html)
+http://localhost:8080/2025年xx月xx日/            # 访问指定日期的报告
+http://localhost:8080/2025年xx月xx日/html/       # 浏览该日期下的所有 HTML 文件
+
+# 方式 2:直接打开文件(本地环境)
+open ./output/index.html             # macOS
+start ./output/index.html            # Windows
+xdg-open ./output/index.html         # Linux
+
+# 方式 3:访问历史归档
+open ./output/2025年xx月xx日/html/当日汇总.html
+```
+
+**为什么有两个 index.html?**
+- `output/index.html`:Docker Volume 挂载到宿主机,本地可直接打开
+- `index.html`:GitHub Actions 推送到仓库,GitHub Pages 自动部署
+
+> 💡 **提示**:两个文件内容完全相同,选择任意一个访问即可。
+
 #### 故障排查
 #### 故障排查
 
 
 ```bash
 ```bash
@@ -2020,6 +2284,513 @@ docker exec -it trend-radar /bin/bash
 docker exec -it trend-radar ls -la /app/config/
 docker exec -it trend-radar ls -la /app/config/
 ```
 ```
 
 
+#### MCP 服务部署(AI 分析功能)
+
+如果需要使用 AI 分析功能,可以部署独立的 MCP 服务容器。
+
+**架构说明**:
+
+```mermaid
+flowchart TB
+    subgraph trend-radar["trend-radar"]
+        A1[定时抓取新闻]
+        A2[推送通知]
+    end
+    
+    subgraph trend-radar-mcp["trend-radar-mcp"]
+        B1[127.0.0.1:3333]
+        B2[AI 分析接口]
+    end
+    
+    subgraph shared["共享卷"]
+        C1["config/ (ro)"]
+        C2["output/ (ro)"]
+    end
+    
+    trend-radar --> shared
+    trend-radar-mcp --> shared
+```
+
+**快速启动**:
+
+使用 docker-compose 同时启动新闻推送和 MCP 服务:
+
+```bash
+# 下载最新的 docker-compose.yml(已包含 MCP 服务配置)
+wget https://raw.githubusercontent.com/sansan0/TrendRadar/master/docker/docker-compose.yml
+
+# 启动所有服务
+docker-compose up -d
+
+# 查看运行状态
+docker ps | grep trend-radar
+```
+
+**单独启动 MCP 服务**:
+
+```bash
+docker run -d --name trend-radar-mcp \
+  -p 127.0.0.1:3333:3333 \
+  -v ./config:/app/config:ro \
+  -v ./output:/app/output:ro \
+  -e TZ=Asia/Shanghai \
+  wantcat/trendradar-mcp:latest
+```
+
+**验证服务**:
+
+```bash
+# 检查 MCP 服务是否正常运行
+curl http://127.0.0.1:3333/mcp
+
+# 查看 MCP 服务日志
+docker logs -f trend-radar-mcp
+```
+
+**在 AI 客户端中配置**:
+
+MCP 服务启动后,在 Claude Desktop、Cherry Studio、Cursor 等客户端中配置:
+
+```json
+{
+  "mcpServers": {
+    "trendradar": {
+      "url": "http://127.0.0.1:3333/mcp",
+      "description": "TrendRadar 新闻热点分析"
+    }
+  }
+}
+```
+
+> 💡 **提示**:MCP 服务仅监听本地端口(127.0.0.1),确保安全性。如需远程访问,请自行配置反向代理和认证。
+
+</details>
+
+### 7. 报告配置
+
+<details>
+<summary>👉 点击展开:<strong>报告相关参数配置</strong></summary>
+<br>
+
+**配置位置:** `config/config.yaml` 的 `report` 部分
+
+```yaml
+report:
+  mode: "daily"                    # 推送模式
+  rank_threshold: 5                # 排名高亮阈值
+  sort_by_position_first: false    # 排序优先级
+  max_news_per_keyword: 0          # 每个关键词最大显示数量
+  reverse_content_order: false     # 内容顺序配置
+```
+
+#### 配置项详解
+
+| 配置项 | 类型 | 默认值 | 说明 |
+|-------|------|-------|------|
+| `mode` | string | `daily` | 推送模式,可选 `daily`/`incremental`/`current`,详见 [推送模式详解](#3-推送模式详解) |
+| `rank_threshold` | int | `5` | 排名高亮阈值,排名 ≤ 该值的新闻会加粗显示 |
+| `sort_by_position_first` | bool | `false` | 排序优先级:`false`=按热点条数排序,`true`=按配置位置排序 |
+| `max_news_per_keyword` | int | `0` | 每个关键词最大显示数量,`0`=不限制 |
+| `reverse_content_order` | bool | `false` | 内容顺序:`false`=热点词汇统计在前,`true`=新增热点新闻在前 |
+
+#### 内容顺序配置(v3.5.0 新增)
+
+控制推送消息和 HTML 报告中两部分内容的显示顺序:
+
+| 配置值 | 显示顺序 |
+|-------|---------|
+| `false`(默认) | ① 热点词汇统计 → ② 新增热点新闻 |
+| `true` | ① 新增热点新闻 → ② 热点词汇统计 |
+
+**适用场景:**
+- `false`(默认):适合关注关键词匹配结果的用户,先看分类统计
+- `true`:适合关注最新动态的用户,优先查看新增热点
+
+**Docker 环境变量:**
+```bash
+REVERSE_CONTENT_ORDER=true
+```
+
+#### 排序优先级配置
+
+**示例场景:** 配置顺序 A、B、C,热点数 A(3条)、B(10条)、C(5条)
+
+| 配置值 | 显示顺序 | 适用场景 |
+|-------|---------|---------|
+| `false`(默认) | B(10条) → C(5条) → A(3条) | 关注热度趋势 |
+| `true` | A(3条) → B(10条) → C(5条) | 关注个人优先级 |
+
+**Docker 环境变量:**
+```bash
+SORT_BY_POSITION_FIRST=true
+MAX_NEWS_PER_KEYWORD=10
+```
+
+</details>
+
+### 8. 推送时间窗口配置
+
+<details>
+<summary>👉 点击展开:<strong>推送时间窗口控制详解</strong></summary>
+<br>
+
+**配置位置:** `config/config.yaml` 的 `notification.push_window` 部分
+
+```yaml
+notification:
+  push_window:
+    enabled: false                    # 是否启用
+    time_range:
+      start: "20:00"                  # 开始时间(北京时间)
+      end: "22:00"                    # 结束时间(北京时间)
+    once_per_day: true                # 每天只推送一次
+    push_record_retention_days: 7     # 推送记录保留天数
+```
+
+#### 配置项详解
+
+| 配置项 | 类型 | 默认值 | 说明 |
+|-------|------|-------|------|
+| `enabled` | bool | `false` | 是否启用推送时间窗口控制 |
+| `time_range.start` | string | `"20:00"` | 推送时间窗口开始时间(北京时间,HH:MM 格式) |
+| `time_range.end` | string | `"22:00"` | 推送时间窗口结束时间(北京时间,HH:MM 格式) |
+| `once_per_day` | bool | `true` | `true`=每天在窗口内只推送一次,`false`=窗口内每次执行都推送 |
+| `push_record_retention_days` | int | `7` | 推送记录保留天数(用于判断是否已推送) |
+
+#### 使用场景
+
+| 场景 | 配置示例 |
+|------|---------|
+| **工作时间推送** | `start: "09:00"`, `end: "18:00"`, `once_per_day: false` |
+| **晚间汇总推送** | `start: "20:00"`, `end: "22:00"`, `once_per_day: true` |
+| **午休时间推送** | `start: "12:00"`, `end: "13:00"`, `once_per_day: true` |
+
+#### 重要提示
+
+> ⚠️ **GitHub Actions 用户注意:**
+> - GitHub Actions 执行时间不稳定,可能有 ±15 分钟的偏差
+> - 时间范围建议至少留足 **2 小时**
+> - 如果想要精准的定时推送,建议使用 **Docker 部署**在个人服务器上
+
+#### Docker 环境变量
+
+```bash
+PUSH_WINDOW_ENABLED=true
+PUSH_WINDOW_START=09:00
+PUSH_WINDOW_END=18:00
+PUSH_WINDOW_ONCE_PER_DAY=false
+PUSH_WINDOW_RETENTION_DAYS=7
+```
+
+#### 完整配置示例
+
+**场景:每天晚上 8-10 点只推送一次汇总**
+
+```yaml
+notification:
+  push_window:
+    enabled: true
+    time_range:
+      start: "20:00"
+      end: "22:00"
+    once_per_day: true
+    push_record_retention_days: 7
+```
+
+**场景:工作时间内每小时推送**
+
+```yaml
+notification:
+  push_window:
+    enabled: true
+    time_range:
+      start: "09:00"
+      end: "18:00"
+    once_per_day: false
+    push_record_retention_days: 7
+```
+
+</details>
+
+### 9. 执行频率配置
+
+<details>
+<summary>👉 点击展开:<strong>自动运行频率设置</strong></summary>
+<br>
+
+**配置位置:** `.github/workflows/crawler.yml` 的 `schedule` 部分
+
+```yaml
+on:
+  schedule:
+    - cron: "0 * * * *"  # 每小时运行一次
+```
+
+#### 什么是 Cron 表达式?
+
+Cron 是一种定时任务格式,由 5 个部分组成:`分 时 日 月 周`
+
+```
+┌───────────── 分钟 (0-59)
+│ ┌───────────── 小时 (0-23)
+│ │ ┌───────────── 日期 (1-31)
+│ │ │ ┌───────────── 月份 (1-12)
+│ │ │ │ ┌───────────── 星期 (0-6,0=周日)
+│ │ │ │ │
+* * * * *
+```
+
+#### 常用配置示例
+
+| 想要的效果 | Cron 表达式 | 说明 |
+|-----------|------------|------|
+| 每小时运行 | `0 * * * *` | 每小时的第 0 分钟运行(默认) |
+| 每 30 分钟运行 | `*/30 * * * *` | 每隔 30 分钟运行一次 |
+| 每天早 8 点运行 | `0 0 * * *` | UTC 0:00 = 北京时间 8:00 |
+| 工作时间运行 | `*/30 0-14 * * *` | 北京 8:00-22:00,每 30 分钟 |
+| 每天 3 次 | `0 0,6,12 * * *` | 北京 8:00、14:00、20:00 |
+
+#### 重要提示
+
+> ⚠️ **时区注意**:GitHub Actions 使用 **UTC 时间**,北京时间需要 **减 8 小时**
+> - 想要北京时间 8:00 运行 → 设置 UTC 0:00
+> - 想要北京时间 20:00 运行 → 设置 UTC 12:00
+
+> ⚠️ **频率限制**:GitHub 对每个账号的 Actions 运行次数有限额
+> - **建议**:不要设置比 30 分钟更短的间隔
+> - **原因**:过于频繁可能被判定为滥用,面临封号风险
+> - **实际情况**:GitHub Actions 执行时间本身就有偏差,设置太精确意义不大
+
+#### 修改方法
+
+1. 打开你 fork 的仓库
+2. 找到 `.github/workflows/crawler.yml` 文件
+3. 点击编辑(铅笔图标)
+4. 修改 `cron: "0 * * * *"` 中的表达式
+5. 点击 "Commit changes" 保存
+
+</details>
+
+### 10. 多账号推送配置
+
+<details>
+<summary>👉 点击展开:<strong>多账号推送配置详解</strong></summary>
+
+> ### ⚠️ **安全警告**
+> **GitHub Fork 用户请勿在 `config.yaml` 中配置推送信息!**
+>
+> - **风险说明**:`config.yaml` 会被提交到公开的 Git 仓库,配置推送信息(Webhook URL、Token 等)会泄露敏感数据
+> - **推荐方式**:
+>   - **GitHub Actions 用户** → 使用 GitHub Secrets 环境变量
+>   - **Docker 用户** → 使用 [`.env` 文件配置](#6-docker-部署)(`.env` 已在 `.gitignore` 中,不会被提交)
+> - **本地开发用户**:可以在 `config.yaml` 中配置(确保不会 push 到公开仓库)
+
+#### 支持的渠道
+
+| 渠道 | 配置项 | 是否需要配对 | 说明 |
+|------|--------|-------------|------|
+| **飞书** | `feishu_url` | 否 | 多个 webhook URL |
+| **钉钉** | `dingtalk_url` | 否 | 多个 webhook URL |
+| **企业微信** | `wework_url` | 否 | 多个 webhook URL |
+| **Telegram** | `telegram_bot_token` + `telegram_chat_id` | ✅ 是 | token 和 chat_id 数量必须一致 |
+| **ntfy** | `ntfy_topic` + `ntfy_token` | ✅ 是 | topic 和 token 数量必须一致(token 可选) |
+| **Bark** | `bark_url` | 否 | 多个推送 URL |
+| **Slack** | `slack_webhook_url` | 否 | 多个 webhook URL |
+| **邮件** | `email_to` | - | 已支持多收件人(逗号分隔),无需修改 |
+
+#### 推荐配置方式 1:GitHub Actions 环境变量
+
+**配置位置**:GitHub Repo → Settings → Secrets and variables → Actions → Repository secrets
+
+**基础配置示例**:
+```bash
+# 多账号数量限制
+MAX_ACCOUNTS_PER_CHANNEL=3
+
+# 飞书多账号(3个群组)
+FEISHU_WEBHOOK_URL=https://hook1.feishu.cn/xxx;https://hook2.feishu.cn/yyy;https://hook3.feishu.cn/zzz
+
+# 钉钉多账号(2个群组)
+DINGTALK_WEBHOOK_URL=https://oapi.dingtalk.com/xxx;https://oapi.dingtalk.com/yyy
+
+# 企业微信多账号(2个群组)
+WEWORK_WEBHOOK_URL=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx;https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=yyy
+
+# Bark多账号(2个设备)
+BARK_URL=https://api.day.app/key1;https://api.day.app/key2
+
+# Slack多账号(2个频道)
+SLACK_WEBHOOK_URL=https://hooks.slack.com/xxx;https://hooks.slack.com/yyy
+```
+
+**配对配置示例(Telegram 和 ntfy)**:
+
+<details>
+<summary><strong>Telegram 配对配置</strong></summary>
+
+```bash
+# ✅ 正确配置:2个token对应2个chat_id
+TELEGRAM_BOT_TOKEN=123456:AAA-BBB;789012:CCC-DDD
+TELEGRAM_CHAT_ID=-100111;-100222
+
+# ❌ 错误配置:数量不一致,将跳过推送
+TELEGRAM_BOT_TOKEN=token1;token2;token3
+TELEGRAM_CHAT_ID=id1;id2
+```
+
+**说明**:`token` 和 `chat_id` 的数量必须完全一致,否则该渠道推送会被跳过。
+
+</details>
+
+<details>
+<summary><strong>ntfy 配对配置</strong></summary>
+
+```bash
+# ✅ 正确配置:3个topic,只有第2个需要token
+NTFY_TOPIC=topic1;topic2;topic3
+NTFY_TOKEN=;token_for_topic2;
+
+# ✅ 正确配置:2个topic都需要token
+NTFY_TOPIC=topic1;topic2
+NTFY_TOKEN=token1;token2
+
+# ❌ 错误配置:topic和token数量不匹配
+NTFY_TOPIC=topic1;topic2
+NTFY_TOKEN=token1;token2;token3
+```
+
+**说明**:
+- 如果某个 topic 不需要 token,在对应位置留空(两个分号之间)
+- `topic` 和 `token` 的数量必须一致
+
+</details>
+
+---
+
+#### 推荐配置方式 2:Docker 环境变量(.env)
+
+**配置位置**:项目根目录 `docker/.env` 文件
+
+**基础配置示例**:
+```bash
+# 多账号数量限制
+MAX_ACCOUNTS_PER_CHANNEL=3
+
+# 飞书多账号(3个群组)
+FEISHU_WEBHOOK_URL=https://hook1.feishu.cn/xxx;https://hook2.feishu.cn/yyy;https://hook3.feishu.cn/zzz
+
+# 钉钉多账号(2个群组)
+DINGTALK_WEBHOOK_URL=https://oapi.dingtalk.com/xxx;https://oapi.dingtalk.com/yyy
+
+# 企业微信多账号(2个群组)
+WEWORK_WEBHOOK_URL=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx;https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=yyy
+
+# Bark多账号(2个设备)
+BARK_URL=https://api.day.app/key1;https://api.day.app/key2
+
+# Slack多账号(2个频道)
+SLACK_WEBHOOK_URL=https://hooks.slack.com/xxx;https://hooks.slack.com/yyy
+```
+
+**配对配置示例(Telegram 和 ntfy)**:
+
+<details>
+<summary><strong>Telegram 配对配置</strong></summary>
+
+```bash
+# ✅ 正确配置:2个token对应2个chat_id
+TELEGRAM_BOT_TOKEN=123456:AAA-BBB;789012:CCC-DDD
+TELEGRAM_CHAT_ID=-100111;-100222
+
+# ❌ 错误配置:数量不一致,将跳过推送
+TELEGRAM_BOT_TOKEN=token1;token2;token3
+TELEGRAM_CHAT_ID=id1;id2
+```
+
+**说明**:`token` 和 `chat_id` 的数量必须完全一致,否则该渠道推送会被跳过。
+
+</details>
+
+<details>
+<summary><strong>ntfy 配对配置</strong></summary>
+
+```bash
+# ✅ 正确配置:3个topic,只有第2个需要token
+NTFY_TOPIC=topic1;topic2;topic3
+NTFY_TOKEN=;token_for_topic2;
+
+# ✅ 正确配置:2个topic都需要token
+NTFY_TOPIC=topic1;topic2
+NTFY_TOKEN=token1;token2
+
+# ❌ 错误配置:topic和token数量不匹配
+NTFY_TOPIC=topic1;topic2
+NTFY_TOKEN=token1;token2;token3
+```
+
+**说明**:
+- 如果某个 topic 不需要 token,在对应位置留空(两个分号之间)
+- `topic` 和 `token` 的数量必须一致
+
+</details>
+
+---
+
+#### 推送行为说明
+
+1. **独立推送**:每个账号独立发送,一个失败不影响其他账号
+2. **部分成功判定**:只要有一个账号发送成功,整体视为成功
+3. **日志区分**:多账号时日志会显示"账号1"、"账号2"等标签
+4. **批次间隔**:多账号会增加总发送时间(每个账号独立计算批次间隔)
+
+---
+
+#### 常见问题
+
+<details>
+<summary><strong>Q1: 超过 3 个账号会怎样?</strong></summary>
+<br>
+
+系统会自动截断到配置的最大数量,并输出警告日志。可通过 `max_accounts_per_channel` 调整限制。
+
+**⚠️ GitHub Actions 用户特别注意**:
+- **不建议配置过多账号**(建议不超过 3 个),可能导致:
+  - **触发 GitHub Actions 速率限制**:频繁的网络请求可能被识别为异常行为
+  - **潜在账号风险**:过度使用 GitHub Actions 资源可能影响账号状态
+
+</details>
+
+<details>
+<summary><strong>Q2: 多账号会影响推送速度吗?</strong></summary>
+<br>
+
+会。每个账号独立发送,总时间 = 账号数 × 单账号发送时间。建议控制账号数量。
+
+</details>
+
+<details>
+<summary><strong>Q3: 本地开发用户如何在 config.yaml 中配置?</strong></summary>
+<br>
+
+如果你是本地开发且**不会将代码推送到公开仓库**,可以直接在 `config/config.yaml` 中配置:
+
+```yaml
+notification:
+  enable_notification: true
+  max_accounts_per_channel: 3
+
+  webhooks:
+    feishu_url: "https://hook1.feishu.cn/xxx;https://hook2.feishu.cn/yyy"
+    telegram_bot_token: "token1;token2"
+    telegram_chat_id: "id1;id2"
+```
+
+**⚠️ 重要提醒**:
+- 确保 `config/config.yaml` 在 `.gitignore` 中(如果会提交代码)
+- 或者只在本地开发环境使用,**绝不提交到公开仓库**
+
+</details>
+
 </details>
 </details>
 
 
 <br>
 <br>

+ 27 - 9
config/config.yaml

@@ -29,6 +29,7 @@ report:
   rank_threshold: 5 # 排名高亮阈值
   rank_threshold: 5 # 排名高亮阈值
   sort_by_position_first: false # 排序优先级:true=先按配置位置排序,false=先按热点条数排序
   sort_by_position_first: false # 排序优先级:true=先按配置位置排序,false=先按热点条数排序
   max_news_per_keyword: 0 # 每个关键词最大显示数量,0=不限制
   max_news_per_keyword: 0 # 每个关键词最大显示数量,0=不限制
+  reverse_content_order: false # 内容顺序:false=热点词汇统计在前,true=新增热点新闻在前
 
 
 notification:
 notification:
   enable_notification: true # 是否启用通知功能,如果 false,则不发送手机通知
   enable_notification: true # 是否启用通知功能,如果 false,则不发送手机通知
@@ -39,6 +40,7 @@ notification:
   slack_batch_size: 4000 # Slack消息分批大小(字节)
   slack_batch_size: 4000 # Slack消息分批大小(字节)
   batch_send_interval: 3 # 批次发送间隔(秒)
   batch_send_interval: 3 # 批次发送间隔(秒)
   feishu_message_separator: "━━━━━━━━━━━━━━━━━━━" # feishu 消息分割线
   feishu_message_separator: "━━━━━━━━━━━━━━━━━━━" # feishu 消息分割线
+  max_accounts_per_channel: 3 # 每个渠道最大账号数量,建议不超过 3
 
 
   # 🕐 推送时间窗口控制(可选功能)
   # 🕐 推送时间窗口控制(可选功能)
   # 用途:限制推送的时间范围,避免非工作时间打扰
   # 用途:限制推送的时间范围,避免非工作时间打扰
@@ -71,23 +73,39 @@ notification:
   #    - Minor: Spam notifications flooding your devices
   #    - Minor: Spam notifications flooding your devices
   #    - Severe: Webhook abuse leading to security incidents (malicious messages, phishing links, etc.)
   #    - Severe: Webhook abuse leading to security incidents (malicious messages, phishing links, etc.)
   #
   #
+  # ⚠️⚠️⚠️ 多账号推送说明 / MULTI-ACCOUNT PUSH NOTICE ⚠️⚠️⚠️
+  #
+  # 🔸 多账号支持:
+  #   • 请使用分号(;)分隔多个账号,如:"url1;url2;url3"
+  #   • 示例:telegram_bot_token: "token1;token2" 对应 telegram_chat_id: "id1;id2"
+  #   • 对于需要配对的配置(如 Telegram 的 token 和 chat_id),数量必须一致
+  #   • 每个渠道最多支持 max_accounts_per_channel 个账号(见上方配置)
+  #   • 邮箱已支持多收件人(逗号分隔),保持不变
+  #
+  # 🔸 Multi-Account Support:
+  #   • Use semicolon(;) to separate multiple accounts, e.g., "url1;url2;url3"
+  #   • Example: telegram_bot_token: "token1;token2" with telegram_chat_id: "id1;id2"
+  #   • For paired configs (e.g., Telegram token and chat_id), quantities must match
+  #   • Each channel supports up to max_accounts_per_channel accounts (see above config)
+  #   • Email already supports multiple recipients (comma-separated), unchanged
+  #
   webhooks:
   webhooks:
-    feishu_url: "" # 飞书机器人的 webhook URL
-    dingtalk_url: "" # 钉钉机器人的 webhook URL
-    wework_url: "" # 企业微信机器人的 webhook URL
+    feishu_url: "" # 飞书机器人的 webhook URL(多账号用 ; 分隔)
+    dingtalk_url: "" # 钉钉机器人的 webhook URL(多账号用 ; 分隔)
+    wework_url: "" # 企业微信机器人的 webhook URL(多账号用 ; 分隔)
     wework_msg_type: "markdown" # 企业微信消息类型:markdown(群机器人) 或 text(个人微信应用)
     wework_msg_type: "markdown" # 企业微信消息类型:markdown(群机器人) 或 text(个人微信应用)
-    telegram_bot_token: "" # Telegram Bot Token
-    telegram_chat_id: "" # Telegram Chat ID
+    telegram_bot_token: "" # Telegram Bot Token(多账号用 ; 分隔,需与 chat_id 数量一致)
+    telegram_chat_id: "" # Telegram Chat ID(多账号用 ; 分隔,需与 bot_token 数量一致)
     email_from: "" # 发件人邮箱地址
     email_from: "" # 发件人邮箱地址
     email_password: "" # 发件人邮箱密码或授权码
     email_password: "" # 发件人邮箱密码或授权码
     email_to: "" # 收件人邮箱地址,多个收件人用逗号分隔
     email_to: "" # 收件人邮箱地址,多个收件人用逗号分隔
     email_smtp_server: "" # SMTP服务器地址(可选,留空自动识别)
     email_smtp_server: "" # SMTP服务器地址(可选,留空自动识别)
     email_smtp_port: "" # SMTP端口(可选,留空自动识别)
     email_smtp_port: "" # SMTP端口(可选,留空自动识别)
     ntfy_server_url: "https://ntfy.sh" # ntfy服务器地址,默认使用公共服务,可改为自托管地址
     ntfy_server_url: "https://ntfy.sh" # ntfy服务器地址,默认使用公共服务,可改为自托管地址
-    ntfy_topic: "" # ntfy主题名称
-    ntfy_token: "" # ntfy访问令牌(可选,用于私有主题)
-    bark_url: "" # Bark推送URL(格式:https://api.day.app/your_device_key 或自建服务器地址)
-    slack_webhook_url: "" # Slack Incoming Webhook URL(格式:https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX)
+    ntfy_topic: "" # ntfy主题名称(多账号用 ; 分隔)
+    ntfy_token: "" # ntfy访问令牌(可选,用于私有主题,多账号用 ; 分隔
+    bark_url: "" # Bark推送URL(多账号用 ; 分隔,格式:https://api.day.app/your_device_key 或自建服务器地址)
+    slack_webhook_url: "" # Slack Incoming Webhook URL(多账号用 ; 分隔,格式:https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX)
 
 
 # 用于让关注度更高的新闻在更前面显示,即用算法重新组合不同平台的热搜排序形成你侧重的热搜,合起来是 1 就行
 # 用于让关注度更高的新闻在更前面显示,即用算法重新组合不同平台的热搜排序形成你侧重的热搜,合起来是 1 就行
 weight:
 weight:

+ 35 - 9
docker/.env

@@ -12,6 +12,21 @@ REPORT_MODE=
 SORT_BY_POSITION_FIRST=
 SORT_BY_POSITION_FIRST=
 # 每个关键词最大显示数量 (0=不限制,>0=限制数量)
 # 每个关键词最大显示数量 (0=不限制,>0=限制数量)
 MAX_NEWS_PER_KEYWORD=
 MAX_NEWS_PER_KEYWORD=
+# 内容顺序:false=热点词汇统计在前,true=新增热点新闻在前
+REVERSE_CONTENT_ORDER=
+
+# ============================================
+# Web 服务器配置
+# ============================================
+
+# 是否自动启动 Web 服务器托管 output 目录 (true/false)
+# 启用后可通过 http://localhost:{WEBSERVER_PORT} 访问生成的报告
+# 手动控制:docker exec -it trend-radar python manage.py start_webserver
+ENABLE_WEBSERVER=false
+
+# Web 服务器端口(默认 8080,可自定义避免冲突)
+# 注意:修改后需要重启容器生效
+WEBSERVER_PORT=8080
 
 
 # ============================================
 # ============================================
 # 推送时间窗口配置
 # 推送时间窗口配置
@@ -29,36 +44,47 @@ PUSH_WINDOW_ONCE_PER_DAY=
 PUSH_WINDOW_RETENTION_DAYS=
 PUSH_WINDOW_RETENTION_DAYS=
 
 
 # ============================================
 # ============================================
-# 通知渠道配置
+# 多账号配置
+# ============================================
+
+# 每个渠道最大账号数量(建议不超过 3,避免fork用户触发账号风险)
+MAX_ACCOUNTS_PER_CHANNEL=
+
+# ============================================
+# 通知渠道配置(多账号用 ; 分隔)
 # ============================================
 # ============================================
 
 
-# 推送配置
+# 飞书机器人 webhook URL(多账号用 ; 分隔)
 FEISHU_WEBHOOK_URL=
 FEISHU_WEBHOOK_URL=
+# Telegram Bot Token(多账号用 ; 分隔,需与 chat_id 数量一致)
 TELEGRAM_BOT_TOKEN=
 TELEGRAM_BOT_TOKEN=
+# Telegram Chat ID(多账号用 ; 分隔,需与 bot_token 数量一致)
 TELEGRAM_CHAT_ID=
 TELEGRAM_CHAT_ID=
+# 钉钉机器人 webhook URL(多账号用 ; 分隔)
 DINGTALK_WEBHOOK_URL=
 DINGTALK_WEBHOOK_URL=
+# 企业微信机器人 webhook URL(多账号用 ; 分隔)
 WEWORK_WEBHOOK_URL=
 WEWORK_WEBHOOK_URL=
+# 企业微信消息类型(markdown 或 text)
 WEWORK_MSG_TYPE=
 WEWORK_MSG_TYPE=
 
 
+# 邮件配置(邮箱已支持多收件人,逗号分隔)
 EMAIL_FROM=
 EMAIL_FROM=
 EMAIL_PASSWORD=
 EMAIL_PASSWORD=
 EMAIL_TO=
 EMAIL_TO=
 EMAIL_SMTP_SERVER=
 EMAIL_SMTP_SERVER=
 EMAIL_SMTP_PORT=
 EMAIL_SMTP_PORT=
 
 
-# ntfy 推送配置
+# ntfy 推送配置(多账号用 ; 分隔,topic 和 token 数量需一致)
 NTFY_SERVER_URL=https://ntfy.sh
 NTFY_SERVER_URL=https://ntfy.sh
-# ntfy主题名称
+# ntfy主题名称(多账号用 ; 分隔)
 NTFY_TOPIC=
 NTFY_TOPIC=
-# 可选:访问令牌(用于私有主题)
+# 可选:访问令牌(用于私有主题,多账号用 ; 分隔,无令牌的留空占位如 ";token2")
 NTFY_TOKEN=
 NTFY_TOKEN=
 
 
-# Bark 推送配置
-# Bark推送URL(格式:https://api.day.app/your_device_key 或自建服务器地址)
+# Bark 推送配置(多账号用 ; 分隔)
 BARK_URL=
 BARK_URL=
 
 
-# Slack 推送配置
-# Slack Incoming Webhook URL(格式:https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX)
+# Slack 推送配置(多账号用 ; 分隔)
 SLACK_WEBHOOK_URL=
 SLACK_WEBHOOK_URL=
 
 
 # ============================================
 # ============================================

+ 18 - 19
docker/Dockerfile

@@ -2,9 +2,9 @@ FROM python:3.10-slim
 
 
 WORKDIR /app
 WORKDIR /app
 
 
-# https://github.com/aptible/supercronic
+# Latest releases available at https://github.com/aptible/supercronic/releases
 ARG TARGETARCH
 ARG TARGETARCH
-ENV SUPERCRONIC_VERSION=v0.2.34
+ENV SUPERCRONIC_VERSION=v0.2.39
 
 
 RUN set -ex && \
 RUN set -ex && \
     apt-get update && \
     apt-get update && \
@@ -12,12 +12,12 @@ RUN set -ex && \
     case ${TARGETARCH} in \
     case ${TARGETARCH} in \
     amd64) \
     amd64) \
     export SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/${SUPERCRONIC_VERSION}/supercronic-linux-amd64; \
     export SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/${SUPERCRONIC_VERSION}/supercronic-linux-amd64; \
-    export SUPERCRONIC_SHA1SUM=e8631edc1775000d119b70fd40339a7238eece14; \
+    export SUPERCRONIC_SHA1SUM=c98bbf82c5f648aaac8708c182cc83046fe48423; \
     export SUPERCRONIC=supercronic-linux-amd64; \
     export SUPERCRONIC=supercronic-linux-amd64; \
     ;; \
     ;; \
     arm64) \
     arm64) \
     export SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/${SUPERCRONIC_VERSION}/supercronic-linux-arm64; \
     export SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/${SUPERCRONIC_VERSION}/supercronic-linux-arm64; \
-    export SUPERCRONIC_SHA1SUM=4ab6343b52bf9da592e8b4bb7ae6eb5a8e21b71e; \
+    export SUPERCRONIC_SHA1SUM=5ef4ccc3d43f12d0f6c3763758bc37cc4e5af76e; \
     export SUPERCRONIC=supercronic-linux-arm64; \
     export SUPERCRONIC=supercronic-linux-arm64; \
     ;; \
     ;; \
     *) \
     *) \
@@ -26,26 +26,25 @@ RUN set -ex && \
     ;; \
     ;; \
     esac && \
     esac && \
     echo "Downloading supercronic for ${TARGETARCH} from ${SUPERCRONIC_URL}" && \
     echo "Downloading supercronic for ${TARGETARCH} from ${SUPERCRONIC_URL}" && \
-    # 添加重试机制和超时设置
-    for i in 1 2 3 4 5; do \
-    echo "Download attempt $i/5"; \
-    if curl --fail --silent --show-error --location --retry 3 --retry-delay 2 --connect-timeout 30 --max-time 120 -o "$SUPERCRONIC" "$SUPERCRONIC_URL"; then \
-    echo "Download successful"; \
-    break; \
-    else \
-    echo "Download attempt $i failed, exit code: $?"; \
-    if [ $i -eq 5 ]; then \
-    echo "All download attempts failed"; \
-    exit 1; \
-    fi; \
-    sleep $((i * 2)); \
-    fi; \
+    # 重试机制:最多3次,每次超时30秒
+    for i in 1 2 3; do \
+        echo "Download attempt $i/3"; \
+        if curl -fsSL --connect-timeout 30 --max-time 60 -o "$SUPERCRONIC" "$SUPERCRONIC_URL"; then \
+            echo "Download successful"; \
+            break; \
+        else \
+            echo "Download attempt $i failed"; \
+            if [ $i -eq 3 ]; then \
+                echo "All download attempts failed"; \
+                exit 1; \
+            fi; \
+            sleep 2; \
+        fi; \
     done && \
     done && \
     echo "${SUPERCRONIC_SHA1SUM}  ${SUPERCRONIC}" | sha1sum -c - && \
     echo "${SUPERCRONIC_SHA1SUM}  ${SUPERCRONIC}" | sha1sum -c - && \
     chmod +x "$SUPERCRONIC" && \
     chmod +x "$SUPERCRONIC" && \
     mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" && \
     mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" && \
     ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic && \
     ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic && \
-    # 验证安装
     supercronic -version && \
     supercronic -version && \
     apt-get remove -y curl && \
     apt-get remove -y curl && \
     apt-get clean && \
     apt-get clean && \

+ 23 - 0
docker/Dockerfile.mcp

@@ -0,0 +1,23 @@
+FROM python:3.10-slim
+
+WORKDIR /app
+
+# 安装依赖
+COPY requirements.txt .
+RUN pip install --no-cache-dir -r requirements.txt
+
+# 复制 MCP 服务器代码
+COPY mcp_server/ ./mcp_server/
+
+# 创建必要目录
+RUN mkdir -p /app/config /app/output
+
+ENV PYTHONUNBUFFERED=1 \
+    CONFIG_PATH=/app/config/config.yaml \
+    FREQUENCY_WORDS_PATH=/app/config/frequency_words.txt
+
+# MCP HTTP 服务端口
+EXPOSE 3333
+
+# 启动 MCP 服务器(HTTP 模式)
+CMD ["python", "-m", "mcp_server.server", "--transport", "http", "--host", "0.0.0.0", "--port", "3333"]

+ 26 - 0
docker/docker-compose-build.yml

@@ -6,6 +6,9 @@ services:
     container_name: trend-radar
     container_name: trend-radar
     restart: unless-stopped
     restart: unless-stopped
 
 
+    ports:
+      - "127.0.0.1:${WEBSERVER_PORT:-8080}:${WEBSERVER_PORT:-8080}"
+
     volumes:
     volumes:
       - ../config:/app/config:ro
       - ../config:/app/config:ro
       - ../output:/app/output
       - ../output:/app/output
@@ -18,6 +21,12 @@ services:
       - REPORT_MODE=${REPORT_MODE:-}
       - REPORT_MODE=${REPORT_MODE:-}
       - SORT_BY_POSITION_FIRST=${SORT_BY_POSITION_FIRST:-}
       - SORT_BY_POSITION_FIRST=${SORT_BY_POSITION_FIRST:-}
       - MAX_NEWS_PER_KEYWORD=${MAX_NEWS_PER_KEYWORD:-}
       - MAX_NEWS_PER_KEYWORD=${MAX_NEWS_PER_KEYWORD:-}
+      - REVERSE_CONTENT_ORDER=${REVERSE_CONTENT_ORDER:-}
+      # Web 服务器
+      - ENABLE_WEBSERVER=${ENABLE_WEBSERVER:-false}
+      - WEBSERVER_PORT=${WEBSERVER_PORT:-8080}
+      # 多账号配置
+      - MAX_ACCOUNTS_PER_CHANNEL=${MAX_ACCOUNTS_PER_CHANNEL:-}
       # 推送时间窗口
       # 推送时间窗口
       - PUSH_WINDOW_ENABLED=${PUSH_WINDOW_ENABLED:-}
       - PUSH_WINDOW_ENABLED=${PUSH_WINDOW_ENABLED:-}
       - PUSH_WINDOW_START=${PUSH_WINDOW_START:-}
       - PUSH_WINDOW_START=${PUSH_WINDOW_START:-}
@@ -49,3 +58,20 @@ services:
       - CRON_SCHEDULE=${CRON_SCHEDULE:-*/5 * * * *}
       - CRON_SCHEDULE=${CRON_SCHEDULE:-*/5 * * * *}
       - RUN_MODE=${RUN_MODE:-cron}
       - RUN_MODE=${RUN_MODE:-cron}
       - IMMEDIATE_RUN=${IMMEDIATE_RUN:-true}
       - IMMEDIATE_RUN=${IMMEDIATE_RUN:-true}
+
+  trend-radar-mcp:
+    build:
+      context: ..
+      dockerfile: docker/Dockerfile.mcp
+    container_name: trend-radar-mcp
+    restart: unless-stopped
+
+    ports:
+      - "127.0.0.1:3333:3333"
+
+    volumes:
+      - ../config:/app/config:ro
+      - ../output:/app/output:ro
+
+    environment:
+      - TZ=Asia/Shanghai

+ 24 - 0
docker/docker-compose.yml

@@ -4,6 +4,9 @@ services:
     container_name: trend-radar
     container_name: trend-radar
     restart: unless-stopped
     restart: unless-stopped
 
 
+    ports:
+      - "127.0.0.1:${WEBSERVER_PORT:-8080}:${WEBSERVER_PORT:-8080}"
+
     volumes:
     volumes:
       - ../config:/app/config:ro
       - ../config:/app/config:ro
       - ../output:/app/output
       - ../output:/app/output
@@ -16,6 +19,12 @@ services:
       - REPORT_MODE=${REPORT_MODE:-}
       - REPORT_MODE=${REPORT_MODE:-}
       - SORT_BY_POSITION_FIRST=${SORT_BY_POSITION_FIRST:-}
       - SORT_BY_POSITION_FIRST=${SORT_BY_POSITION_FIRST:-}
       - MAX_NEWS_PER_KEYWORD=${MAX_NEWS_PER_KEYWORD:-}
       - MAX_NEWS_PER_KEYWORD=${MAX_NEWS_PER_KEYWORD:-}
+      - REVERSE_CONTENT_ORDER=${REVERSE_CONTENT_ORDER:-}
+      # Web 服务器
+      - ENABLE_WEBSERVER=${ENABLE_WEBSERVER:-false}
+      - WEBSERVER_PORT=${WEBSERVER_PORT:-8080}
+      # 多账号配置
+      - MAX_ACCOUNTS_PER_CHANNEL=${MAX_ACCOUNTS_PER_CHANNEL:-}
       # 推送时间窗口
       # 推送时间窗口
       - PUSH_WINDOW_ENABLED=${PUSH_WINDOW_ENABLED:-}
       - PUSH_WINDOW_ENABLED=${PUSH_WINDOW_ENABLED:-}
       - PUSH_WINDOW_START=${PUSH_WINDOW_START:-}
       - PUSH_WINDOW_START=${PUSH_WINDOW_START:-}
@@ -47,3 +56,18 @@ services:
       - CRON_SCHEDULE=${CRON_SCHEDULE:-*/5 * * * *}
       - CRON_SCHEDULE=${CRON_SCHEDULE:-*/5 * * * *}
       - RUN_MODE=${RUN_MODE:-cron}
       - RUN_MODE=${RUN_MODE:-cron}
       - IMMEDIATE_RUN=${IMMEDIATE_RUN:-true}
       - IMMEDIATE_RUN=${IMMEDIATE_RUN:-true}
+
+  trend-radar-mcp:
+    image: wantcat/trendradar-mcp:latest
+    container_name: trend-radar-mcp
+    restart: unless-stopped
+
+    ports:
+      - "127.0.0.1:3333:3333"
+
+    volumes:
+      - ../config:/app/config:ro
+      - ../output:/app/output:ro
+
+    environment:
+      - TZ=Asia/Shanghai

+ 7 - 1
docker/entrypoint.sh

@@ -33,9 +33,15 @@ case "${RUN_MODE:-cron}" in
         /usr/local/bin/python main.py
         /usr/local/bin/python main.py
     fi
     fi
 
 
+    # 启动 Web 服务器(如果配置了)
+    if [ "${ENABLE_WEBSERVER:-false}" = "true" ]; then
+        echo "🌐 启动 Web 服务器..."
+        /usr/local/bin/python manage.py start_webserver
+    fi
+
     echo "⏰ 启动supercronic: ${CRON_SCHEDULE:-*/30 * * * *}"
     echo "⏰ 启动supercronic: ${CRON_SCHEDULE:-*/30 * * * *}"
     echo "🎯 supercronic 将作为 PID 1 运行"
     echo "🎯 supercronic 将作为 PID 1 运行"
-    
+
     exec /usr/local/bin/supercronic -passthrough-logs /tmp/crontab
     exec /usr/local/bin/supercronic -passthrough-logs /tmp/crontab
     ;;
     ;;
 *)
 *)

+ 167 - 14
docker/manage.py

@@ -8,8 +8,14 @@ import os
 import sys
 import sys
 import subprocess
 import subprocess
 import time
 import time
+import signal
 from pathlib import Path
 from pathlib import Path
 
 
+# Web 服务器配置
+WEBSERVER_PORT = int(os.environ.get("WEBSERVER_PORT", "8080"))
+WEBSERVER_DIR = "/app/output"
+WEBSERVER_PID_FILE = "/tmp/webserver.pid"
+
 
 
 def run_command(cmd, shell=True, capture_output=True):
 def run_command(cmd, shell=True, capture_output=True):
     """执行系统命令"""
     """执行系统命令"""
@@ -374,13 +380,13 @@ def restart_supercronic():
     """重启supercronic进程"""
     """重启supercronic进程"""
     print("🔄 重启supercronic...")
     print("🔄 重启supercronic...")
     print("⚠️ 注意: supercronic 是 PID 1,无法直接重启")
     print("⚠️ 注意: supercronic 是 PID 1,无法直接重启")
-    
+
     # 检查当前 PID 1
     # 检查当前 PID 1
     try:
     try:
         with open('/proc/1/cmdline', 'r') as f:
         with open('/proc/1/cmdline', 'r') as f:
             pid1_cmdline = f.read().replace('\x00', ' ').strip()
             pid1_cmdline = f.read().replace('\x00', ' ').strip()
         print(f"  🔍 当前 PID 1: {pid1_cmdline}")
         print(f"  🔍 当前 PID 1: {pid1_cmdline}")
-        
+
         if "supercronic" in pid1_cmdline.lower():
         if "supercronic" in pid1_cmdline.lower():
             print("  ✅ PID 1 是 supercronic")
             print("  ✅ PID 1 是 supercronic")
             print("  💡 要重启 supercronic,需要重启整个容器:")
             print("  💡 要重启 supercronic,需要重启整个容器:")
@@ -394,29 +400,167 @@ def restart_supercronic():
         print("  💡 建议重启容器: docker restart trend-radar")
         print("  💡 建议重启容器: docker restart trend-radar")
 
 
 
 
+def start_webserver():
+    """启动 Web 服务器托管 output 目录"""
+    print(f"🌐 启动 Web 服务器 (端口: {WEBSERVER_PORT})...")
+    print(f"  🔒 安全提示:仅提供静态文件访问,限制在 {WEBSERVER_DIR} 目录")
+
+    # 检查是否已经运行
+    if Path(WEBSERVER_PID_FILE).exists():
+        try:
+            with open(WEBSERVER_PID_FILE, 'r') as f:
+                old_pid = int(f.read().strip())
+            try:
+                os.kill(old_pid, 0)  # 检查进程是否存在
+                print(f"  ⚠️ Web 服务器已在运行 (PID: {old_pid})")
+                print(f"  💡 访问: http://localhost:{WEBSERVER_PORT}")
+                print("  💡 停止服务: python manage.py stop_webserver")
+                return
+            except OSError:
+                # 进程不存在,删除旧的 PID 文件
+                os.remove(WEBSERVER_PID_FILE)
+        except Exception as e:
+            print(f"  ⚠️ 清理旧的 PID 文件: {e}")
+            try:
+                os.remove(WEBSERVER_PID_FILE)
+            except:
+                pass
+
+    # 检查目录是否存在
+    if not Path(WEBSERVER_DIR).exists():
+        print(f"  ❌ 目录不存在: {WEBSERVER_DIR}")
+        return
+
+    try:
+        # 启动 HTTP 服务器
+        # 使用 --bind 绑定到 0.0.0.0 使容器内部可访问
+        # 工作目录限制在 WEBSERVER_DIR,防止访问其他目录
+        process = subprocess.Popen(
+            [sys.executable, '-m', 'http.server', str(WEBSERVER_PORT), '--bind', '0.0.0.0'],
+            cwd=WEBSERVER_DIR,
+            stdout=subprocess.DEVNULL,
+            stderr=subprocess.DEVNULL,
+            start_new_session=True
+        )
+
+        # 等待一下确保服务器启动
+        time.sleep(1)
+
+        # 检查进程是否还在运行
+        if process.poll() is None:
+            # 保存 PID
+            with open(WEBSERVER_PID_FILE, 'w') as f:
+                f.write(str(process.pid))
+
+            print(f"  ✅ Web 服务器已启动 (PID: {process.pid})")
+            print(f"  📁 服务目录: {WEBSERVER_DIR} (只读,仅静态文件)")
+            print(f"  🌐 访问地址: http://localhost:{WEBSERVER_PORT}")
+            print(f"  📄 首页: http://localhost:{WEBSERVER_PORT}/index.html")
+            print("  💡 停止服务: python manage.py stop_webserver")
+        else:
+            print(f"  ❌ Web 服务器启动失败")
+    except Exception as e:
+        print(f"  ❌ 启动失败: {e}")
+
+
+def stop_webserver():
+    """停止 Web 服务器"""
+    print("🛑 停止 Web 服务器...")
+
+    if not Path(WEBSERVER_PID_FILE).exists():
+        print("  ℹ️ Web 服务器未运行")
+        return
+
+    try:
+        with open(WEBSERVER_PID_FILE, 'r') as f:
+            pid = int(f.read().strip())
+
+        try:
+            # 尝试终止进程
+            os.kill(pid, signal.SIGTERM)
+            time.sleep(0.5)
+
+            # 检查进程是否已终止
+            try:
+                os.kill(pid, 0)
+                # 进程还在,强制杀死
+                os.kill(pid, signal.SIGKILL)
+                print(f"  ⚠️ 强制停止 Web 服务器 (PID: {pid})")
+            except OSError:
+                print(f"  ✅ Web 服务器已停止 (PID: {pid})")
+        except OSError as e:
+            if e.errno == 3:  # No such process
+                print(f"  ℹ️ 进程已不存在 (PID: {pid})")
+            else:
+                raise
+
+        # 删除 PID 文件
+        os.remove(WEBSERVER_PID_FILE)
+    except Exception as e:
+        print(f"  ❌ 停止失败: {e}")
+        # 尝试清理 PID 文件
+        try:
+            os.remove(WEBSERVER_PID_FILE)
+        except:
+            pass
+
+
+def webserver_status():
+    """查看 Web 服务器状态"""
+    print("🌐 Web 服务器状态:")
+
+    if not Path(WEBSERVER_PID_FILE).exists():
+        print("  ⭕ 未运行")
+        print(f"  💡 启动服务: python manage.py start_webserver")
+        return
+
+    try:
+        with open(WEBSERVER_PID_FILE, 'r') as f:
+            pid = int(f.read().strip())
+
+        try:
+            os.kill(pid, 0)  # 检查进程是否存在
+            print(f"  ✅ 运行中 (PID: {pid})")
+            print(f"  📁 服务目录: {WEBSERVER_DIR}")
+            print(f"  🌐 访问地址: http://localhost:{WEBSERVER_PORT}")
+            print(f"  📄 首页: http://localhost:{WEBSERVER_PORT}/index.html")
+            print("  💡 停止服务: python manage.py stop_webserver")
+        except OSError:
+            print(f"  ⭕ 未运行 (PID 文件存在但进程不存在)")
+            os.remove(WEBSERVER_PID_FILE)
+            print("  💡 启动服务: python manage.py start_webserver")
+    except Exception as e:
+        print(f"  ❌ 状态检查失败: {e}")
+
+
 def show_help():
 def show_help():
     """显示帮助信息"""
     """显示帮助信息"""
     help_text = """
     help_text = """
 🐳 TrendRadar 容器管理工具
 🐳 TrendRadar 容器管理工具
 
 
 📋 命令列表:
 📋 命令列表:
-  run         - 手动执行一次爬虫
-  status      - 显示容器运行状态
-  config      - 显示当前配置
-  files       - 显示输出文件
-  logs        - 实时查看日志
-  restart     - 重启说明
-  help        - 显示此帮助
+  run              - 手动执行一次爬虫
+  status           - 显示容器运行状态
+  config           - 显示当前配置
+  files            - 显示输出文件
+  logs             - 实时查看日志
+  restart          - 重启说明
+  start_webserver  - 启动 Web 服务器托管 output 目录
+  stop_webserver   - 停止 Web 服务器
+  webserver_status - 查看 Web 服务器状态
+  help             - 显示此帮助
 
 
 📖 使用示例:
 📖 使用示例:
   # 在容器中执行
   # 在容器中执行
   python manage.py run
   python manage.py run
   python manage.py status
   python manage.py status
   python manage.py logs
   python manage.py logs
-  
+  python manage.py start_webserver
+
   # 在宿主机执行
   # 在宿主机执行
   docker exec -it trend-radar python manage.py run
   docker exec -it trend-radar python manage.py run
   docker exec -it trend-radar python manage.py status
   docker exec -it trend-radar python manage.py status
+  docker exec -it trend-radar python manage.py start_webserver
   docker logs trend-radar
   docker logs trend-radar
 
 
 💡 常用操作指南:
 💡 常用操作指南:
@@ -424,18 +568,24 @@ def show_help():
      - 查看 supercronic 是否为 PID 1
      - 查看 supercronic 是否为 PID 1
      - 检查配置文件和关键文件
      - 检查配置文件和关键文件
      - 查看 cron 调度设置
      - 查看 cron 调度设置
-  
-  2. 手动执行测试: run  
+
+  2. 手动执行测试: run
      - 立即执行一次新闻爬取
      - 立即执行一次新闻爬取
      - 测试程序是否正常工作
      - 测试程序是否正常工作
-  
+
   3. 查看日志: logs
   3. 查看日志: logs
      - 实时监控运行情况
      - 实时监控运行情况
      - 也可使用: docker logs trend-radar
      - 也可使用: docker logs trend-radar
-  
+
   4. 重启服务: restart
   4. 重启服务: restart
      - 由于 supercronic 是 PID 1,需要重启整个容器
      - 由于 supercronic 是 PID 1,需要重启整个容器
      - 使用: docker restart trend-radar
      - 使用: docker restart trend-radar
+
+  5. Web 服务器管理:
+     - 启动: start_webserver
+     - 停止: stop_webserver
+     - 状态: webserver_status
+     - 访问: http://localhost:8080
 """
 """
     print(help_text)
     print(help_text)
 
 
@@ -453,6 +603,9 @@ def main():
         "files": show_files,
         "files": show_files,
         "logs": show_logs,
         "logs": show_logs,
         "restart": restart_supercronic,
         "restart": restart_supercronic,
+        "start_webserver": start_webserver,
+        "stop_webserver": stop_webserver,
+        "webserver_status": webserver_status,
         "help": show_help,
         "help": show_help,
     }
     }
 
 

Разница между файлами не показана из-за своего большого размера
+ 511 - 199
main.py


+ 1 - 1
version

@@ -1 +1 @@
-3.4.1
+3.5.0

Некоторые файлы не были показаны из-за большого количества измененных файлов