Files
MediaCrawler/webui/src/lib/urlParser.ts
程序员阿江(Relakkes) 076dcba978 fix: 修复 WebUI 源码缺失、环境检测路径及文档说明
- 调整 .gitignore,避免误忽略 webui/src/lib/ 和 webui/src/components/env/
- 补齐 WebUI 缺失的 lib 工具函数、API 封装及环境检测组件
- 修复 /api/env/check 使用相对路径导致启动目录不同时检测失败的问题
- 更新中/英/西三语 README 的 WebUI 开发调试与生产构建说明
2026-07-01 23:32:10 +08:00

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))
}