- package main
- import (
- "bytes"
- "fmt"
- "golang.org/x/text/encoding/simplifiedchinese"
- "golang.org/x/text/transform"
- "io/ioutil"
- "log"
- "net/http"
- "os"
- "os/exec"
- "regexp"
- "strconv"
- "strings"
- )
- //redirect url
- func redirect(url string) (string, error) {
- resp, err := http.Head(url)
- if err != nil {
- log.Fatal(err)
- }
- defer resp.Body.Close()
- url = resp.Request.URL.String()
- return url, err
- }
- //output html with encoding(gb2312)
- func decode(url string) string {
- resp, err := http.Get(url)
- if err != nil {
- log.Fatal(err)
- }
- defer resp.Body.Close()
- input, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- log.Fatal(err)
- }
- out := make([]byte, len(input))
- out = out[:]
- I := bytes.NewReader(input)
- O := transform.NewReader(I, simplifiedchinese.GBK.NewDecoder())
- d, err := ioutil.ReadAll(O)
- if err != nil {
- log.Fatal(err)
- }
- return string(d)
- }
- func download(i int, name string, url []string, execChans chan bool, doneChans chan bool) {
- execChans <- true // 放在函数的开始处,用来阻塞执行,如果通道里的数量超过设定数量,在没有读取完成前,不会运行
- isOk := false
- fmt.Printf("NO: %d start...\\n", i+1)
- argv1 := "--user-agent=\\"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.6) Gecko/20060728 Firefox/1.5\\""
- argv2 := "/home/justin/Videos/" + name + "_" + strconv.Itoa(i+1) + ".flv"
- argv3 := url[i]
- defer func() {
- doneChans <- isOk
- }()
- cmd := exec.Command("wget", argv1, "-O", argv2, argv3)
- _, execErr := cmd.Output()
- if execErr != nil {
- panic(execErr)
- } else {
- isOk = true
- }
- return
- }
- func main() {
- var url string
- if len(os.Args) > 1 {
- url = os.Args[1]
- } else {
- fmt.Println("Please input the URL :")
- fmt.Scanf("%s", &url)
- }
- output := decode("http://www.flvcd.com/parse.php?kw=" + url + "&flag=one&format=high&format=super")
- r, _ := regexp.Compile("<strong>当前解析视频:</strong>(.*?)<strong>")
- title := r.FindAllStringSubmatch(output, 1)
- title[0][1] = strings.TrimSpace(title[0][1]) //title[0][1] is the video title
- fmt.Printf("downloading %s now\\n", title[0][1])
- r, _ = regexp.Compile("<BR><a href=\\"(.*?)\\" target=\\"_blank\\" onclick='_alert()")
- videoURL := r.FindAllStringSubmatch(output, -1)
- count := len(videoURL)
- realURL := make([]string, count)
- m3u := "#EXTM3U\\n"
- for i := 0; i < count; i++ {
- realURL[i], _ = redirect(videoURL[i][1])
- m3u += "#EXTINF:" + title[0][1] + "\\n" + title[0][1] + "_" + strconv.Itoa(i+1) + ".flv\\n"
- }
- out := []byte(m3u)
- ioutil.WriteFile("/home/justin/Videos/"+title[0][1]+".m3u", out, 0644) //create a m3u file
- pnum := 5 // channel amount
- if pnum > count {
- pnum = count
- }
- execChans := make(chan bool, pnum)
- doneChans := make(chan bool, 1)
- for i := 0; i < count; i++ {
- go download(i, title[0][1], realURL, execChans, doneChans)
- }
- for i := 0; i < count; i++ {
- msg := <-doneChans // 完成一个,同时获取下一个任务
- <-execChans // 紧接着读取下一个任务,类是于beanstalkd的任务分发机制
- if msg { // 获取失败时,打印该网址失败。
- fmt.Printf("No. %d/%d is succeed\\n", i+1, count)
- } else {
- fmt.Printf("No. %d/%d is failure\\n", i+1, count)
- }
- }
- close(doneChans) // 关闭完成信号
- close(execChans) // 关闭执行信号
- fmt.Println("done!")
- }
- //该片段来自于http://www.codesnippet.cn/detail/2411201411036.html
来源: http://www.codesnippet.cn/detail/2411201411036.html