程式語言: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
留言
張貼留言