使用go語言來下載蜻蜓fm上的歌曲,效率感覺還行

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
package mainimport (       "encoding/json"       "errors"       "fmt"       "net/http"       "io"       "os"       "path"       "io/ioutil"       "sync")//翻唱FM的URL:http://www.qingting.fm/#/vchannels/136962/programs/5659080//翻唱FM的ajax地址:http://www.qingting.fm/s/vchannels/136962/programs/5745196/ajaxvar QingTingAjaxAddrFmt = "http://www.qingting.fm/s/vchannels/%d/programs/%d/ajax"//Go語言中json的解析,如果沒有固定的輸入格式,盡量使用通用格式 map [] interface{}//因為GO語言匯出結構體預設使用首字母大寫,而且需要和實際的格式進行對應,還不如使用map+interface+[]//type QingTingSongSubItem struct {//     Name       string           "歌曲名稱"//     ParentName string           "專輯名稱"//     QTSongs    []string        "歌曲URL"//     ParentID   int              "父目錄ID"//     Duration   int              "時間長度"//     Type       string           "類型"//     ID         int              "類型"//     Thumb      string           "縮圖"//}////type QingTingSongItem struct {//     PlayInfo QingTingSongSubItem//}////type QingTingPlayInfo QingTingSongItem////func (this *QingTingPlayInfo) Download(dirname string) (bool, error) {//     return false, nil//}////func (this *QingTingPlayInfo) String() string{//     return fmt.Sprintf("歌曲名稱:%#v 專輯名稱:%#v 歌曲URL地址:%#v 父目錄ID:%#v 時間長度:%#v 類型:%#v 縮圖:%#v",//            this.PlayInfo.Name,//            this.PlayInfo.ParentName,//            this.PlayInfo.QTSongs,//            this.PlayInfo.ParentID,//            this.PlayInfo.Duration,//            this.PlayInfo.Type,//            this.PlayInfo.ID,//            this.PlayInfo.Thumb)//}type QingTingPlayInfo map[string]interface{}func Download(this QingTingPlayInfo, dirname string, wg *sync.WaitGroup) (bool, error){       defer wg.Done()       //pthis := (map[string]interface{})(this)       name := this["name"].(string)       url :="http://od.qingting.fm" + this["urls"].([]interface{})[0].(string)       filename := path.Join(dirname, name+".m4a")       fmt.Printf("開始下載:%s 到:%s\n", url, filename)       res, err := http.Get(url)       if err != nil{              fmt.Printf("下載錯誤:%s\n", err)              return false,err       }       defer res.Body.Close()       data, err := ioutil.ReadAll(res.Body)       if err != nil{              fmt.Printf("下載失敗:%s\n", err)              return false,err       }       err2 := ioutil.WriteFile(filename, data, 0666)       if err2 != nil{              fmt.Printf("下載失敗:%s\n", err2)              return false, err2       }       fmt.Printf("!!!下載成功:%s 到:%s\n", url, filename)       return true, nil}//-----------------------------------------------------------------type QingTingFM struct {       Channel int "頻道"       ID      int "頻道ID"}func (this *QingTingFM) Crawl() ([]QingTingPlayInfo, error) {       jsonbyte, err := this.readJson()       if err != nil {              return nil, err       }       if jsonbyte == nil{              return nil,errors.New("返回了無效資料")       }       //go語言和json的映射關係 :對應結構體資料 []對應數組       pis := make([]QingTingPlayInfo,0)       jerr := json.Unmarshal(jsonbyte, &pis)       if jerr != nil{              return nil,jerr       }       downloadDir := "music_go"       os.MkdirAll(downloadDir, 0666)       //for _,pi := range pis{       //     fmt.Println(pi["name"])       //}       var wg sync.WaitGroup       //串連緩衝最大數目       maxIndex := len(pis) - 1       cacheMax := 5       for i,pi := range pis{              wg.Add(1)              cacheMax++              //wg必須是傳引用,這裡必須要限制非同步個數,否則與伺服器的串連過多,伺服器會拒絕,從而導致下載失敗              go Download(pi,downloadDir, &wg)              //使用緩衝              if cacheMax > 5 || maxIndex == i{                     wg.Wait()                     cacheMax = 0              }       }       return pis, nil}func (this *QingTingFM) readJson() ([]byte, error) {       //ajaxAddr := "http://www.golangtc.com/t/533c0ad2320b520cc400004f"       //http.Get自動gzip解壓縮資料流       res, err := http.Get(this.getAajxAddr())       if err != nil {              return nil, err       }       readerCloser := res.Body       //讀取之後需要關閉       defer readerCloser.Close()       if res.StatusCode != 200 {              return nil, errors.New("返回錯誤狀態代碼")       }       bytes := make([]byte, 0, 1024)       //buffer必須是數組,或者可以使用ioutil ReadAll來讀取       var buffera [128]byte       buffer := buffera[:]       for {              readed, rerr := readerCloser.Read(buffer)              if readed == 0 && rerr == nil{                     return nil, errors.New("readed=0 rerr=nil")              }              //切片...,自動將數組解壓成很多個參數輸入              //實現原理和...,變參支援的原理一樣              //這句應該在 ==io.EOF之前,如果寫到後面,則會丟失最後部分的資料              bytes = append(bytes,buffer[:readed]...)              //資料流讀取完畢              if rerr == io.EOF{                     break              }              if rerr != nil {                     return nil, rerr              }       }       //將bytes轉換成string       return bytes, nil}func (this *QingTingFM) getAajxAddr() string {       return fmt.Sprintf(QingTingAjaxAddrFmt, this.Channel, this.ID)}//-----------------------------------------------------------------func main() {       qtfm := QingTingFM{Channel: 136962, ID: 5745196}       qtfm.Crawl()}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.