isNullOrEmptyString($title)) { return 0; } $response = $this->search($title); if ($this->isNullOrEmptyString($response)) { return 0; } $json = json_decode($response, true); $songArray = $json['result']['songs']; $foundArray = array(); if(count($songArray) == 0) { return 0; } // Try to find the titles that match exactly $exactMatchArray = array(); $partialMatchArray = array(); foreach ($songArray as $song) { if (strtolower($title) === strtolower($song['name'])) { array_push($exactMatchArray, $song); } else if (strpos($song['name'], $title) || strpos($title, $song['name'])) { array_push($partialMatchArray, $song); } } if (count($exactMatchArray) != 0) { $songArray = $exactMatchArray; } else if (count($partialMatchArray != 0)) { $songArray = $partialMatchArray; } // Try to find the artists that match exactly $artistMatchArray = array(); foreach ($songArray as $song) { $elem = array( 'id' => $song['id'], 'artist' => $song['artists'][0]["name"], 'title' => $song['name'], 'alt' => $song['alias'][0] . "; Album: " . $song['album']['name'] ); array_push($foundArray, $elem); // Match artist // TODO artist in title like feat. foreach ($song['artists'] as $item) { if (strtolower($item['name']) === strtolower($artist)) { $elem['artist'] = $item['name']; array_push($artistMatchArray, $elem); break; } } } if (count($artistMatchArray) > 0) { $foundArray = $artistMatchArray; } // It's not easy for user to select the best match, so randomize the first match so that next time a new one will be returned $info->addTrackInfoToList($artist, $title, $this->LUCKY_PREFIX . $foundArray[rand(0, count($foundArray) - 1)]['id'], // Audio Statio will deduplicate, so add a special prefix "I'm feeling lucky. Random result of the best matches."); foreach ($foundArray as $song) { // add artist, title, id, lrc preview (or additional comment) $info->addTrackInfoToList($song['artist'], $song['title'], $song['id'], $song['id'] . "; " . $song['alt']); } return count($foundArray) + 1; } /** * Downloads a file with the specific ID */ public function getLyrics($id, $info) { if (substr($id, 0, strlen($this->LUCKY_PREFIX)) === $this->LUCKY_PREFIX) { $id = substr($id, strlen($this->LUCKY_PREFIX), strlen($id)); } //TODO combine translated lrc $lrc = $this->downloadLyric($id); if ($this->isNullOrEmptyString($lrc)) { printf("download lyrics from server failed\n"); return FALSE; } $info->addLyrics($lrc, $id); return true; } private static function search($word) { $params = array( 's' => $word, 'offset' => '0', 'limit' => '20', 'total' => true, 'type' => '1', //搜索单曲(1),歌手(100),专辑(10),歌单(1000),用户(1002) ); $headers = array( 'Connection: close', 'Content-Type: application/x-www-form-urlencoded', 'Host: music.163.com', 'Cookie: appver=1.5.0.75771;'); $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "http://music.163.com/api/search/pc", CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query($params), // CURLOPT_REFERER => "http://music.163.com/", // CURLOPT_HTTPHEADER => $headers, )); $output = curl_exec($curl); curl_close($curl); return $output; } /** * Gets all lyrics, apart from original one, translated and karaoke versions will also be returned if available. */ private function downloadLyric($music_id) { // lv = original version; tv = translated version; kv = karaoke version, rarely available. Set value to 0 if don't want $url = "http://music.163.com/api/song/lyric?os=pc&id=" . $music_id . "&lv=-1&kv=0&tv=-1"; $response = $this->download($url); if ($this->isNullOrEmptyString($response)) { return NULL; } $json = json_decode($response, true); return $json['lrc']['lyric']; } // Function for basic field validation (present and neither empty nor only white space private static function isNullOrEmptyString($question){ return (!isset($question) || trim($question)===''); } private static function download($url) { $header[] = "Cookie: appver=1.5.0.75771;"; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => $url, // CURLOPT_HTTPHEADER => $header, CURLOPT_RETURNTRANSFER => true, // CURLOPT_BINARYTRANSFER => true, // CURLOPT_REFERER => "http://music.163.com/", )); $output = curl_exec($curl); curl_close($curl); return $output; } } ////////////////////////// Debug //////////////////////////////////// if ($DEBUG == true) { class TestObj { private $items; function __construct() { $this->items = array(); } public function addLyrics($lyric, $id) { printf("\n"); printf("song id: %s\n", $id); printf("\n"); printf("== lyric ==\n"); printf("%s\n", $lyric); printf("** END of lyric **\n\n"); } public function addTrackInfoToList($artist, $title, $id, $prefix) { printf("\n"); printf("song id: %s\n", $id); printf("artist [%s]\n", $artist); printf("title [%s]\n", $title); printf("prefix [%s]\n", $prefix); printf("\n"); array_push($this->items, array( 'artist' => $artist, 'title' => $title, 'id' => $id )); } function getItems() { return $this->items; } function getFirstItem() { if (count($this->items) > 0) { return $this->items[0]; } else { return NULL; } } } /** * Main */ $artist = " lisa"; $title = "catch the moment "; echo "Trying to find lyrics for ['$title'] by artist ['$artist'] ...
"; $testObj = new TestObj(); $downloader = (new ReflectionClass("LudysuNetEaseLrc"))->newInstance(); $count = $downloader->getLyricsList($artist, $title, $testObj); if ($count > 0) { $item = $testObj->getFirstItem(); if (array_key_exists('id', $item)) { $downloader->getLyrics($item['id'], $testObj); } else { echo "\nno id to query lyric\n"; } } else { echo " ****************************\n"; echo " *** Failed to find lyric ***\n"; echo " ****************************\n"; } }