下载脚本
bbdowner.ps1
# 从 bilibili 下载视频并转为 mp3
# 调用了 bbdown 命令, dotnet tool install -g bbdown
# 调用了 ffmpeg 命令, brew install ffmpeg
$ErrorActionPreference = 'stop'
# 兼容一些低版本的 .net 工具
$env:DOTNET_ROLL_FORWARD = "LatestMajor"
class BbDownloader {
# 解析传入的链接文本, 获取链接并下载视频到桌面
[void] DownloadFromContentToDesktop([string]$urlContent) {
[string[]]$urls = $urlContent -split "[\r\n]" |
ForEach-Object { $this.FormatUrl($_) } |
Where-Object { $_.Length -gt 0 }
# $urls 去重
$urls = $urls | Select-Object -Unique
$this.DownloadToDesktop($urls)
}
# 格式化链接
[string] FormatUrl([string]$url) {
# 正则取 https://www.bilibili.com/video/ 开头到空格为止
$matche = [Regex]::Match($url, "https://www.bilibili.com/video/[^ ]+")
if (-not $matche.Success) {
return ""
}
$url = $matche.Value
# url 去掉 ?后的部分
[System.UriBuilder]$uri = [System.UriBuilder]::new($url)
$uri.Query = ""
$url = "$($uri.Uri)"
return $url
}
# 下载视频到桌面
[void] DownloadToDesktop([string[]]$urls) {
$desktop = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::Desktop)
$mp3Dir = Join-Path $desktop -ChildPath "mp3"
$this.Download($urls, $mp3Dir)
}
[void] Download([string[]]$urls, [string]$outputDir) {
foreach ($url in $urls) {
Write-Host "处理链接 $url"
$tmpDir = Join-Path $([System.IO.Path]::GetTempPath()) -ChildPath $([System.IO.Path]::GetRandomFileName())
Write-Host "临时目录 $tmpDir"
New-Item -Path $tmpDir -ItemType Directory | Out-Null
$current = Get-Location
Set-Location $tmpDir
try {
$videoFile = $this.DownloadVideoFromUrl($url)
$mp3File = $this.ConvertVideoToMp3($videoFile)
$this.MoveFileToOutputDir($mp3File, $outputDir)
}
finally {
Set-Location $current
Remove-Item -Path $tmpDir -Recurse -Force
# Start-Process 'open' $tmpDir
}
}
Start-Process "open" -ArgumentList $outputDir
Write-Host "处理完成"
}
# 移动文件到输出目录
[void] MoveFileToOutputDir([string]$file, [string]$outputDir) {
New-Item -Path $outputDir -ItemType Directory -Force | Out-Null
$fileName = [System.IO.Path]::GetFileName($file)
$outputFile = Join-Path $outputDir -ChildPath $fileName
Move-Item $file -Destination $outputFile -Force
}
# 使用 ffmpeg 转换视频
[string] ConvertVideoToMp3([string]$videoFile) {
$mp3File = [System.IO.Path]::ChangeExtension($videoFile, ".mp3")
# 调用 ffmpeg 转换视频
$command = "ffmpeg -i '$videoFile' -vn -acodec libmp3lame -qscale:a 0 -ac 2 '$mp3File' -y 2>&1"
Write-Host $command
Invoke-Expression $command | Out-Host
if ($LASTEXITCODE -ne 0) {
throw "FFmpeg 转换失败!"
}
return $mp3File
}
[string] GetSafeFileName([string]$fileName, [string]$replacement = "_") {
# 1. 获取非法字符
$invalidChars = [System.IO.Path]::GetInvalidFileNameChars()
$pattern = "[{0}]" -f [regex]::Escape(-join $invalidChars)
# 2. 替换非法字符
$result = $fileName -replace $pattern, $replacement
# 3. 移除不可见控制字符并修剪两端
$result = $result -replace "[\x00-\x1f]", ""
return $result.Trim()
}
[string] GetDownloadMp4File() {
$filePath = Get-ChildItem -Filter *.mp4 | Select-Object -First 1 | ForEach-Object { $_.FullName }
if ($filePath -and $(Test-Path $filePath)) {
return $filePath
}
Write-Host "可能有多首音乐"
# 找到第一个 mp4 文件认为是需要的音乐
$mp4File = Get-ChildItem -Filter *.mp4 -Recurse | Select-Object -First 1 | ForEach-Object { $_.FullName }
if (-not $mp4File -and $(Test-Path $mp4File)) {
throw "没有找到视频文件"
}
# 找到第一个文件夹认为是需要的音乐文件名
$dirPath = Get-ChildItem -Directory | Select-Object -First 1 # | ForEach-Object { $_.Name }
if (-not $dirPath -and $(Test-Path $dirPath)) {
throw "没有找到视频文件所在目录"
}
$dirName = [System.IO.Path]::GetFileName($dirPath)
$dirRoot = [System.IO.Path]::GetDirectoryName($dirPath)
$fileName = $this.GetSafeFileName($dirName, "-")
$ext = [System.IO.Path]::GetExtension($mp4File)
$filePath = Join-Path $dirRoot -ChildPath "$($fileName)$($ext)"
[System.IO.File]::Copy($mp4File, $filePath)
# Copy-Item $mp4File -Destination $filePath
# Move-Item $mp4File -Destination $filePath
if (-not $? -or (-not $filePath) -or (-not (Test-Path $filePath))) {
throw "复制视频文件失败"
}
return $filePath
}
# 使用 bbdown 下载视频, 并得到 视频文件
[string] DownloadVideoFromUrl([string]$url) {
BBDown $url 2>&1 | Out-Host
if ($LASTEXITCODE -ne 0) {
throw "bbdown 命令执行失败, 错误码 $LASTEXITCODE"
}
return $this.GetDownloadMp4File()
}
}
# 一行一个下载链接
$urls = "
22 Attr href https://www.bilibili.com/video/BV1vrCdYvEQb?spm_id_from=333.1387.favlist.content.click
23 Attr href https://www.bilibili.com/video/BV1vrCdYvEQb?spm_id_from=333.1387.favlist.content.click
"
$bbDownloader = [BbDownloader]::new()
$bbDownloader.DownloadFromContentToDesktop($urls)