同步家纺情报 v2 数据、59 个严格权威源、趋势图库、移动端交互、Google/Yandex 翻译门控及静态 SEO/GEO 构建。 补充面向 C# 研发的 README,明确当前无 LLM、多模态与生图模型,记录翻译请求参数、缓存与失败策略、数据处理边界、前端职责和无 GitHub Pages 部署流程。 新增按日期倒序维护的 CHANGELOG,记录影响、验证与代码/数据/dist 回滚方法。 验证:11 个 Python 契约测试、13 个 Node 前端测试通过;静态构建生成 1096 个 Sitemap URL。
94 lines
4.1 KiB
Python
94 lines
4.1 KiB
Python
"""家纺与时装 RSS 来源及相关性筛选。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from typing import Any
|
|
|
|
|
|
FASHION_TREND_FEEDS: list[dict[str, Any]] = [
|
|
{
|
|
"name": "Hypebeast 中文",
|
|
"url": "https://hypebeast.cn/fashion/feed",
|
|
"category": "时装趋势",
|
|
"category_key": "fashion_trends",
|
|
},
|
|
{
|
|
"name": "GQ Hong Kong",
|
|
"url": "https://gqhongkong.com/style/feed/",
|
|
"category": "时装趋势",
|
|
"category_key": "fashion_trends",
|
|
},
|
|
{
|
|
"name": "Citta Bella 都会佳人",
|
|
"url": "https://cittabella.my/category/fashion/feed/",
|
|
"category": "时装趋势",
|
|
"category_key": "fashion_trends",
|
|
},
|
|
]
|
|
|
|
CURATED_TREND_PAGES: list[dict[str, str]] = [
|
|
{
|
|
"name": "ASInsight",
|
|
"url": "https://www.asinsight.com/report/US/cooling-duvet-cover",
|
|
"category": "趋势博客",
|
|
"category_key": "trend_blogs",
|
|
},
|
|
]
|
|
|
|
FREE_TREND_FEEDS: list[dict[str, Any]] = [
|
|
{"name": "Dezeen - Textiles", "url": "https://www.dezeen.com/tag/textiles/feed/"},
|
|
{"name": "Dezeen - Fashion", "url": "https://www.dezeen.com/tag/fashion-tag/feed/"},
|
|
{"name": "Dezeen - Clothing", "url": "https://www.dezeen.com/tag/clothing/feed/"},
|
|
{"name": "Dezeen - Homeware", "url": "https://www.dezeen.com/tag/homeware/feed/"},
|
|
{"name": "ArchDaily - Fabrics", "url": "https://www.archdaily.com/tag/fabrics/feed/"},
|
|
{"name": "Trendland", "url": "https://trendland.com/feed/"},
|
|
{"name": "Design Milk", "url": "https://design-milk.com/feed/"},
|
|
{"name": "Designboom", "url": "https://www.designboom.com/feed/"},
|
|
{"name": "Fibre2Fashion - Textiles", "url": "https://feeds.feedburner.com/fibre2fashion/textile-news"},
|
|
{"name": "Fibre2Fashion - Fashion", "url": "https://feeds.feedburner.com/fibre2fashion/fashion-news"},
|
|
] + FASHION_TREND_FEEDS
|
|
|
|
FASHION_REFERENCE_KEYWORDS: tuple[str, ...] = (
|
|
"runway", "lookbook", "fashion week", "couture", "ready-to-wear", "menswear", "womenswear",
|
|
"tailoring", "apparel", "garment", "outfit", "textile", "fabric",
|
|
"embroidery", "knit", "woven", "jacquard", "denim", "dress", "shirt", "jacket", "coat",
|
|
"trousers", "pants", "skirt", "suit", "home textile", "bedding", "bed linen",
|
|
"時裝", "时装", "秀場", "秀场", "時裝週", "时装周", "大秀", "春夏", "秋冬",
|
|
"男裝", "男装", "女裝", "女装", "成衣", "高訂", "高定", "型錄", "型录",
|
|
"服裝", "服装", "服飾", "服饰", "穿搭", "剪裁", "廓形", "面料", "布料",
|
|
"織物", "织物", "印花", "刺繡", "刺绣", "針織", "针织", "提花", "牛仔",
|
|
"西裝", "西装", "襯衫", "衬衫", "外套", "洋裝", "洋装", "紡織", "纺织",
|
|
"家紡", "家纺", "床品", "床上用品",
|
|
)
|
|
|
|
SURFACE_DESIGN_KEYWORDS: tuple[str, ...] = (
|
|
"pattern", "texture", "motif", "surface design", "紋樣", "纹样", "圖案", "图案",
|
|
"紋理", "纹理", "肌理", "流行趨勢", "流行趋势",
|
|
)
|
|
|
|
NON_TEXTILE_TITLE_KEYWORDS: tuple[str, ...] = (
|
|
"watch", "watches", "jewelry", "jewellery", "eyewear", "sunglasses", "handbag", "footwear",
|
|
"sneaker", "perfume", "fragrance", "cosmetic", "腕表", "腕錶", "手表", "手錶", "珠宝", "珠寶",
|
|
"首饰", "首飾", "眼镜", "眼鏡", "太阳镜", "太陽鏡", "包袋", "手袋", "手包", "鞋", "靴",
|
|
"香水", "香氛", "彩妆", "彩妝", "美妆", "美妝",
|
|
)
|
|
|
|
|
|
def is_fashion_reference(title: str, content: str) -> bool:
|
|
"""判断内容是否具备服装、秀场或纺织设计参考价值。"""
|
|
title_text = title.lower()
|
|
haystack = f"{title} {content}".lower()
|
|
|
|
def contains(text: str, keyword: str) -> bool:
|
|
token = keyword.lower()
|
|
if token.isascii():
|
|
return re.search(rf"(?<![a-z]){re.escape(token)}(?![a-z])", text) is not None
|
|
return token in text
|
|
|
|
if any(contains(title_text, keyword) for keyword in NON_TEXTILE_TITLE_KEYWORDS):
|
|
return False
|
|
if any(contains(haystack, keyword) for keyword in FASHION_REFERENCE_KEYWORDS):
|
|
return True
|
|
return any(contains(title_text, keyword) for keyword in SURFACE_DESIGN_KEYWORDS)
|