"""
小红书数据模型定义
使用 Pydantic 定义所有数据结构,提供类型验证和序列化支持
"""
from typing import List, Optional
from pydantic import BaseModel, Field
# ================ Feed 列表相关结构 ================
class ImageInfo(BaseModel):
"""图片信息"""
image_scene: str = Field(alias="imageScene")
url: str
class Cover(BaseModel):
"""封面信息"""
width: int
height: int
url: Optional[str] = None
file_id: Optional[str] = Field(None, alias="fileId")
url_pre: Optional[str] = Field(None, alias="urlPre")
url_default: str = Field(alias="urlDefault")
info_list: List[ImageInfo] = Field(default_factory=list, alias="infoList")
@property
def display_url(self) -> str:
"""获取显示用的 URL,优先使用 url,其次使用 url_default"""
return self.url or self.url_default
class VideoCapability(BaseModel):
"""视频能力信息"""
duration: int # 视频时长,单位秒
class Video(BaseModel):
"""视频信息"""
capa: VideoCapability
class User(BaseModel):
"""用户信息"""
user_id: str = Field(alias="userId")
nickname: Optional[str] = None
nick_name: Optional[str] = Field(None, alias="nickName")
avatar: Optional[str] = None
@property
def display_name(self) -> str:
"""获取显示名称"""
return self.nickname or self.nick_name or ""
class InteractInfo(BaseModel):
"""互动信息"""
liked: bool = False
liked_count: str = Field(default="0", alias="likedCount")
shared_count: str = Field(default="0", alias="sharedCount")
comment_count: str = Field(default="0", alias="commentCount")
collected_count: str = Field(default="0", alias="collectedCount")
collected: bool = False
class NoteCard(BaseModel):
"""笔记卡片信息"""
type: str
display_title: str = Field(alias="displayTitle")
user: User
interact_info: InteractInfo = Field(alias="interactInfo")
cover: Cover
video: Optional[Video] = None # 视频内容,可能为空
class Feed(BaseModel):
"""单个 Feed 项目"""
xsec_token: str = Field(alias="xsecToken")
id: str
model_type: str = Field(alias="modelType")
note_card: Optional[NoteCard] = Field(None, alias="noteCard")
index: int = 0
class FeedsValue(BaseModel):
"""Feeds 的值结构"""
value: List[Feed] = Field(default_factory=list, alias="_value")
class FeedData(BaseModel):
"""Feed 数据结构"""
feeds: FeedsValue
class FeedResponse(BaseModel):
"""从 __INITIAL_STATE__ 中获取的完整 Feed 响应"""
feed: FeedData
# ================ Feed 详情页相关结构 ================
class DetailImageInfo(BaseModel):
"""详情页的图片信息"""
width: int
height: int
url_default: str = Field(alias="urlDefault")
url_pre: str = Field(alias="urlPre")
live_photo: bool = Field(default=False, alias="livePhoto")
class FeedDetail(BaseModel):
"""详情页的笔记内容"""
note_id: str = Field(alias="noteId")
xsec_token: str = Field(alias="xsecToken")
title: str
desc: str
type: str
time: int
ip_location: str = Field(default="", alias="ipLocation")
user: User
interact_info: InteractInfo = Field(alias="interactInfo")
image_list: List[DetailImageInfo] = Field(default_factory=list, alias="imageList")
class Comment(BaseModel):
"""单条评论"""
id: str
note_id: str = Field(alias="noteId")
content: str
like_count: str = Field(default="0", alias="likeCount")
create_time: int = Field(alias="createTime")
ip_location: str = Field(default="", alias="ipLocation")
liked: bool = False
user_info: User = Field(alias="userInfo")
sub_comment_count: str = Field(default="0", alias="subCommentCount")
sub_comments: List["Comment"] = Field(default_factory=list, alias="subComments")
show_tags: List[str] = Field(default_factory=list, alias="showTags")
class CommentList(BaseModel):
"""评论列表"""
list: List[Comment] = Field(default_factory=list)
cursor: str = ""
has_more: bool = Field(default=False, alias="hasMore")
class FeedDetailResponse(BaseModel):
"""Feed 详情页完整响应"""
note: FeedDetail
comments: CommentList
# ================ 用户主页相关结构 ================
class UserBasicInfo(BaseModel):
"""用户的基本信息"""
gender: int = 0
ip_location: str = Field(default="", alias="ipLocation")
desc: str = ""
imageb: str = ""
nickname: str = ""
images: str = ""
red_id: str = Field(alias="redId")
class UserInteractions(BaseModel):
"""用户的关注、粉丝、收藏量"""
type: str # follows, fans, interaction
name: str # 关注, 粉丝, 获赞与收藏
count: str # 数量
class UserPageData(BaseModel):
"""用户的详细信息"""
class RawValue(BaseModel):
interactions: List[UserInteractions] = Field(default_factory=list)
basic_info: UserBasicInfo = Field(alias="basicInfo")
raw_value: RawValue = Field(alias="_rawValue")
class UserProfileResponse(BaseModel):
"""用户详情页完整响应"""
user_basic_info: UserBasicInfo = Field(alias="userBasicInfo")
interactions: List[UserInteractions] = Field(default_factory=list)
feeds: List[Feed] = Field(default_factory=list)
# 更新前向引用
Comment.model_rebuild()