Download nhạc từ MP3 Zing với PHP và jQuery

Trong bài viết lấy link nhạc trực tiếp từ MP3 Zing trước đây, tôi có nhận được một số phản hồi về việc tạo một trang web cho phép người dùng nhập link và download nhạc từ MP3 Zing với PHP và jQuery. Và hôm nay tôi sẽ chia sẻ cách tôi thực hiện trang web như thế.

1, Phân tích và lấy thông tin

Muốn tải về được thì trước tiên chúng ta cần phải có thông tin. Tôi đã làm gì để có thông tin? Mở View-Source sẽ có điều chúng ta cần. Khi xem page source của một bài hát trên MP3 Zing

Ví dụ: http://mp3.zing.vn/bai-hat/Tinh-Da-Phai-Don-Ho/ZW60E7IE.html

Tôi để ý đến một dòng code như sau:

<div id="player5" data-xml="http://mp3.zing.vn/xml/song-xml/ZHcHtZmazFdiZVStkbctvmkG" class="none"></div>

Như vậy chúng ta có thể phán đoán rằng đường dẫn trong thuộc tính data-xml sẽ chứa thông tin bài hát dưới dạng XML. Nếu điều phỏng đoán trên là đúng thì ZHcHtZmazFdiZVStkbctvmkG sẽ là ID thật sự của bài hát còn ZW60E7IE chỉ là bí danh (alias) của bài hát mà thôi.

Nếu chúng ta truy cập đến đường dẫn chứa ID thật sự của bài hát (http://mp3.zing.vn/xml/song-xml/ZHcHtZmazFdiZVStkbctvmkG) thì chúng ta sẽ thu được những thông tin sau:

<data page="http://mp3.zing.vn/bai-hat/Tinh-Da-Phai-Don-Ho/ZW60E7IE.html">
   <item type="mp3">
      <title>
         <![CDATA[ Tình Đã Phai ]]>
      </title>
      <performer>
         <![CDATA[ Don Hồ ]]>
      </performer>
      <link>
      <![CDATA[ http://mp3.zing.vn/tim-kiem/bai-hat.html?q=Don+Ho ]]>
      </link>
      <source>
         <![CDATA[
            http://mp3.zing.vn/xml/load-song/MjAxMiUyRjA2JTJGMjYlMkYxJTJGYiUyRjFiNjM5ZTBhOWFhYWExMjgxZmY5MjczY2E4MDY4YTk2Lm1wMyU3QzI=
            ]]>
      </source>
      <hq>
         <![CDATA[ require vip ]]>
      </hq>
      <duration>243</duration>
      <lyric>
         <![CDATA[ ]]>
      </lyric>
      <mvlink>
         <![CDATA[ ]]>
      </mvlink>
      <adparam>
         <![CDATA[ cid=a_1074239134 ]]>
      </adparam>
      <backimage>
         <![CDATA[
            http://image.mp3.zdn.vn/skins/zmp3-v4/images/default2/1190x350.jpg
            ]]>
      </backimage>
      <errorcode>0</errorcode>
      <errormessage/>
   </item>
</data>

Và đường link trong thuộc tính <source></source> chính là đường dẫn trực tiếp của bài hát. Vậy điều chúng ta cần đã có. Bắt tay viết chương trình thôi!

Nhưng, mà khoan…

Tôi nhận ra mình vui mừng hơi sớm bởi vì thông tin bài hát được lưu trữ dưới dạng XML nên việc thao tác, bóc tách dữ liệu sẽ hơi khó. Vậy nên tôi tiếp tục tìm thử xem liệu MP3 Zing có lưu thông tin bài hát dưới dạng khác không như JSON chẳng hạn.

Xem page source tiếp thì tôi thấy một đoạn code dùng để khởi tạo player chơi nhạc như sau:

init: function () {
  $('#html5player').removeClass('none');
  var player = $('#player5');
  var url = player.data('xml').split('/');
  $.get('http://mp3.zing.vn' + '/html5xml/' + url[url.length - 2] + '/' + url[url.length - 1], function (rs) {
    var playlist = [];
    for (var i in rs.data) {
      var item = rs.data[i];
      item.title = item.name;
      for (var x in item.source_list) {
        item.source_list[x] = item.source_base + '/' + item.source_list[x];
      }
      item.mp3 = item.source_list[0];
      delete(item.name);
      delete(item.source_base);
      playlist.push(item);

      for (var i in item.qualities) {
        $('.fn-quality .fn-item[data-quality=' + item.qualities[i] + ']').removeClass('disabled');
      }
    }
    zmp3HTML5.initPlayer(playlist);
  });
}

Các bạn thấy điều gì đặc biệt ở đoạn code trên không? Tôi nhận ra trang web đang lấy data từ đường dẫn http://mp3.zing.vn/html5xml/. Vậy thì sao nhỉ?

Đối chiếu với đường dẫn ở trên, http://mp3.zing.vn/xml/song-xml/ZHcHtZmazFdiZVStkbctvmkG, chứa thông tin dưới dạng XML. Tôi đã đổi đướng dẫn thành http://mp3.zing.vn/html5xml/song-xml/ZHcHtZmazFdiZVStkbctvmkG để kiểm tra thì…tôi tìm thấy toàn bộ thông tin bài hát dưới dạng JSON. Thật tuyệt vời! 😀

{
   "msg": "",
   "data": [
      {
         "id": "ZW60E7IE",
         "name": "Tình Đã Phai",
         "artist": "Don Hồ",
         "link": "/bai-hat/Tinh-Da-Phai-Don-Ho/ZW60E7IE.html",
         "artist_list": [
            {
               "name": "Don Hồ",
               "link": "/nghe-si/Don-Ho"
            }
         ],
         "cover": "/null",
         "qualities": [
            "128"
         ],
         "source_list": [
            "MjAxMi8wNi8yNi8xL2IvMWI2MzllMGE5YWFhYTEyODFmZjkyNzNjYTgwNjhhOTYubXAzfDI="
         ],
         "source_base": "http://mp3.zing.vn/xml/load-song",
         "lyric": "http://static.mp3.zdn.vn/lyrics/"
      }
   ]
}

Tương tự các bạn có thể debug theo cách của tôi để tìm thông tin cho Video, Album. Dưới đây là tổng hợp những gì chúng ta có được nếu debug tiếp

// Song
JSON: http://mp3.zing.vn/html5xml/song-xml/<ID_that_su_cua_bai_hat>
XML:  http://mp3.zing.vn/xml/song-xml/<ID_that_su_cua_bai_hat>

// Album
JSON: http://mp3.zing.vn/html5xml/album-xml/<ID_that_su_cua_bai_hat>
XML:  http://mp3.zing.vn/xml/album-xml/<ID_that_su_cua_bai_hat>

// Video
JSON: http://mp3.zing.vn/xml/video-xml/<ID_that_su_cua_bai_hat>?format=json
XML:  http://mp3.zing.vn/xml/video-xml/<ID_that_su_cua_bai_hat>

Bây giờ mọi việc đã dễ dàng hơn, bắt tay vào code thôi!

2, Sử dụng PHP để xử lý thông tin

Phía backend tôi sẽ dùng PHP để request tới link bài hát, video, album để bóc tách dữ liệu và gửi qua frontend để hiển thị kết quả.

Đầu tiên, tôi sử dụng cURL để lấy page source

  /**
   * Using cURL to grab page content
   * @param  String $url The link need to grab
   * @return Object      The page content
   *
   * @note   Zing MP3 is using gzip
   */
  function getPageSource($url) {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
    curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
    $content = curl_exec($ch);
    curl_close($ch);

    return $content;
  }

Sau khi có được nội dung page source, tôi sẽ xử lý tiếp và gửi kết quả đến frontend dưới dạng JSON

  /**
   * @author Tấn Việt
   * @copyright 2015
   * @website https://tanvietblog.com
   */

  if (!empty($_POST['link'])) {
    $link = trim($_POST['link']);

    // Initialize the variables
    $results = array(
      'msg' => '',
      'type' => '',
      'data' => ''
    );

    // Get page source
    $html = getPageSource($link);

    // Parse the page source to get link song with its XML format
    $pattern = '/data-xml=\"(.*?)\"/';
    preg_match($pattern, $html, $matches);

    if (isset($matches[1]) && (substr($matches[1], 0, 23) === 'http://mp3.zing.vn/xml/')) {
      $url = $matches[1];
      $type = getLinkType($url);

      // Get link information with JSON format
      if ($type === 'song-xml' || $type === 'album-xml') {
        $url = str_replace('/xml/', '/html5xml/', $url);
        $results['type'] = $type;
        $results['data'] = getPageSource($url);
      } else if ($type === 'video-xml') {
        $results['type'] = $type;
        $results['data'] = getPageSource($url . '?format=json');
      }
    } else {
      $results['msg'] = 'Link bạn nhập vào không đúng hoặc bài hát (album, video) đã bị xóa khỏi hệ thống. Bạn vui lòng kiểm tra lại.';
    }

    echo json_encode($results);
  }

3, Download nhạc từ MP3 Zing

Trên frontend được xây dựng với HTML và jQuery, việc bóc tách dữ liệu khá đơn giản sau khi gọi Ajax đến backend để lấy thông tin. Ví dụ với thông tin bài hát, album tôi xử lý như sau

var linkData = $.parseJSON(result.data);
var siteBase = 'http://mp3.zing.vn';
var imageBase = 'http://image.mp3.zdn.vn';

$('#results').show();

// Hiển thị nội dung
if (result.type === 'song-xml' || result.type === 'album-xml') {
  for (var i = 0; i < linkData.data.length; i++) {
    var thumbnail, mv_link, lyric;
    var artist_list = [];
    var download = [];
    var item = linkData.data[i];

    // Nghệ sỹ
    for (var j = 0; j < item.artist_list.length; j++) {
      artist_list.push('<a href="' + siteBase + item.artist_list[j].link + '" target="_blank">' + item.artist_list[j].name + '</a>');
    }

    // Link download
    for (var j = 0; j < item.source_list.length; j++) {
      download.push('<a href="' + item.source_base + '/' + item.source_list[j] + '"  target="_blank">Download</a>');
    }

    // Ảnh đại diện
    thumbnail = item.cover !== '/null' ? (imageBase + item.cover) : null;

    // MV
    mv_link = item.mv_link ? (siteBase + item.mv_link) : null;

    // Lyric
    lyric = (item.lyric !== 'http://static.mp3.zdn.vn/lyrics/') ? item.lyric : null;

    // Nội dung hiển thị
    $('#results').append('<p><strong>THÔNG TIN:</strong></p>');

    if (thumbnail) {
      $('#results').append('<img src="' + thumbnail + '"/>');
    }

    $('#results').append('<p><strong>Tên bài hát: </strong>' + item.name + '</p>');

    $('#results').append('<p><strong>Nghệ sỹ: </strong>' + artist_list.join(' ft. ') + '</p>');

    $('#results').append('<p><strong>Chất lượng: </strong>' + item.qualities.join(', ') + '</p>');

    if (lyric) {
      $('#results').append('<p><strong>Lời bài hát: </strong><a href="' + lyric + '" target="_blank">' + lyric + '</a></p>');
    }

    if (mv_link) {
      $('#results').append('<p><strong>Music Video (MV): </strong><a href="' + mv_link + '" target="_blank">' + mv_link + '</a></p>');
    }

    $('#results').append('<p><strong>Tải về: </strong>' + download.join(', ') + '</p>');

    $('#results').append('<div class="row"></div>');
  }
}

4, Tổng kết

Như vậy chúng ta đã thực hiện xong một trang web mà tải về các bài hát, album, video trực tiếp trên MP3 Zing mà không cần dùng đến công cụ nào nữa. Các bạn hãy tải source code về để xem kỹ hơn nhé.

Tấn Việt

Tôi lập trang web này để thỏa mãn sở thích viết cái gì đó vui vui khi rãnh rỗi và đồng thời cũng chia sẻ những gì tôi biết hoặc đọc đâu đó trên mạng về Lập trình web. Tôi hi vọng những bài viết này sẽ giúp ích cho các bạn. Thân ái!

You may also like...

3 Responses

  1. đức says:

    Không dùng được nữa v admin

  2. Có vẻ link html5xml đối với nhiều bài hát nó không hoạt động đó bạn

  3. Huy says:

    Hiện tại ở chỗ data-xml đã được zing chuyển sang cấu trúc như thế này:
    /media/get-source?type=audio&key=kmJmyZHNgViacpXyHtFnZH\
    Vậy làm sao để làm tiếp đây

Leave a Reply

Your email address will not be published. Required fields are marked *