程式語言: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
- 回傳資料
- length_seconds 影片長度
- author 作者
- thumbnail_url 封面縮圖
- title 標題
- view_count 觀看次數
- url_encoded_fmt_stream_map 不同品質影片的來源資訊
- quality 品質
- type 影片格式
- url 網址
程式碼
- package gotube
-
- import (
- "fmt"
- "io"
- "io/ioutil"
- "log"
- "net/http"
- "net/url"
- "os"
- "path/filepath"
- "regexp"
- "strings"
- )
-
- const userAgent = `Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0`
-
- type Youtube struct {
- videoID string
- VideoURL string
- VideoInfo
- }
-
- type VideoInfo struct {
- URL string
- Quality string
- Ext string
- Name string
- }
-
- func (y *Youtube) api(method string) ([]byte, error) {
- urlIndex := "http://www.youtube.com/" + method
- req, err := http.NewRequest(http.MethodGet, urlIndex, nil)
- if err != nil {
- return nil, err
- }
- req.Header.Add("User-Agent", userAgent)
-
- q := req.URL.Query()
- q.Add("video_id", y.videoID)
- req.URL.RawQuery = q.Encode()
- log.Printf("Request api url=%s", req.URL)
-
- client := &http.Client{}
- resp, err := client.Do(req)
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
-
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return nil, err
- }
-
- return body, nil
- }
-
- func (y *Youtube) getVideoInfo() error {
- body, err := y.api("get_video_info")
-
- m, err := url.ParseQuery(string(body))
- if err != nil {
- return err
- }
-
- y.VideoInfo.Name = m.Get("title")
-
- qs := m.Get("url_encoded_fmt_stream_map")
- qs = strings.Replace(qs, ",", "&", -1)
- values, err := url.ParseQuery(qs)
- if err != nil {
- return err
- }
-
- y.VideoInfo.Quality = values.Get("quality")
- y.VideoInfo.URL = values.Get("url")
- ext := strings.Split(values.Get("type"), ";")
- ext = strings.Split(ext[0], "/")
- y.VideoInfo.Ext = ext[1]
-
- log.Printf("Video: %+v\n", y.VideoInfo)
- return nil
- }
-
- func (y *Youtube) GetVideo() error {
- parse := strings.Split(y.VideoURL, "?")
- paras, err := url.ParseQuery(parse[1])
- if err != nil {
- return err
- }
-
- y.videoID = paras.Get("v")
- err = y.getVideoInfo()
- if err != nil {
- return err
- }
-
- fileName := fmt.Sprintf("%s.%s", FileNameCorrect(y.Name), y.Ext)
- path := filepath.Join(".", fileName)
- if err := DownloadFile(path, y.URL); err != nil {
- return err
- }
-
- return nil
- }
-
- func FileNameCorrect(s string) string {
- var re = regexp.MustCompile(`[\/:*?"<>|]`)
- s = re.ReplaceAllString(s, " ")
- return s
- }
-
- func DownloadFile(filepath, url string) error {
- // Create the file
- out, err := os.Create(filepath)
- if err != nil {
- return err
- }
- defer out.Close()
-
- // Get the data
- resp, err := http.Get(url)
- if err != nil {
- return err
- }
- defer resp.Body.Close()
-
- // Write the body to file
- _, err = io.Copy(out, resp.Body)
- if err != nil {
- return err
- }
-
- return nil
- }
參考
拆解 Youtube 影片下載位置
[爬蟲實戰] 如何使用Python 爬蟲 (Python Crawler) 下載Youtube 影片 - YouTube
留言
張貼留言