使用 Last.fm API 获取相似歌曲

Getting similar songs using Last.fm API

我正在尝试使用 Last.fm's API to find similar songs given a song name. Last.fm has a feature that can do this called track.getSimilar, but both "track" and "artist" are required parameters. However, because of the way this works, I can't figure out a way to either a) get both a song name, and the artist from one search bar input, or b) get the song's artist using track.search。这是我的代码中与此相关的部分:

const API_KEY = (my key);
const DEFAULT_TRACK = 'humble.'
const DEFAULT_ARTIST = 'kendrick lamar'
const RESULT_LIMIT = 5;
const RESULT_PAGE = 1;
const API_GET_SIMILAR_URL = `http://ws.audioscrobbler.com/2.0/?method=track.getSimilar&limit=${RESULT_LIMIT}&format=json&api_key=${API_KEY}`

const initialState = {
  loading: false,
  tracks: [],
  errorMessage: null
}

const reducer = (state, action) => {
  switch (action.type) {
    case "SEARCH_REQUEST":
      return {
        ...state,
        loading: true,
        errorMessage: null
      };
    case "SEARCH_SUCCESS":
      return {
        ...state,
        loading: false,
        tracks: action.payload
      };
    case "SEARCH_FAILURE":
      return {
        ...state,
        loading: false,
        errorMessage: action.error
      };
    default:
      return state;
  }
}

useEffect(() => {
  fetch(`${API_GET_SIMILAR_URL}&page=${RESULT_PAGE}&artist=${DEFAULT_ARTIST}&track=${DEFAULT_TRACK}`)
    .then(response => response.json())
    .then(jsonResponse => {
      const tracks = jsonResponse.similartracks[Object.keys(jsonResponse.similartracks)[0]];
      dispatch({
        type: "SEARCH_SUCCESS",
        payload: tracks
      });
    });
}, []);

const search = (searchValue) => {
  dispatch({
    type: "SEARCH_REQUEST"
  });
  fetch(`${API_GET_SIMILAR_URL}&page=${RESULT_PAGE}&track=${searchValue}`)
    .then(response => response.json())
    .then(jsonResponse => {
      if (!jsonResponse.error) {
        const tracks = jsonResponse.similartracks[Object.keys(jsonResponse.similartracks)[0]];
        dispatch({
          type: "SEARCH_SUCCESS",
          payload: tracks
        });
      } else {
        dispatch({
          type: "SEARCH_FAILURE",
          error: jsonResponse.error
        });
      }
    });
};

let {
  tracks,
  errorMessage,
  loading
} = state;
console.log(state);

在我的搜索功能中,我在 Object.keys 行中收到 Uncaught (in promise) TypeError: Cannot convert undefined or null to object 错误,因为我在调用 API 时没有使用艺术家参数。我尝试使用 track.search 获取艺术家,但我不确定 where/how 是否将其合并到我的代码中。

感谢任何帮助或建议。谢谢。

我认为您的问题可能是缺少 URL 编码。我认为这是因为您的艺术家字符串中有一个 space,需要将其编码为 kendrick%20lamar 才能正确处理。

API's introduction page. UTF-8 is common, so you can use a function like encodeURI() to achieve this (MDN Web Docs) 中提到了编码。

检验该理论的一种方法是使用 track.getSimilar docs 中的示例 URL 中的值,即艺术家 cher 和曲目 believe。这些值方便地没有 spaces 或需要转义的特殊字符。通过了解预期的响应,它也是一个很好的功能基线,可以确保您的其余代码按预期运行。

也是一首好歌,一定要give it a listen:)