基于PowerShell和yt-dlp的简单大批量cookie登录+正常浏览伪装的视频下载器 更新5
❀原创教程,转载本页必须注明链接和作者
❀目前本文档处于发布早期,代码可能会不稳~
因油管河蟹,及不慎手抽而痛失收藏视频,遂慌,借PowerShell bbenc工程代码而凑此物. (文言文太差,尽力了)
使用前,要在设置-->更新和安全-->开发者选项中解除PowerShell的运行限制,如图:
代码如下,拷下来用Unicode/UTF-8编码保存为yt-dlp-ops.ps1
运行即可(⊙_◎):
Function whereisit($startPath='DESKTOP') {
#启用System.Windows.Forms选择文件的GUI交互窗,通过SelectedPath将GUI交互窗锁定到桌面文件夹, 效果一般
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
Add-Type -AssemblyName System.Windows.Forms
$startPath = New-Object System.Windows.Forms.OpenFileDialog -Property @{ InitialDirectory = [Environment]::GetFolderPath('DESKTOP') }#GUI交互窗锁定到桌面文件夹
Do {$dInput = $startPath.ShowDialog()} While ($dInput -eq "Cancel") #1.打开选择文件的GUI交互窗, 通过重新打开选择窗来反取消用户的取消操作. 2. 窗口大, TopMost关
return $startPath.FileName
}
Function whichlocation($startPath='DESKTOP') {
#启用System.Windows.Forms选择文件夹的GUI交互窗
Add-Type -AssemblyName System.Windows.Forms
$startPath = New-Object System.Windows.Forms.FolderBrowserDialog -Property @{ Description="选择路径用的窗口. 拖拽边角可放大以便操作"; SelectedPath=[Environment]::GetFolderPath($startPath); RootFolder='MyComputer'; ShowNewFolderButton=$true }
#打开选择文件的GUI交互窗, 用Do-While循环拦截误操作(取消/关闭选择窗)
Do {$dInput = $startPath.ShowDialog((New-Object System.Windows.Forms.Form -Property @{TopMost=$true}))} While ($dInput -eq "Cancel") #2. 窗口小, TopMost开
#由于选择根目录时路径变量含"\", 而文件夹时路径变量缺"\", 所以要自动判断并补上
if (($startPath.SelectedPath.SubString($startPath.SelectedPath.Length-1) -eq "\") -eq $false) {$startPath.SelectedPath+="\"}
return $startPath.SelectedPath
}
Function Read-MultiLineInputDialog([string]$Message, [string]$WindowTitle, [string]$DefaultText) {#「@Daniel Schroeder」多行文本输入框
$DebugPreference = 'Continue'
if (($host.name -match 'consolehost')) { #PowerShell窗口
Write-Debug "√ 运行于PowerShell Console窗口中,使用GWMI分辨率信息"
$oWidth = gwmi win32_videocontroller | select-object CurrentHorizontalResolution -first 1
$oHeight = gwmi win32_videocontroller | select-object CurrentVerticalResolution -first 1
[int]$mWidth = [Convert]::ToInt32($oWidth.CurrentHorizontalResolution)
[int]$mHeight = [Convert]::ToInt32($oHeight.CurrentVerticalResolution)
#Write-Debug "√ $mWidth x $mHeight"
}
else { #PowerShell ISE窗口
Write-Debug "√ 运行于PowerShell ISE窗口中,使用系统分辨率信息"
[int]$mWidth = [System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Width
[int]$mHeight = [System.Windows.Forms.SystemInformation]::PrimaryMonitorSize.Height
}
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms
#根据显示器大小换算窗口内说明文本起始位置和大小
[int]$LBStartX = [math]::Round($mWidth /192)
[int]$LBStartY = [math]::Round($mHeight/108)
[int]$LblSizeX = [math]::Round($mWidth /19)
[int]$LblSizeY = [math]::Round($mHeight/54)
# 窗口内说明文本
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Size($LBStartX,$LBStartY) #非换算
$label.Size = New-Object System.Drawing.Size($LblSizeX,$LblSizeY) #非换算,$Message太长则增加
$label.AutoSize = $true
$label.Text = $Message
#根据显示器大小换算文本框起始位置和大小
[int]$TBStartX = [math]::Round($mWidth /192)
[int]$TBStartY = [math]::Round($mHeight/27)
[int]$TblSizeX = [math]::Round($mWidth /3.73)
[int]$TblSizeY = [math]::Round($mHeight/2.57)
#绘制文本框
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Size($TBStartX,$TBStartY) #文本框左上起始位,非换算
$textBox.Size = New-Object System.Drawing.Size($TblSizeX,$TblSizeY) #文本框大小,换算X-Y
$textBox.Font = New-Object System.Drawing.Font((New-Object System.Windows.Forms.Form).font.Name,10) #修复高DPI下字号过小的"bug"
$textBox.AcceptsReturn = $true
$textBox.AcceptsTab = $false
$textBox.Multiline = $true
$textBox.ScrollBars = 'Both'
$textBox.Text = $DefaultText
#根据显示器大小换算OK按钮起始位置和大小
[int]$OKStartX = [math]::Round($mWidth /4.7)
[int]$OKStartY = [math]::Round($mHeight/108)
[int]$OKbSizeX = [math]::Round($mWidth /34.92)
[int]$OKbSizeY = [math]::Round($mHeight/47)
#绘制OK按钮
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Size($OKStartX,$OKStartY) #OK按钮左上起始位,换算
$okButton.Size = New-Object System.Drawing.Size($OKbSizeX,$OKbSizeY) #OK按钮大小,换算
$okButton.Text = "确认"
$okButton.DialogResult = "OK"
$okButton.Add_Click({$form.Tag = $textBox.Text; $form.Close()})
#根据显示器大小换算Cancel按钮起始位置
[int]$ClStartX = [math]::Round($mWidth /4.08)
[int]$ClStartY = $OKStartY
[int]$ClbSizeX = $OKbSizeX
[int]$ClbSizeY = $OKbSizeY
#绘制Cancel按钮
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Size($ClStartX,$ClStartY)
$cancelButton.Size = New-Object System.Drawing.Size($ClbSizeX,$ClbSizeY)
$cancelButton.Text = "取消"
$cancelButton.DialogResult = "Cancel"
$cancelButton.Add_Click({$form.Tag = $null; $form.Close()})
#根据显示器分辨率换算窗口大小
[int]$formSizeX = [math]::Round($mWidth /3.56)
[int]$formSizeY = [math]::Round($mHeight/2.18)
#绘制窗口
$form = New-Object System.Windows.Forms.Form
$form.Text = $WindowTitle
$form.Size = New-Object System.Drawing.Size($formSizeX,$formSizeY) #完整窗口大小,换算
$form.FormBorderStyle = 'FixedSingle'
$form.StartPosition = "CenterScreen"
$form.AutoSizeMode = 'GrowAndShrink'
$form.Topmost = $True
$form.AcceptButton = $okButton
$form.CancelButton = $cancelButton
$form.ShowInTaskbar = $true
#将控制元素添加到绘制的窗口
$form.Controls.Add($label); $form.Controls.Add($textBox); $form.Controls.Add($okButton); $form.Controls.Add($cancelButton)
#初始化并显示窗口
$form.Add_Shown({$form.Activate()})
#用Do-While循环拦截误操作(取消/关闭选择窗)
Do {$dInput = $form.ShowDialog(); if ($dInput -eq "Cancel") {Write-Debug "× 不可取消,请关闭PowerShell窗口"}} While ($dInput -eq "Cancel")
#回执输入内容
return $form.Tag
}
#「@MrNetTek」高DPI显示渲染模式的System.Windows.Forms
Add-Type -TypeDefinition @'
using System.Runtime.InteropServices;
public class ProcessDPI {
[DllImport("user32.dll", SetLastError=true)]
public static extern bool SetProcessDPIAware();
}
'@
$null = [ProcessDPI]::SetProcessDPIAware()
clear
#准备一个记事本窗口,将所有要下载的视频链接粘贴进去
$link=""
Do {($link = Read-MultiLineInputDialog -Message "★ 粘贴所有要下载的视频链接,多个链接通过换行区分" -WindowTitle "★ yt-dlp-ops 下载链接输入窗口" -DefaultText ""); if ($link -eq "") {Write-Error "× 输入了空值,重试"}} While ($link -eq "")
Do {Read-Host "`r`n将打开[选择视频下载路径]的选择窗,按Enter继续"; $DownloadPath = whichlocation; $DownloadPath #下载视频路径
Read-Host "`r`n将打开[选择yt-dlp.exe]的选择窗,按Enter继续"; $ytdlpAppPath = whereisit; $ytdlpAppPath #下载器路径
Read-Host "`r`n将打开[导出批处理路径]的选择窗,按Enter继续"; $CmdPrintPath = whichlocation; $CmdPrintPath #导出批处理路径
""
if (Test-Path $DownloadPath) {Write-Host "√ yt-dlp.exe路径正常"} else {Write-Error "× yt-dlp.exe路径异常"; pause; exit}
if (Test-Path $ytdlpAppPath) {Write-Host "√ 视频文件夹路径正常"} else {Write-Error "× 视频文件夹路径异常"; pause; exit}
if (Test-Path $CmdPrintPath) {Write-Host "√ 导出批处理路径正常"} else {Write-Error "× 导出批处理路径异常"; pause; exit}
""
} While ((Test-Path $ytdlpAppPath) + (Test-Path $DownloadPath) + (Test-Path $CmdPrintPath) -ne 3) #$true+$true+$true=3
$CookieIOPath = $DownloadPath+"ytdlpCookies.txt" #导出和后来导入Cookie用的txt
$brwsrSelect=$cookieExp=""
Switch (Read-Host "输入y以添加一行[导出当前浏览器cookie]的命令,或按Enter跳过") {
y {
$brwsrSelect = Switch (Read-Host "选择含登录Cookie的浏览器 [A: Chrome | B: Brave | C: Chromium | D: Opera | E: Edge | F: Firefox | G: Safari | H: Vivaldi]") {
a {"Chrome"} b {"Brave"} c {"Chromium"} d {"Opera"} e {"Edge"} f {"Firefox"} g {"Safari"} h {"Vivaldi"} default {"Chromium"}
}
$cookieExp = "$ytdlpAppPath --ignore-errors --cookies-from-browser $brwsrSelect --cookies $CookieIOPath"
Write-Output "!仅导出Cookies的命令会导致yt-dlp弹出没有视频下载链接的报错,无视即可`n"
}
Default {"√ 跳过"}
}
$cookieImp = "--cookies $CookieIOPath" #此处完成yt-dlp导出以及导入cookies的命令
$CmdPrint = $CmdPrintPath+"yt-dlp-download.bat"; "`r`n将导出批处理文件:$CmdPrint" #此处完成批处理导出路径的搭建
if (Test-Path $CmdPrint) {Remove-Item $CmdPrint} #由于写入使用了 >> 所以需要通过检测删除机制覆盖原始文件
$ctrl_gen = @()
$ctrl_gen += "
chcp 65001
@echo off"
if ($brwsrSelect -ne "") {
$ctrl_gen+="
@ECHO 从浏览器生成cookies到$CookieIOPath"
$ctrl_gen+=$cookieExp
} #将导出cookie的命令写入控制批处理
$ctrl_gen += "
@ECHO 下载视频与随机间隔"
$link.Split("`r`n").Trim() | where {$_ -ne ""} | ForEach-Object {
$ctrl_gen+="timeout /nobreak /t "+(Get-Random -InputObject 1,2,3,4,5,6,7).ToString() #每个下载随机间隔1~7秒以降低对视频平台的压力,从而实现对普通观看过程的模拟,并降低被拦截的概率
$ctrl_gen+="$ytdlpAppPath --newline --ignore-errors -o `"$DownloadPath%%(title)s.%%(ext)s`" --ignore-config --hls-prefer-native --no-playlist $_ $cookieImp " #批处理中需要%%而不是常规%(title)
}
$ctrl_gen += "
pause
"
$utf8NoBOM=New-Object System.Text.UTF8Encoding $false #导出utf-8NoBOM文本编码用
[IO.File]::WriteAllLines($CmdPrint, $ctrl_gen, $utf8NoBOM) #强制导出utf-8NoBOM编码
Write-Output "`r`n完成`r`n"
pause
工作以及使用流程
- 下载一个yt-dlp.exe工具
- 最好创建一个文件夹用于放置
- 打开一个记事本/空白文本文档进程
- 将所有要下载的视频链接(取决于yt-dlp支持的视频网站)粘贴进去
- 最好去掉如
&list
,&si
之类的后缀,以防止油管未来在链接中用这种方式偷偷添加标记(可能想多了) - 可以用批量拷贝链接的浏览器插件,如Snap Links Plus
- 最好去掉如
- 创建一个文件夹用于下载所有视频
- 运行yt-dlp-ops.ps1,可以在PowerShell ISE中打开并运行,也可以右键→用PowerShell运行
- 将所有要下载的视频链接粘贴进去
- 通过弹出的选择窗选择下载视频的路径
- 通过弹出的选择窗定位yt-dlp.exe
- 通过弹出的选择窗选择导出批处理的路径
- 每天第一次使用时,选择y以添加一行用于导出当前浏览器cookie的命令
- 用于以你的账号登录油管或其它视频网站,从而确保下载进程正常
- 完成!双击运行导出的
yt-dlp-download.bat
以开始下载
其它特性
- 每个下载线程之间会随机生成一个1~7秒的间隔,从而让下载进程更像正常观看,且每次都不会重复
- 通过GUI窗口选择各种路径,极大地降低了操作难度
- 导出UTF-8 No BOM编码的批处理
那么就这样~
打赏信息
这玩意不一定适合打赏
- 更新2:添加了高DPI的Windows Form GUI选择窗渲染,添加了运行后暂停
- 更新3:添加了极为先进的分辨率自适应多行文本输入框Windows Form GUI,用于改进输入并编辑多链接的流程
- 更新4:添加了区分PowerShell ISE和Console窗口的区分,以正确统计分辨率
- 更新5:通过文本框Font属性搭配加载默认Windows Form并获取其中属性的方式实现了高DPI文本框字号过小的修复