【问题标题】:How to search for a user by name using Spotify Web API如何使用 Spotify Web API 按名称搜索用户
【发布时间】:2016-07-31 21:07:37
【问题描述】:

我正在尝试创建一个 Android 应用程序,其中包含一项功能,您可以在其中按名称搜索 Spotify 用户。使用 Spotify 时,您可以通过 ID 或姓名搜索用户。但是,目前,我认为 Spotify Web API 不支持按名称搜索用户。如果您有用户 ID,则可以使用 Web API 访问他们的个人资料。但我希望有一种方法可以让您搜索用户名并通过这种方式获取他们的 ID。

Spotify 的 Web API 允许您搜索“曲目”或“艺术家”,它们将返回所有搜索结果。那么为什么你不能对用户名做同样的事情呢?有什么方法可以使我没有看到的这项工作?

【问题讨论】:

    标签: spotify


    【解决方案1】:

    我认为这是一个有趣的问题,因为它涉及到一个庞大社区的用户数据,所以我会试着弄清楚。

    首先,您可以清楚地看到 Spotify Web API 端点search 有一个 type 参数,它只接受以下类型:artistplaylisttrack。 让我们尝试从这里运行(注意:请参阅Promise.all 获取数据的解决方案,我正在使用here

    注意 最近的 Spotify search API 需要在请求标头中指定访问令牌:

    -H "Authorization: Bearer {your access token}" 
    

    var spotifyAccessToken = "YourSpotifyAccessToken";
    var console = {
        log: function(s) {
          document.getElementById("console").innerHTML += s + "<br/>"
        }
      }
      // Simple XMLHttpRequest
      // based on https://davidwalsh.name/xmlhttprequest
    SimpleRequest = {
        call: function(what, response) {
          var request;
          if (window.XMLHttpRequest) { // Mozilla, Safari, ...
            request = new XMLHttpRequest();
          } else if (window.ActiveXObject) { // IE
            try {
              request = new ActiveXObject('Msxml2.XMLHTTP');
            } catch (e) {
              try {
                request = new ActiveXObject('Microsoft.XMLHTTP');
              } catch (e) {}
            }
          }
          // state changes
          request.onreadystatechange = function() {
            if (request.readyState === 4) { // done
              if (request.status === 200) { // complete	
                response(request.responseText)
              } else response();
            }
          }
          request.open('GET', what, true);
          request.setRequestHeader("Authorization", "Bearer " + spotifyAccessToken);
          request.send(null);
        }
      }
      //PromiseAll
    var promiseAll = function(items, block, done, fail) {
      var self = this;
      var promises = [],
        index = 0;
      items.forEach(function(item) {
        promises.push(function(item, i) {
          return new Promise(function(resolve, reject) {
            if (block) {
              block.apply(this, [item, index, resolve, reject]);
            }
          });
        }(item, ++index))
      });
      Promise.all(promises).then(function AcceptHandler(results) {
        if (done) done(results);
      }, function ErrorHandler(error) {
        if (fail) fail(error);
      });
    }; //promiseAll
    
    // LP: deferred execution block
    var ExecutionBlock = function(item, index, resolve, reject) {
      var url="https://api.spotify.com/v1/"
      url+=item;
      SimpleRequest.call(url, function(result) {
        if (result) {
          console.log( JSON.stringify( result, null, 2)
                      .replace(/\\n/g,"<br>").replace(/\\"/g,'"'));
          resolve(result);
        } else {
          reject(new Error("call error"));
        }
      })
    }
    
    arr = [
      "search?type=playlist&q=%22doom%20metal%22",
      "search?type=playlist&q=Adele"]
    promiseAll(arr, function(item, index, resolve, reject) {
      console.log("Making request [" + index + "]")
      ExecutionBlock(item, index, resolve, reject);
    }, function(results) { // aggregated results
      console.log("All response received " + results.length);
      //console.log(JSON.stringify(results));
    }, function(error) { // error
      console.log(error);
    });
    &lt;div id="console" /&gt;

    所有这些对象都是自定义的,但只有一个:playlist。 事实上,我们可以从这个响应中看到我们有 user 对象,例如(示例):

    "owner" {
        "external_urls": {
       "spotify": "http://open.spotify.com/user/12345678"
     }
    

    很好!external_urls 是用户个人资料 url,而 href 是播放列表 url(需要身份验证),因此我们可以首先从 json 响应中获取它们:

    var console = {
            log: function(s) {
              document.getElementById("console").innerHTML += s + "<br/>"
            }
          }
          // Simple XMLHttpRequest
          // based on https://davidwalsh.name/xmlhttprequest
        SimpleRequest = {
            call: function(what, response) {
              var request;
              if (window.XMLHttpRequest) { // Mozilla, Safari, ...
                request = new XMLHttpRequest();
              } else if (window.ActiveXObject) { // IE
                try {
                  request = new ActiveXObject('Msxml2.XMLHTTP');
                } catch (e) {
                  try {
                    request = new ActiveXObject('Microsoft.XMLHTTP');
                  } catch (e) {}
                }
              }
              // state changes
              request.onreadystatechange = function() {
                if (request.readyState === 4) { // done
                  if (request.status === 200) { // complete	
                    response(request.responseText)
                  } else response();
                }
              }
              request.open('GET', what, true);
              request.send(null);
            }
          }
          //PromiseAll
        var promiseAll = function(items, block, done, fail) {
          var self = this;
          var promises = [],
            index = 0;
          items.forEach(function(item) {
            promises.push(function(item, i) {
              return new Promise(function(resolve, reject) {
                if (block) {
                  block.apply(this, [item, index, resolve, reject]);
                }
              });
            }(item, ++index))
          });
          Promise.all(promises).then(function AcceptHandler(results) {
            if (done) done(results);
          }, function ErrorHandler(error) {
            if (fail) fail(error);
          });
        }; //promiseAll
    
        // LP: deferred execution block
        var ExecutionBlock = function(item, index, resolve, reject) {
          var url="https://api.spotify.com/v1/"
          url+=item;
          SimpleRequest.call(url, function(result) {
            if (result) {
              
              JSON.parse(result).playlists.items.map(function(item,index) {
                var userProfileUrl = item.owner.href;
                console.log( JSON.stringify( userProfileUrl, null, 2)
                          .replace(/\\n/g,"<br>").replace(/\\"/g,'"') ); 
              })
              
              resolve(result);
            } else {
              reject(new Error("call error"));
            }
          })
        }
    
        arr = [
          "search?type=playlist&q=%22doom%20metal%22",
          "search?type=playlist&q=Adele"]
        promiseAll(arr, function(item, index, resolve, reject) {
          console.log("Making request [" + index + "]")
          ExecutionBlock(item, index, resolve, reject);
        }, function(results) { // aggregated results
          console.log("All response received " + results.length);
          //console.log(JSON.stringify(results));
        }, function(error) { // error
          console.log(error);
        });
    &lt;div id="console" /&gt;

    此时您将看到一个 spotify user 对象 url 列表,例如(示例 url)

    "https://api.spotify.com/v1/users/12345678"
    

    所以现在我们可以获取用户配置文件 url(无需身份验证):

    var console = {
        log: function(s) {
          document.getElementById("console").innerHTML += s + "<br/>"
        }
      }
      // Simple XMLHttpRequest
      // based on https://davidwalsh.name/xmlhttprequest
    SimpleRequest = {
        call: function(what, response) {
          var request;
          if (window.XMLHttpRequest) { // Mozilla, Safari, ...
            request = new XMLHttpRequest();
          } else if (window.ActiveXObject) { // IE
            try {
              request = new ActiveXObject('Msxml2.XMLHTTP');
            } catch (e) {
              try {
                request = new ActiveXObject('Microsoft.XMLHTTP');
              } catch (e) {}
            }
          }
          // state changes
          request.onreadystatechange = function() {
            if (request.readyState === 4) { // done
              if (request.status === 200) { // complete	
                response(request.responseText)
              } else response();
            }
          }
          request.open('GET', what, true);
          request.send(null);
        }
      }
      //PromiseAll
    var promiseAll = function(items, block, done, fail) {
      var self = this;
      var promises = [],
        index = 0;
      items.forEach(function(item) {
        promises.push(function(item, i) {
          return new Promise(function(resolve, reject) {
            if (block) {
              block.apply(this, [item, index, resolve, reject]);
            }
          });
        }(item, ++index))
      });
      Promise.all(promises).then(function AcceptHandler(results) {
        if (done) done(results);
      }, function ErrorHandler(error) {
        if (fail) fail(error);
      });
    }; //promiseAll
    
    // LP: deferred execution block
    var ExecutionBlock = function(item, index, resolve, reject) {
      var url = "https://api.spotify.com/v1/"
      url += item;
      SimpleRequest.call(url, function(result) {
        if (result) {
    
          var profileUrls = JSON.parse(result).playlists.items.map(function(item, index) {
            return item.owner.href;
          })
          resolve(profileUrls);
        } else {
          reject(new Error("call error"));
        }
      })
    }
    
    arr = [
      "search?type=playlist&q=%22doom%20metal%22",
      "search?type=playlist&q=Adele"
    ]
    promiseAll(arr, function(item, index, resolve, reject) {
        console.log("Making request [" + index + "]")
        ExecutionBlock(item, index, resolve, reject);
      }, function(results) { // aggregated results
    
        console.log("All profiles received " + results.length);
        //console.log(JSON.stringify(results[0], null, 2));
    
        ///// promiseall again
    
        var ExecutionProfileBlock = function(item, index, resolve, reject) {
          SimpleRequest.call(item, function(result) {
            if (result) {
              var obj = JSON.parse(result);
              resolve({
                name: obj.display_name ,
                followers: obj.followers.total,
                url : obj.href
              });
            }//result
          })
        }//ExecutionProfileBlock
    
    promiseAll(results[0], function(item, index, resolve, reject) {
                  //console.log("Making request [" + index + "] " + item)
                  ExecutionProfileBlock(item, index, resolve, reject);
                }, function(results) { // aggregated results
                   console.log("All response received " + results.length);
                  console.log( JSON.stringify(results, null, 2) );
                }
    
                ,function(error) { // error
                  console.log(error);
                })
    
    
    
        /////
    
    
      },
      function(error) { // error
        console.log(error);
      });
    &lt;div id="console" /&gt;

    拿出来!此时我们可以看到user 对象与display_namefollowers 类似(示例json):

    {
        "name": "Joe Deere",
        "followers": 666,
        "url": "https://api.spotify.com/v1/users/12345678"
    }
    

    所以,回顾一下,起点是搜索 api 中的playlist 搜索类型。鉴于此,您可以获得无需身份验证的用户配置文件。假设您获得了有效的 oauth 令牌,您可以获取热门图表以进行进一步查询。

    【讨论】:

    • 我想我不理解你的第一部分代码。看起来您正在使用关键字“doom metal”和“Adele”进行播放列表搜索。据我了解,您是根据这些播放列表结果找到用户的。这些用户是否隶属于包含阿黛尔或厄运金属的播放列表?这是否意味着要查找用户个人资料,我需要了解有关其播放列表的信息?我根本看不到这段代码如何使用输入信息“用户名”,我所看到的只是播放列表信息作为输入。
    • @OMGitzMidgar 是的,这是将用户作为输出的唯一方法,因为无法查询用户名,如果您在答案中唯一可以查询的对象是艺术家、专辑、曲目和播放列表。但是,给定播放列表,您可以将 usera 作为输出,这是问题的一半;)
    猜你喜欢
    • 2022-11-17
    • 2022-06-11
    • 1970-01-01
    • 1970-01-01
    • 2015-11-06
    • 2017-11-17
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多