[Go] Download Youtube

程式語言:Go
Package:
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
"path/filepath"
"regexp"
"strings"
GitHub 網址

功能:下載 youtube 影片

工作原理

  • api
    • http://www.youtube.com/get_video_info?video_id=v
      • 得到影片相關資訊
      • 範例
        • 影片網址:https://www.youtube.com/watch?v=5yAU52qfYuU
          查詢網址:http://www.youtube.com/get_video_info?video_id=5yAU52qfYuU
      • 回傳資料
        • 格式 Query String
        • 重要參數
          • length_seconds 影片長度
          • author 作者
          • thumbnail_url 封面縮圖
          • title 標題
          • view_count 觀看次數
          • url_encoded_fmt_stream_map 不同品質影片的來源資訊
            • 格式 Query String
            • 資料
              • quality 品質
              • type 影片格式
              • url 網址

程式碼

  1. package gotube
  2.  
  3. import (
  4. "fmt"
  5. "io"
  6. "io/ioutil"
  7. "log"
  8. "net/http"
  9. "net/url"
  10. "os"
  11. "path/filepath"
  12. "regexp"
  13. "strings"
  14. )
  15.  
  16. const userAgent = `Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0`
  17.  
  18. type Youtube struct {
  19. videoID string
  20. VideoURL string
  21. VideoInfo
  22. }
  23.  
  24. type VideoInfo struct {
  25. URL string
  26. Quality string
  27. Ext string
  28. Name string
  29. }
  30.  
  31. func (y *Youtube) api(method string) ([]byte, error) {
  32. urlIndex := "http://www.youtube.com/" + method
  33. req, err := http.NewRequest(http.MethodGet, urlIndex, nil)
  34. if err != nil {
  35. return nil, err
  36. }
  37. req.Header.Add("User-Agent", userAgent)
  38.  
  39. q := req.URL.Query()
  40. q.Add("video_id", y.videoID)
  41. req.URL.RawQuery = q.Encode()
  42. log.Printf("Request api url=%s", req.URL)
  43.  
  44. client := &http.Client{}
  45. resp, err := client.Do(req)
  46. if err != nil {
  47. return nil, err
  48. }
  49. defer resp.Body.Close()
  50.  
  51. body, err := ioutil.ReadAll(resp.Body)
  52. if err != nil {
  53. return nil, err
  54. }
  55.  
  56. return body, nil
  57. }
  58.  
  59. func (y *Youtube) getVideoInfo() error {
  60. body, err := y.api("get_video_info")
  61.  
  62. m, err := url.ParseQuery(string(body))
  63. if err != nil {
  64. return err
  65. }
  66.  
  67. y.VideoInfo.Name = m.Get("title")
  68.  
  69. qs := m.Get("url_encoded_fmt_stream_map")
  70. qs = strings.Replace(qs, ",", "&", -1)
  71. values, err := url.ParseQuery(qs)
  72. if err != nil {
  73. return err
  74. }
  75.  
  76. y.VideoInfo.Quality = values.Get("quality")
  77. y.VideoInfo.URL = values.Get("url")
  78. ext := strings.Split(values.Get("type"), ";")
  79. ext = strings.Split(ext[0], "/")
  80. y.VideoInfo.Ext = ext[1]
  81.  
  82. log.Printf("Video: %+v\n", y.VideoInfo)
  83. return nil
  84. }
  85.  
  86. func (y *Youtube) GetVideo() error {
  87. parse := strings.Split(y.VideoURL, "?")
  88. paras, err := url.ParseQuery(parse[1])
  89. if err != nil {
  90. return err
  91. }
  92.  
  93. y.videoID = paras.Get("v")
  94. err = y.getVideoInfo()
  95. if err != nil {
  96. return err
  97. }
  98.  
  99. fileName := fmt.Sprintf("%s.%s", FileNameCorrect(y.Name), y.Ext)
  100. path := filepath.Join(".", fileName)
  101. if err := DownloadFile(path, y.URL); err != nil {
  102. return err
  103. }
  104.  
  105. return nil
  106. }
  107.  
  108. func FileNameCorrect(s string) string {
  109. var re = regexp.MustCompile(`[\/:*?"<>|]`)
  110. s = re.ReplaceAllString(s, " ")
  111. return s
  112. }
  113.  
  114. func DownloadFile(filepath, url string) error {
  115. // Create the file
  116. out, err := os.Create(filepath)
  117. if err != nil {
  118. return err
  119. }
  120. defer out.Close()
  121.  
  122. // Get the data
  123. resp, err := http.Get(url)
  124. if err != nil {
  125. return err
  126. }
  127. defer resp.Body.Close()
  128.  
  129. // Write the body to file
  130. _, err = io.Copy(out, resp.Body)
  131. if err != nil {
  132. return err
  133. }
  134.  
  135. return nil
  136. }

參考

拆解 Youtube 影片下載位置
[爬蟲實戰] 如何使用Python 爬蟲 (Python Crawler) 下載Youtube 影片 - YouTube

留言