【问题标题】:Shell Script to download youtube files from playlist用于从播放列表下载 youtube 文件的 Shell 脚本
【发布时间】:2012-02-13 20:13:57
【问题描述】:

我正在尝试编写一个 bash 脚本,该脚本将从播放列表中下载所有 youtube 视频,并根据 youtube 视频本身的标题将它们保存到特定的文件名。到目前为止,我有两段独立的代码可以执行我想要的操作,但我不知道如何将它们组合在一起以作为一个单元运行。

这段代码查找给定页面上所有 youtube 视频的标题:

curl -s "$1" | grep '<span class="title video-title "' | cut -d\> -f2 | cut -d\< -f1

这段代码将文件下载到 youtube 视频 ID 给出的文件名(例如 youtube.com/watch?v=CsBVaJelurE&feature=relmfu 给出的文件名将是 CsBVaJelurE.flv )

curl -s "$1" | grep "watch?" | cut -d\" -f4| while read video; 
do youtube-dl "http://www.youtube.com$video";
done

我想要一个脚本,它将 youtube .flv 文件输出为由视频标题(在本例中为 BASH 第 2.flv 课)给出的文件名,而不是简单的视频 ID 名称。提前感谢所有帮助。

【问题讨论】:

标签: bash shell download cut youtube-dl


【解决方案1】:

好的,所以在进一步研究和更新我的 youtube-dl 版本后,事实证明这个功能现在直接内置在程序中,不需要 shell 脚本来解决 youtube 上的播放列表下载问题。完整的文档可以在这里找到:(http://rg3.github.com/youtube-dl/documentation.html) 但我原来的问题的简单解决方案如下:

1) youtube-dl 将自动处理播放列表链接,无需单独向其提供其中包含的视频的 URL(这消除了使用 grep 搜索“观看?”来查找唯一的视频 ID

2) 现在包含一个选项来格式化文件名,其中包括:

  • id:序列将替换为视频标识符。
  • url:序列将被视频URL替换。
  • 上传者:序列将替换为上传视频的人的昵称。
  • upload_date:该序列将替换为 YYYYMMDD 格式的上传日期。
  • title:序列将替换为文字视频标题。
  • ext:该序列将被适当的扩展名替换(如 flv 或 mp4)。
  • epoch:创建时将替换为 Unix epoch 文件。
  • 自动编号:序列将替换为一个五位数字 每次下载都会增加,从零开始。

此输出选项的语法如下(其中 NAME 是上面显示的任何选项):

youtube-dl -o '%(NAME)s' http://www.youtube.com/your_video_or_playlist_url

例如,回答我原来的问题,语法如下:

youtube-dl -o '%(title)s.%(ext)s' http://www.youtube.com/playlist?list=PL2284887FAE36E6D8&feature=plcp

再次感谢那些回答我问题的人,非常感谢您的帮助。

【讨论】:

  • 这肯定是最好的答案。感谢分享。看起来不再支持“标题”。改用“标题”;我更新了你的答案。
【解决方案2】:

如果您想使用 youtube 页面的标题作为文件名,您可以使用 youtube-dl-t 选项。如果您想使用“视频列表”页面中的标题,并且您确定每个 &lt;span class="title video-title" 标题都有一个 watch? URL,那么您可以使用以下内容:

#!/bin/bash

TMPFILE=/tmp/downloader-$$

onexit() {
  rm -f $TMPFILE
}

trap onexit EXIT

curl -s "$1" -o $TMPFILE

i=0
grep '<span class="title video-title "' $TMPFILE | cut -d\> -f2 | cut -d\< -f1 | while read title; do
  titles[$i]=$title
  ((i++))
done

i=0
grep "watch?" $TMPFILE | cut -d\" -f4 | while read url; do
  urls[$i]="http://www.youtube.com$url"
  ((i++))
done

i=0; while (( i < ${#urls[@]} )); do
  youtube-dl -o "${titles[$i]}.%(ext)" "${urls[$i]}"
  ((i++))
done

我没有测试它,因为我没有“视频列表”页面示例。

【讨论】:

  • 感谢 praetorian 的回答, -t 选项暂时有效,但您提供的脚本中有一些错误,我需要检查一下。目前文件本身根本不下载,但我还没有时间测试你的脚本并了解原因。如果我发现任何问题,我会保持更新。
【解决方案3】:

以下方法有效并在 youtube 上播放你的泰坦尼克号

youtube-downloader.sh youtube-video-url.sh

#!/bin/bash
decode() {
    to_decode='s:%([0-9A-Fa-f][0-9A-Fa-f]):\\x\1:g'
    printf "%b" `echo $1 | sed 's:&:\n:g' | grep "^$2" | cut -f2 -d'=' | sed -r $to_decode`
}
data=`wget http://www.youtube.com/get_video_info?video_id=$1\&hl=pt_BR -q -O-`
url_encoded_fmt_stream_map=`decode $data 'url_encoded_fmt_stream_map' | cut -f1 -d','`
signature=`decode $url_encoded_fmt_stream_map 'sig'`
url=`decode $url_encoded_fmt_stream_map 'url'`
test $2 && name=$2 || name=`decode $data 'title' | sed 's:+: :g;s:/:-:g'`
test "$name" = "-" && name=/dev/stdout || name="$name.vid"
wget "${url}&signature=${signature}" -O "$name"






#!/usr/bin/env /bin/bash
function youtube-video-url {
    local field=
    local data=
    local split="s:&:\n:g"
    local decode_str='s:%([0-9A-Fa-f][0-9A-Fa-f]):\\x\1:g'
    local yt_url="http://www.youtube.com/get_video_info?video_id=$1"
    local grabber=`command -v curl`
    local args="-sL"
    if [ ! "$grabber" ]; then
        grabber=`command -v wget`
        args="-qO-"
    fi
    if [ ! "$grabber" ]; then
        echo 'No downloader available.' >&2
        test x"${BASH_SOURCE[0]}" = x"$0" && exit 1 || return 1
    fi
    function decode {
        data="`echo $1`"
        field="$2"
        if [ ! "$field" ]; then
            field="$1"
            data="`cat /dev/stdin`"
        fi
        data=`echo $data | sed $split | grep "^$field" | cut -f2 -d'=' | sed -r $decode_str`
        printf "%b" $data
    }
    local map=`$grabber $args $yt_url | decode 'url_encoded_fmt_stream_map' | cut -f1 -d','`
    echo `decode $map 'url'`\&signature=`decode $map 'sig'`
}
[ $SHLVL != 1 ] && export -f youtube-video-url

bash youtube-player.sh saalGKY7ifU

#!/bin/bash
decode() {
    to_decode='s:%([0-9A-Fa-f][0-9A-Fa-f]):\\x\1:g'
    printf "%b" `echo $1 | sed 's:&:\n:g' | grep "^$2" | cut -f2 -d'=' | sed -r $to_decode`
}


data=`wget http://www.youtube.com/get_video_info?video_id=$1\&hl=pt_BR -q -O-`


url_encoded_fmt_stream_map=` decode $data 'url_encoded_fmt_stream_map' | cut -f1 -d','`

signature=` decode $url_encoded_fmt_stream_map 'sig'`

url=`decode $url_encoded_fmt_stream_map 'url'`
test $2 && name=$2 || name=`decode $data 'title' | sed 's:+: :g;s:/:-:g'`


test "$name" = "-" && name=/dev/stdout || name="$name.mp4"

# // wget "${url}&signature=${signature}" -O "$name"

mplayer -zoom -fs "${url}&signature=${signature}"

它使用你可能已经安装的 decode 和 bash。

【讨论】:

    【解决方案4】:

    我使用这个 bash 脚本从给定的 youtube 的播放列表中下载一组给定的歌曲

    #!/bin/bash
    downloadDirectory = <directory where you want your videos to be saved>
    playlistURL = <URL of the playlist>
    for i in {<keyword 1>,<keyword 2>,...,<keyword n>}; do
        youtube-dl -o ${downloadDirectory}"/youtube-dl/%(title)s.%(ext)s" ${playlistURL} --match-title $i
    done
    

    注意:“关键字 i”是该播放列表中给定视频的标题(全部或部分;如果是部分,则该播放列表应该是唯一的)。

    编辑:您可以通过 pip install youtube-dl

    安装 youtube-dl

    【讨论】:

      【解决方案5】:
      #!/bin/bash
      # Coded by Biki Teron 
      # String replace command in linux
      
      echo "Enter youtube url:"
      read url1
      
      wget -c -O index.html $url1
      ################################### Linux string replace    ##################################################
      sed -e 's/%3A%2F%2F/:\/\//g'  index.html > youtube.txt
      sed -i 's/%2F/\//g' youtube.txt
      sed -i 's/%3F/?/g' youtube.txt
      sed -i 's/%3D/=/g' youtube.txt
      sed -i 's/%26/\&/g'  youtube.txt
      sed -i 's/%252/%2/g'  youtube.txt
      sed -i 's/sig/&signature/g'  youtube.txt
      ## command to get filename
      nawk '/<title>/,/<\/title>/' youtube.txt > filename.txt ## Print the line between   containing <title> and <\/title> .
      sed -i 's/.*content="//g' filename.txt 
      sed -i 's/">.*//g' filename.txt
      sed -i 's/.*<title>//g' filename.txt
      sed -i 's/<.*//g' filename.txt
      ######################################## Coding to get all itag list ########################################
      
      nawk '/"fmt_list":/,//' youtube.txt > fmt.html ## Print the line containing "fmt_list": .
      sed -i 's/.*"fmt_list"://g' fmt.html
      sed -i 's/, "platform":.*//g' fmt.html
      sed -i 's/, "title":.*//g' fmt.html
      
      # String replace command in linux to get correct itag format
      sed -i 's/\\\/1920x1080\\\/99\\\/0\\\/0//g'  fmt.html  ## Replace \/1920x1080\/99\/0\/0 by blank .
      sed -i 's/\\\/1920x1080\\\/9\\\/0\\\/115//g' fmt.html  ## Replace \/1920x1080\/9\/0\/115 by blank.
      sed -i 's/\\\/1280x720\\\/99\\\/0\\\/0//g'   fmt.html  ## Replace \/1280x720\/99\/0\/0 by blank.
      sed -i 's/\\\/1280x720\\\/9\\\/0\\\/115//g'  fmt.html  ## Replace \/1280x720\/9\/0\/115 by blank.
      sed -i 's/\\\/854x480\\\/99\\\/0\\\/0//g'    fmt.html  ## Replace \/854x480\/99\/0\/0 by blank.
      sed -i 's/\\\/854x480\\\/9\\\/0\\\/115//g'   fmt.html  ## Replace \/854x480\/9\/0\/115 by blank.
      sed -i 's/\\\/640x360\\\/99\\\/0\\\/0//g'    fmt.html  ## Replace \/640x360\/99\/0\/0 by blank.
      sed -i 's/\\\/640x360\\\/9\\\/0\\\/115//g'   fmt.html  ## Replace \/640x360\/9\/0\/115 by blank.
      sed -i 's/\\\/640x360\\\/9\\\/0\\\/115//g'   fmt.html  ## Replace \/640x360\/9\/0\/115 by blank.
      sed -i 's/\\\/320x240\\\/7\\\/0\\\/0//g'     fmt.html  ## Replace \/320x240\/7\/0\/0 by blank.
      sed -i 's/\\\/320x240\\\/99\\\/0\\\/0//g'    fmt.html  ## Replace \/320x240\/99\/0\/0 by blank.
      sed -i 's/\\\/176x144\\\/99\\\/0\\\/0//g'    fmt.html  ## Replace \/176x144\/99\/0\/0 by blank.
      
      # Command to cut a part of a file between any two strings
      nawk '/"url_encoded_fmt_stream_map":/,//' youtube.txt > url.txt
      sed -i 's/.*url_encoded_fmt_stream_map"://g' url.txt
      
      #Display video resolution information
      echo ""
      echo "Video resolution:"
      echo "[46=1080(.webm)]--[37=1080(.mp4)]--[35=480(.flv)]--[36=180(.3gpp)]"
      echo "[45=720 (.webm)]--[22=720 (.mp4)]--[34=360(.flv)]--[17=144(.3gpp)]"
      echo "[44=480 (.webm)]--[18=360 (.mp4)]--[5=240 (.flv)]"
      echo "[43=360 (.webm)]"
      echo ""
      echo "itag list= "`cat fmt.html`
      echo "Enter itag number: "
      read fmt
      
      ####################################### Coding to get required resolution #################################################
      ## cut itag=?
      
      sed -e "s/.*,itag=$fmt//g" url.txt > "$fmt"_1.txt
      sed -e 's/\u0026quality.*//g' "$fmt"_1.txt > "$fmt".txt
      sed -i 's/.*u0026url=//g' "$fmt".txt ## Ignore all lines before \u0026url= but print all lines after \u0026url=.
      sed -e 's/\u0026type.*//g' "$fmt".txt > "$fmt"url.txt ## Ignore all lines after \u0026type but print all lines before \u0026type.
      sed -i 's/\\/\&/g' "$fmt"url.txt ## replace \ by &
      sed -e 's/.*\u0026sig//g' "$fmt".txt > "$fmt"sig.txt ## Ignore all lines before \u0026sig but print all lines after \u0026sig.
      sed -i 's/\\/\&ptk=machinima/g' "$fmt"sig.txt ## replace \ by &
      echo `cat "$fmt"url.txt``cat "$fmt"sig.txt` > "$fmt"url.txt ## Add string at the end of a line
      echo `cat "$fmt"url.txt` > link.txt ## url and signature content to 44url.txt
      rm "$fmt"sig.txt
      rm "$fmt"_1.txt
      rm "$fmt".txt
      rm "$fmt"url.txt
      rm youtube.txt
      ########################################### Coding for filename with correct extension #####################################
      if [ $fmt -eq 46 ]
       then 
          echo `cat filename.txt`.webm > filename.txt
      
      elif [ $fmt -eq 45 ]
        then 
           echo `cat filename.txt`.webm > filename.txt
      
      elif [ $fmt -eq 44 ]
        then 
           echo `cat filename.txt`.webm > filename.txt
      
      elif [ $fmt -eq 43 ]
         then 
         echo `cat filename.txt`.webm > filename.txt
      
      elif [ $fmt -eq 37 ]
         then 
         echo `cat filename.txt`.mp4 > filename.txt
      
      elif [ $fmt -eq 22 ]
         then 
         echo `cat filename.txt`.mp4 > filename.txt
      
      elif [ $fmt -eq 18 ]
         then 
        echo `cat filename.txt`.mp4 > filename.txt
      
      elif [ $fmt -eq 35 ]
         then 
         echo `cat filename.txt`.flv > filename.txt
      
      elif [ $fmt -eq 34 ]
         then 
         echo `cat filename.txt`.flv > filename.txt
      
      elif [ $fmt -eq 5 ]
         then 
         echo `cat filename.txt`.flv > filename.txt
      
      elif [ $fmt -eq 36 ]
         then 
         echo `cat filename.txt`.3gpp > filename.txt
      
       else
         echo `cat filename.txt`.3gpp > filename.txt
      
      fi
      rm fmt.html
      rm url.txt
      filename=`cat filename.txt`
      linkdownload=`cat link.txt`
      wget -c -O "$filename" $linkdownload
      echo "Download Finished!"
      read
      

      【讨论】:

      • 我正在学习 bash 脚本来下载 youtube 视频,这是基于最新的 youtube 算法。它将显示所有可用的视频分辨率。您可以下载 .webm、.mp4、.flv、.3gpp 文件格式。
      • 对不起,这与原来的问题无关,-1。
      猜你喜欢
      • 2017-12-12
      • 2020-11-08
      • 2018-07-03
      • 1970-01-01
      • 2012-09-10
      • 1970-01-01
      • 2020-10-12
      • 2021-02-05
      • 1970-01-01
      相关资源
      最近更新 更多