当前位置:首页>python>Python实现多平台热点聚合 GUI 版

Python实现多平台热点聚合 GUI 版

  • 2026-10-11 08:17:45
Python实现多平台热点聚合 GUI 版

这是一个使用 Python 内置库 tkinter 改造的图形界面(GUI)版本。它保留了你原有脚本的所有核心功能,并将其封装在一个现代化的窗口中,支持实时日志显示和结果查看。

多平台热点聚合 GUI 版

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
多平台热点聚合抓取引擎 - GUI版
支持:知乎热榜、微博热搜、百度热搜、B站排行榜
"""


import json
import os
import sys
import ssl
import time
import certifi
import threading
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox
from urllib.request import urlopen, Request
from urllib.error import URLError, HTTPError

# ---------------- 核心抓取逻辑 (保持原样) ----------------

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))

_SAFE_SSL_CTX = ssl.create_default_context()
_SAFE_SSL_CTX.load_verify_locations(certifi.where())

def_urlopen(req, timeout=10):
return urlopen(req, timeout=timeout, context=_SAFE_SSL_CTX)

HEADERS = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36"
}

deffetch_zhihu(limit=20):
    url = "https://api.zhihu.com/topstory/hot-lists/total?limit={}".format(limit)
try:
        req = Request(url, headers=HEADERS)
with _urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read().decode("utf-8"))
except Exception as e:
return [], f"知乎抓取失败: {str(e)}"

    results = []
for item in data.get("data", []):
        target = item.get("target", {})
        title = target.get("title", "").strip()
ifnot title: continue
        detail = item.get("detail_text", "")
        heat_num = 0
if"万"in detail:
try: heat_num = float(detail.replace("万热度", "").replace("万", "").strip()) * 10000
except ValueError: pass
        results.append({
"title": title, "platform": "知乎", "heat": int(heat_num),
"heat_display": detail, "url": f"https://www.zhihu.com/question/{target.get('id', '')}",
"excerpt": (target.get("excerpt", "") or"")[:100]
        })
return results, "知乎抓取完成"

deffetch_weibo(limit=20):
    url = "https://weibo.com/ajax/side/hotSearch"
    headers = {**HEADERS, "Referer": "https://weibo.com/"}
try:
        req = Request(url, headers=headers)
with _urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read().decode("utf-8"))
except Exception as e:
return [], f"微博抓取失败: {str(e)}"

    results = []
    realtime = data.get("data", {}).get("realtime", [])
for item in realtime[:limit]:
        note = item.get("note", "").strip()
ifnot note: continue
        label = item.get("label_name", "")
if label: note = f"[{label}]{note}"
        results.append({
"title": note, "platform": "微博", "heat": int(item.get("num", 0)),
"heat_display": str(item.get("num", 0)),
"url": f"https://s.weibo.com/weibo?q=%23{item.get('word', item.get('note', ''))}%23",
"excerpt": ""
        })
return results, "微博抓取完成"

deffetch_baidu(limit=20):
    url = "https://top.baidu.com/api/board?platform=wise&tab=realtime"
try:
        req = Request(url, headers=HEADERS)
with _urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read().decode("utf-8"))
except Exception as e:
return [], f"百度抓取失败: {str(e)}"

    results = []
    cards = data.get("data", {}).get("cards", [])
if cards:
        content = cards[0].get("content", [])
for item in content[:limit]:
            query = item.get("query", "").strip()
ifnot query: continue
            results.append({
"title": query, "platform": "百度", "heat": int(item.get("hotScore", 0)),
"heat_display": item.get("desc", "")[:30],
"url": f"https://www.baidu.com/s?wd={query}",
"excerpt": item.get("desc", "")[:100]
            })
return results, "百度抓取完成"

deffetch_bilibili(limit=20):
    url = "https://api.bilibili.com/x/web-interface/ranking/v2?rid=0&type=all"
try:
        req = Request(url, headers=HEADERS)
with _urlopen(req, timeout=10) as resp:
            data = json.loads(resp.read().decode("utf-8"))
except Exception as e:
return [], f"B站抓取失败: {str(e)}"

    results = []
    items = data.get("data", {}).get("list", [])
for item in items[:limit]:
        title = item.get("title", "").strip()
ifnot title: continue
        stat = item.get("stat", {})
        results.append({
"title": title, "platform": "B站", "heat": int(stat.get("view", 0)),
"heat_display": f"{_format_num(stat.get('view', 0))}播放",
"url": item.get("short_link_v2", f"https://www.bilibili.com/video/{item.get('bvid', '')}"),
"excerpt": item.get("description", "")[:100] if item.get("description") else""
        })
return results, "B站抓取完成"

def_format_num(n):
    n = int(n)
if n >= 10000: returnf"{n/10000:.1f}万"
elif n >= 1000: returnf"{n/1000:.1f}k"
return str(n)

# ---------------- GUI 应用逻辑 ----------------

classTrendApp:
def__init__(self, root):
        self.root = root
        self.root.title("多平台热点聚合助手")
        self.root.geometry("900x650")

# 变量
        self.platforms = {
"zhihu": tk.BooleanVar(value=True),
"weibo": tk.BooleanVar(value=True),
"baidu": tk.BooleanVar(value=True),
"bilibili": tk.BooleanVar(value=True)
        }
        self.limit_val = tk.IntVar(value=15)
        self.keyword_val = tk.StringVar()

        self.setup_ui()

defsetup_ui(self):
# 1. 顶部控制栏
        control_frame = ttk.LabelFrame(self.root, text="控制面板", padding=10)
        control_frame.pack(fill=tk.X, padx=10, pady=5)

# 平台选择
        plat_frame = ttk.Frame(control_frame)
        plat_frame.pack(side=tk.LEFT, fill=tk.Y)
        ttk.Label(plat_frame, text="选择平台:").pack(anchor=tk.W)
for key, var in self.platforms.items():
            ttk.Checkbutton(plat_frame, text=key.capitalize(), variable=var).pack(side=tk.LEFT)

# 参数设置
        param_frame = ttk.Frame(control_frame)
        param_frame.pack(side=tk.LEFT, fill=tk.Y, padx=20)

        ttk.Label(param_frame, text="单平台条数:").grid(row=0, column=0, sticky=tk.W)
        ttk.Entry(param_frame, textvariable=self.limit_val, width=8).grid(row=0, column=1, padx=5)

        ttk.Label(param_frame, text="关键词过滤:").grid(row=1, column=0, sticky=tk.W, pady=5)
        ttk.Entry(param_frame, textvariable=self.keyword_val, width=20).grid(row=1, column=1, padx=5, pady=5)

# 按钮
        btn_frame = ttk.Frame(control_frame)
        btn_frame.pack(side=tk.RIGHT)
        self.fetch_btn = ttk.Button(btn_frame, text="开始抓取", command=self.start_fetch_thread)
        self.fetch_btn.pack(pady=10)
        ttk.Button(btn_frame, text="清空结果", command=lambda: self.result_text.delete(1.0, tk.END)).pack()

# 2. 日志显示
        log_frame = ttk.LabelFrame(self.root, text="运行日志", padding=5)
        log_frame.pack(fill=tk.X, padx=10, pady=0)
        self.log_text = scrolledtext.ScrolledText(log_frame, height=6, state='disabled')
        self.log_text.pack(fill=tk.BOTH, expand=True)

# 3. 结果显示
        res_frame = ttk.LabelFrame(self.root, text="热点结果 (按热度排序)", padding=5)
        res_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        self.result_text = scrolledtext.ScrolledText(res_frame, font=("Microsoft YaHei", 10))
        self.result_text.pack(fill=tk.BOTH, expand=True)

deflog(self, message):
        self.log_text.config(state='normal')
        self.log_text.insert(tk.END, f"[{time.strftime('%H:%M:%S')}] {message}\n")
        self.log_text.see(tk.END)
        self.log_text.config(state='disabled')

defstart_fetch_thread(self):
# 检查是否至少选择了一个平台
ifnot any(v.get() for v in self.platforms.values()):
            messagebox.showwarning("提示", "请至少选择一个平台!")
return

        self.fetch_btn.config(state='disabled')
        self.result_text.delete(1.0, tk.END)
        threading.Thread(target=self.run_fetch, daemon=True).start()

defrun_fetch(self):
        all_items = []
        fetch_map = {
"zhihu": fetch_zhihu,
"weibo": fetch_weibo,
"baidu": fetch_baidu,
"bilibili": fetch_bilibili
        }

        limit = self.limit_val.get()
        keyword = self.keyword_val.get().strip()

for name, var in self.platforms.items():
ifnot var.get(): continue

            self.log(f"正在抓取 {name.capitalize()}...")
try:
                items, msg = fetch_map[name](limit)
                self.log(msg)
if items:
# 关键词过滤
if keyword:
                        items = [i for i in items if keyword.lower() in i["title"].lower()]
                    all_items.extend(items)
except Exception as e:
                self.log(f"错误: {str(e)}")

# 排序
        all_items.sort(key=lambda x: x.get("heat", 0), reverse=True)

# 显示结果
        self.display_results(all_items, keyword)

        self.root.after(0, lambda: self.fetch_btn.config(state='normal'))

defdisplay_results(self, items, keyword):
ifnot items:
            self.result_text.insert(tk.END, "未抓取到任何数据。\n")
return

        header = f"=== 热点聚合报告 (关键词: {keyword if keyword else'无'}) ===\n\n"
        self.result_text.insert(tk.END, header)

# 简单分组显示
        current_plat = None
for item in items:
if item['platform'] != current_plat:
                current_plat = item['platform']
                self.result_text.insert(tk.END, f"\n🔥 【{current_plat}】\n", "platform_tag")

            heat_str = f" {item['heat_display']}"if item['heat_display'] else""
            line = f"  • {item['title']}{heat_str}\n"
            self.result_text.insert(tk.END, line)

if item.get('excerpt'):
                self.result_text.insert(tk.END, f"    摘要: {item['excerpt']}\n", "excerpt_tag")

# 配置标签颜色
        self.result_text.tag_config("platform_tag", foreground="
#FF5722", font=("Microsoft YaHei", 11, "bold"))
        self.result_text.tag_config("excerpt_tag", foreground="#666666")

if __name__ == "__main__":
    root = tk.Tk()
# 简单的样式美化
try:
        style = ttk.Style()
        style.theme_use('clam') 
except:
pass

    app = TrendApp(root)
    root.mainloop()

功能特点:

  1. 直观的控制面板:
    • 使用复选框选择你想抓取的平台(知乎、微博、百度、B站)。
    • 可以设置每个平台抓取的条数。
    • 支持关键词过滤(只显示包含关键词的标题)。
  2. 实时日志:底部有一个小的日志窗口,显示当前的抓取进度和报错信息(如果有)。
  3. 结果展示:
    • 大文本框展示所有结果。
    • 按热度自动排序。
    • 对不同平台的标题进行了简单的颜色高亮,方便阅读。
  4. 防卡死设计:使用了多线程(threading),点击“开始抓取”时界面不会卡死。

如何运行:

  1. 确保你安装了 certifi 库(你的原脚本也用到了):
    pip install certifi
  2. 直接运行该 Python 脚本即可弹出窗口。

🔥 cn-hot-trends

中文全平台热搜聚合。知乎·微博·百度·B站·抖音·头条,一键获取。

功能

  • 6大平台热搜 — 知乎/微博/百度/B站/抖音/头条实时热搜
  • 全平台总榜 — 跨平台热度综合排名
  • AI选题推荐 — 基于热搜自动生成内容选题 + 目标平台 + 切入角度 + 建议标题
  • JSON输出 — 方便接入其他工具

快速开始

# 全平台热搜
python3 scripts/fetch_trends.py

# 单平台
python3 scripts/fetch_trends.py --platform zhihu

# AI选题推荐
python3 scripts/fetch_trends.py --platform zhihu --limit 5 --recommend

# JSON格式
python3 scripts/fetch_trends.py --json

AI选题推荐示例

🎯 AI选题推荐
1. 李想朋友圈发飙...
   📍 平台: 知乎 | 专业分析文 | 给背景、分析、结论
   🎯 可写角度: 行业分析 / 竞争格局 / 创始人故事
   📝 建议标题:「关于「李想朋友圈发飙」,我从3个角度拆解」

数据来源

所有数据来自平台公开 API,无需登录无需 Key。

安装

# OpenClaw 用户直接安装
clawhub install freedompixels/cn-hot-trends

# 或手动复制到 skills 目录
cp -r cn-hot-trends ~/.qclaw/skills/

最新文章

随机文章