mirror of
https://github.com/NanmiCoder/MediaCrawler.git
synced 2026-07-25 22:10:29 +08:00
- 调整 .gitignore,避免误忽略 webui/src/lib/ 和 webui/src/components/env/ - 补齐 WebUI 缺失的 lib 工具函数、API 封装及环境检测组件 - 修复 /api/env/check 使用相对路径导致启动目录不同时检测失败的问题 - 更新中/英/西三语 README 的 WebUI 开发调试与生产构建说明
142 lines
2.9 KiB
TypeScript
142 lines
2.9 KiB
TypeScript
export interface ParsedId {
|
|
id: string
|
|
type: 'video' | 'creator' | 'unknown'
|
|
original: string
|
|
isValid: boolean
|
|
}
|
|
|
|
// URL patterns for different platforms
|
|
const platformPatterns: Record<string, {
|
|
video: RegExp[]
|
|
creator: RegExp[]
|
|
}> = {
|
|
xhs: {
|
|
video: [
|
|
/xiaohongshu\.com\/explore\/([a-zA-Z0-9]+)/,
|
|
/xiaohongshu\.com\/discovery\/item\/([a-zA-Z0-9]+)/,
|
|
/xhslink\.com\/([a-zA-Z0-9]+)/,
|
|
],
|
|
creator: [
|
|
/xiaohongshu\.com\/user\/profile\/([a-zA-Z0-9]+)/,
|
|
],
|
|
},
|
|
dy: {
|
|
video: [
|
|
/douyin\.com\/video\/(\d+)/,
|
|
/v\.douyin\.com\/([a-zA-Z0-9]+)/,
|
|
/iesdouyin\.com\/share\/video\/(\d+)/,
|
|
],
|
|
creator: [
|
|
/douyin\.com\/user\/([a-zA-Z0-9_-]+)/,
|
|
],
|
|
},
|
|
bili: {
|
|
video: [
|
|
/bilibili\.com\/video\/(BV[a-zA-Z0-9]+)/,
|
|
/bilibili\.com\/video\/(av\d+)/,
|
|
/b23\.tv\/([a-zA-Z0-9]+)/,
|
|
],
|
|
creator: [
|
|
/space\.bilibili\.com\/(\d+)/,
|
|
],
|
|
},
|
|
wb: {
|
|
video: [
|
|
/weibo\.com\/\d+\/([a-zA-Z0-9]+)/,
|
|
/m\.weibo\.cn\/status\/(\d+)/,
|
|
],
|
|
creator: [
|
|
/weibo\.com\/u\/(\d+)/,
|
|
/weibo\.com\/([a-zA-Z0-9]+)$/,
|
|
],
|
|
},
|
|
ks: {
|
|
video: [
|
|
/kuaishou\.com\/short-video\/([a-zA-Z0-9_-]+)/,
|
|
/v\.kuaishou\.com\/([a-zA-Z0-9]+)/,
|
|
],
|
|
creator: [
|
|
/kuaishou\.com\/profile\/([a-zA-Z0-9_-]+)/,
|
|
],
|
|
},
|
|
}
|
|
|
|
export function parseUrl(input: string, platform: string): ParsedId {
|
|
const trimmed = input.trim()
|
|
|
|
// If it's just an ID (no URL structure), return as unknown type
|
|
if (!trimmed.includes('/') && !trimmed.includes('.')) {
|
|
return {
|
|
id: trimmed,
|
|
type: 'unknown',
|
|
original: trimmed,
|
|
isValid: trimmed.length > 0,
|
|
}
|
|
}
|
|
|
|
const patterns = platformPatterns[platform]
|
|
if (!patterns) {
|
|
return {
|
|
id: trimmed,
|
|
type: 'unknown',
|
|
original: trimmed,
|
|
isValid: false,
|
|
}
|
|
}
|
|
|
|
// Try video patterns
|
|
for (const pattern of patterns.video) {
|
|
const match = trimmed.match(pattern)
|
|
if (match && match[1]) {
|
|
return {
|
|
id: match[1],
|
|
type: 'video',
|
|
original: trimmed,
|
|
isValid: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
// Try creator patterns
|
|
for (const pattern of patterns.creator) {
|
|
const match = trimmed.match(pattern)
|
|
if (match && match[1]) {
|
|
return {
|
|
id: match[1],
|
|
type: 'creator',
|
|
original: trimmed,
|
|
isValid: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fallback: try to extract any ID-like segment
|
|
const urlMatch = trimmed.match(/([a-zA-Z0-9_-]{6,})/)
|
|
if (urlMatch) {
|
|
return {
|
|
id: urlMatch[1],
|
|
type: 'unknown',
|
|
original: trimmed,
|
|
isValid: false,
|
|
}
|
|
}
|
|
|
|
return {
|
|
id: trimmed,
|
|
type: 'unknown',
|
|
original: trimmed,
|
|
isValid: false,
|
|
}
|
|
}
|
|
|
|
export function parseMultipleUrls(input: string, platform: string): ParsedId[] {
|
|
if (!input.trim()) return []
|
|
|
|
const items = input
|
|
.split(/[,\n]+/)
|
|
.map(s => s.trim())
|
|
.filter(Boolean)
|
|
|
|
return items.map(item => parseUrl(item, platform))
|
|
}
|