161 lines
5.0 KiB
Python
161 lines
5.0 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
热点发现模块
|
|
负责从小红书搜索热门科技话题
|
|
"""
|
|
|
|
import subprocess
|
|
import json
|
|
import re
|
|
from typing import List, Dict, Optional
|
|
|
|
class TopicDiscovery:
|
|
"""热点话题发现器"""
|
|
|
|
def __init__(self):
|
|
self.keyword = "AI科技"
|
|
|
|
def search_notes(self, keyword: str = None, limit: int = 5) -> List[Dict]:
|
|
"""
|
|
搜索小红书笔记
|
|
|
|
Args:
|
|
keyword: 搜索关键词
|
|
limit: 返回数量限制
|
|
|
|
Returns:
|
|
笔记列表,每个包含id, title, likes, desc等信息
|
|
"""
|
|
keyword = keyword or self.keyword
|
|
|
|
try:
|
|
# 执行xhs搜索命令
|
|
result = subprocess.run(
|
|
['xhs', 'search', keyword],
|
|
capture_output=True, text=True, timeout=30
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
print(f"搜索失败: {result.stderr}")
|
|
return []
|
|
|
|
# 解析YAML输出
|
|
return self._parse_search_result(result.stdout, limit)
|
|
|
|
except Exception as e:
|
|
print(f"搜索异常: {e}")
|
|
return []
|
|
|
|
def _parse_search_result(self, output: str, limit: int) -> List[Dict]:
|
|
"""解析搜索结果"""
|
|
notes = []
|
|
|
|
try:
|
|
# 简单解析:提取id和title
|
|
# 实际应该解析YAML,这里简化处理
|
|
import yaml
|
|
data = yaml.safe_load(output)
|
|
|
|
if data and 'data' in data and 'items' in data['data']:
|
|
for item in data['data']['items'][:limit]:
|
|
if 'note_card' in item:
|
|
card = item['note_card']
|
|
note = {
|
|
'id': item.get('id', ''),
|
|
'title': card.get('display_title', ''),
|
|
'desc': card.get('desc', '')[:200],
|
|
'likes': card.get('interact_info', {}).get('liked_count', '0'),
|
|
'author': card.get('user', {}).get('nickname', ''),
|
|
'images': len(card.get('image_list', []))
|
|
}
|
|
notes.append(note)
|
|
|
|
except Exception as e:
|
|
print(f"解析结果异常: {e}")
|
|
|
|
return notes
|
|
|
|
def read_note_detail(self, note_id: str) -> Optional[Dict]:
|
|
"""
|
|
读取笔记详情
|
|
|
|
Args:
|
|
note_id: 笔记ID
|
|
|
|
Returns:
|
|
笔记详细信息
|
|
"""
|
|
try:
|
|
result = subprocess.run(
|
|
['xhs', 'read', note_id],
|
|
capture_output=True, text=True, timeout=30
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
return None
|
|
|
|
# 解析详情
|
|
import yaml
|
|
data = yaml.safe_load(result.stdout)
|
|
|
|
if data and 'data' in data and 'items' in data['data']:
|
|
item = data['data']['items'][0]
|
|
card = item.get('note_card', {})
|
|
return {
|
|
'id': note_id,
|
|
'title': card.get('display_title', ''),
|
|
'desc': card.get('desc', ''),
|
|
'likes': card.get('interact_info', {}).get('liked_count', '0'),
|
|
'comments': card.get('interact_info', {}).get('comment_count', '0'),
|
|
'tags': [t.get('name', '') for t in card.get('tag_list', [])]
|
|
}
|
|
|
|
except Exception as e:
|
|
print(f"读取详情异常: {e}")
|
|
|
|
return None
|
|
|
|
def extract_topic(self, note: Dict) -> str:
|
|
"""
|
|
从笔记中提取话题关键词
|
|
|
|
Args:
|
|
note: 笔记信息
|
|
|
|
Returns:
|
|
话题关键词
|
|
"""
|
|
title = note.get('title', '')
|
|
desc = note.get('desc', '')
|
|
|
|
# 简单的关键词提取逻辑
|
|
# 实际可以使用NLP或关键词提取算法
|
|
keywords = []
|
|
|
|
# 从标题提取
|
|
if 'AI' in title or '人工智能' in title:
|
|
keywords.append("AI产业趋势")
|
|
if '芯片' in title:
|
|
keywords.append("芯片技术")
|
|
if '机器人' in title:
|
|
keywords.append("机器人技术")
|
|
|
|
# 如果没有匹配到,使用默认
|
|
if not keywords:
|
|
keywords.append("科技趋势分析")
|
|
|
|
return keywords[0] if keywords else "AI科技"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# 测试
|
|
discovery = TopicDiscovery()
|
|
notes = discovery.search_notes("AI科技", limit=3)
|
|
|
|
print(f"找到 {len(notes)} 篇热门笔记:")
|
|
for note in notes:
|
|
print(f"\n📱 {note['title'][:40]}...")
|
|
print(f" 👍 {note['likes']} 📷 {note['images']}张")
|
|
topic = discovery.extract_topic(note)
|
|
print(f" 🏷️ 话题: {topic}")
|