英文:
Getting Most Recent Results when Searching for Podcast Episodes in the Spotify API
问题
我假装获取最新的剧集,当它们的标题或描述包含一些文本时,比如,“tim ferriss”。这是否可能?我成功使用搜索项目选项来搜索特定的字符串,但我无法弄清楚如何按发布日期排序结果。提前感谢。
英文:
I pretend to get the most recent episodes for when their title or description contain some text like, for example, "tim ferriss". Is this possible? I managed to search for certain strings with Search for Item option but I can't figure out how to sort the results by publication datetime. Thanks in advance.
答案1
得分: 0
Search for Item
API没有排序选项。
因此,您必须根据自己的逻辑在客户端进行排序。
您没有指定语言选项。
我用node.js
制作了一个演示代码。
演示代码
const express = require("express")
const axios = require('axios')
const cors = require("cors")
const fs = require('fs')
const app = express()
app.use(cors())
// 凭据
CLIENT_ID = "<your Client ID>"
CLIENT_SECRET = "<your Client Secret>"
PORT = 3000 // it is located in Spotify dashboard's Redirect URIs, my port is 3000, should be replace your Port
REDIRECT_URI = `http://localhost:${PORT}/callback` // my case is 'http://localhost:3000/callback'
SCOPE = [
'user-read-private'
]
// 获取访问令牌
const getToken = async (code) => {
try {
const resp = await axios.post(
url = 'https://accounts.spotify.com/api/token',
data = new URLSearchParams({
'grant_type': 'authorization_code',
'redirect_uri': REDIRECT_URI,
'code': code
}),
config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
auth: {
username: CLIENT_ID,
password: CLIENT_SECRET
}
})
return Promise.resolve(resp.data.access_token);
} catch (err) {
console.error(err)
return Promise.reject(err)
}
}
// 通过查询获取剧集
const getEpisodes = async (token, query) => {
try {
let offset = 0
let next = 1
const limit = 50;
const episodes = [];
const encodeString = encodeURI(query)
while (next != null) {
const resp = await axios.get(
url = `https://api.spotify.com/v1/search?q=${encodeString}&type=episode&limit=${limit}&offset=${offset}`,
config = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
}
})
for(const item of resp.data.episodes.items) {
if(item?.name != null) {
episodes.push({
name: item.name,
release_date: item.release_date,
external_urls: item.external_urls.spotify,
duration_ms: item.duration_ms,
type: item.type,
id : item.id,
// <extension data>
// audio_preview_url: item.audio_preview_url,
// description: item.description,
// html_description: item.html_description,
// images : item.images,
})
}
}
offset = offset + limit
next = resp.data.episodes.next
}
// 在发布日期排序后
return Promise.resolve(episodes.sort((a,b) => Date.parse(b.release_date) - Date.parse(a.release_date)));
} catch (err) {
console.error(err)
return Promise.reject(err)
}
}
// 登录URL
app.get("/login", (request, response) => {
const redirect_url = `https://accounts.spotify.com/authorize?response_type=code&client_id=${CLIENT_ID}&scope=${SCOPE}&state=123456&redirect_uri=${REDIRECT_URI}&prompt=consent`
response.redirect(redirect_url);
})
// 回调URL
app.get("/callback", async (request, response) => {
const code = request.query["code"]
getToken(code)
.then(access_token => {
getEpisodes(access_token,"tim ferriss")
.then(episodes => {
// For file save
const data = JSON.stringify(episodes);
fs.writeFileSync('simple_results.json', data);
// For browser displaying
return response.send({
'Total episodes length: ': episodes.length,
'Episodes': episodes
});
})
})
.catch(error => {
console.log(error.message);
})
})
// 启动express服务器
app.listen(PORT, () => {
console.log(`Listening on :${PORT}`)
})
安装依赖项
npm install axios express cors fs
运行服务器
node demo.js
登录并获取剧集
端口号应与您的端口号匹配。
http://localhost:3000/user
结果
如果要查看完整数据,请取消注释getEpisodes()
中的代码
episodes.push({
name: item.name,
release_date: item.release_date,
external_urls: item.external_urls.spotify,
duration_ms: item.duration_ms,
type: item.type,
id : item.id,
// <extension data>
audio_preview_url: item.audio_preview_url,
description: item.description,
html_description: item.html_description,
images : item.images,
})
更新 - 添加Python演示
另存为get-episodes.py
文件名。
import spotipy
from spotipy.oauth2 import SpotifyOAuth
import pandas as pd
from urllib.parse import quote
import numpy as np
import datetime as DT
# 将您的Spotify API凭据设置为环境变量,它将被spotipy API自动选择
CLIENT_ID = "9d53d43408c04c089e58f6b615f44bf9"
CLIENT_SECRET = "96f14dc115644d83b8957b77fcface31"
PORT = 3000
REDIRECT_URI = "http://localhost:{0}/callback".format(PORT)
# 只需此范围即可获取user_recently_played API
scope = "user-read-recently-played"
# 此API调用会引发Web浏览器,并要求用户使用Authorization Code流进行登录以获取回调
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(
client_id = CLIENT_ID,
client_secret = CLIENT_SECRET,
redirect_uri = REDIRECT_URI,
scope = scope))
def get_episodes(query):
try:
offset = 0
limit = 50
episode_features_list = [
"name",
"release_date",
"tag_new",
"external_urls",
"duration_ms",
"type",
"id",
# <extension data>
# "audio_preview_url",
# "description",
# "html_description",
# "images",
]
episode_df = pd.DataFrame(columns=episode_features_list)
today = DT.date.today()
two_week_ago = today - DT.timedelta(days = 14)
while True:
results = sp.search(q=quote(query), type='episode', offset=offset, limit=limit)
for item in results['episodes']['items']:
# 创建空字典
episode_features = {}
<details>
<summary>英文:</summary>
The [`Search for Item`](https://developer.spotify.com/documentation/web-api/reference/search) API has no sort option.
So you have to sort at the client side by your own logic.
You did not specify the language option.
I made a demo code by `node.js`
#### Demo Code
```node.js
const express = require("express")
const axios = require('axios')
const cors = require("cors")
const fs = require('fs')
const app = express()
app.use(cors())
// Credential
CLIENT_ID = "<your Client ID>"
CLIENT_SECRET = "<your Client Secret>"
PORT = 3000 // it is located in Spotify dashboard's Redirect URIs, my port is 3000, should be replace your Port
REDIRECT_URI = `http://localhost:${PORT}/callback` // my case is 'http://localhost:3000/callback'
SCOPE = [
'user-read-private'
]
// Get Access Token
const getToken = async (code) => {
try {
const resp = await axios.post(
url = 'https://accounts.spotify.com/api/token',
data = new URLSearchParams({
'grant_type': 'authorization_code',
'redirect_uri': REDIRECT_URI,
'code': code
}),
config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
auth: {
username: CLIENT_ID,
password: CLIENT_SECRET
}
})
return Promise.resolve(resp.data.access_token);
} catch (err) {
console.error(err)
return Promise.reject(err)
}
}
// Get Episodes by query
const getEpisodes = async (token, query) => {
try {
let offset = 0
let next = 1
const limit = 50;
const episodes = [];
const encodeString = encodeURI(query)
while (next != null) {
const resp = await axios.get(
url = `https://api.spotify.com/v1/search?q=${encodeString}&type=episode&limit=${limit}&offset=${offset}`,
config = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
}
})
for(const item of resp.data.episodes.items) {
if(item?.name != null) {
episodes.push({
name: item.name,
release_date: item.release_date,
external_urls: item.external_urls.spotify,
duration_ms: item.duration_ms,
type: item.type,
id : item.id,
// <extension data>
// audio_preview_url: item.audio_preview_url,
// description: item.description,
// html_description: item.html_description,
// images : item.images,
})
}
}
offset = offset + limit
next = resp.data.episodes.next
}
// After sort by release date
return Promise.resolve(episodes.sort((a,b) => Date.parse(b.release_date) - Date.parse(a.release_date)));
} catch (err) {
console.error(err)
return Promise.reject(err)
}
}
// login URL
app.get("/login", (request, response) => {
const redirect_url = `https://accounts.spotify.com/authorize?response_type=code&client_id=${CLIENT_ID}&scope=${SCOPE}&state=123456&redirect_uri=${REDIRECT_URI}&prompt=consent`
response.redirect(redirect_url);
})
// Call back URL
app.get("/callback", async (request, response) => {
const code = request.query["code"]
getToken(code)
.then(access_token => {
getEpisodes(access_token,"tim ferriss")
.then(episodes => {
// For file save
const data = JSON.stringify(episodes);
fs.writeFileSync('simple_results.json', data);
// For browser displaying
return response.send({
'Total episodes length: ': episodes.length,
'Episodes': episodes
});
})
})
.catch(error => {
console.log(error.message);
})
})
// start express server
app.listen(PORT, () => {
console.log(`Listening on :${PORT}`)
})
Install dependencies
npm install axios express cors fs
Run the server
node demo.js
Login and Get Episodes
The port number should be match your port number.
http://localhost:3000/user
Result
If you want to see full data, remove commend-out code in getEpisodes()
episodes.push({
name: item.name,
release_date: item.release_date,
external_urls: item.external_urls.spotify,
duration_ms: item.duration_ms,
type: item.type,
id : item.id,
// <extension data>
audio_preview_url: item.audio_preview_url,
description: item.description,
html_description: item.html_description,
images : item.images,
})
Update - added Python demo
Save as get-episodes.py
file name.
import spotipy
from spotipy.oauth2 import SpotifyOAuth
import pandas as pd
from urllib.parse import quote
import numpy as np
import datetime as DT
# Set your Spotify API credentials as environment variables, it will pick by spotipy API
CLIENT_ID = "9d53d43408c04c089e58f6b615f44bf9"
CLIENT_SECRET = "96f14dc115644d83b8957b77fcface31"
PORT = 3000
REDIRECT_URI = "http://localhost:{0}/callback".format(PORT)
# Just this scope good enough to get user_recently_played API
scope = "user-read-recently-played"
# This API call raise web browser and ask user login for getting callback with Authorization Code flow
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(
client_id = CLIENT_ID,
client_secret = CLIENT_SECRET,
redirect_uri = REDIRECT_URI,
scope = scope))
def get_episodes(query):
try:
offset = 0
limit = 50
episode_features_list = [
"name",
"release_date",
"tag_new",
"external_urls",
"duration_ms",
"type",
"id",
# <extension data>
# "audio_preview_url",
# "description",
# "html_description",
# "images",
]
episode_df = pd.DataFrame(columns=episode_features_list)
today = DT.date.today()
two_week_ago = today - DT.timedelta(days = 14)
while True:
results = sp.search(q=quote(query), type='episode', offset=offset, limit=limit)
for item in results['episodes']['items']:
# Create empty dictionary
episode_features = {}
# Get metadata
episode_features["name"] = item["name"]
episode_features["release_date"] = pd.to_datetime(item["release_date"], format='%Y-%m-%d')
episode_features['tag_new'] = np.where(episode_features["release_date"] >= pd.to_datetime(two_week_ago, format='%Y-%m-%d'), True, False)
episode_features["external_urls"] = item["external_urls"]["spotify"]
episode_features["duration_ms"] = item["duration_ms"]
episode_features["type"] = item["type"]
episode_features["id"] = item["id"]
# Concatenate the data frames
item_df = pd.DataFrame(episode_features, index=[0])
episode_df = pd.concat([episode_df, item_df], ignore_index=True)
# Increment offset by the limit for the next API call
offset += limit
next = results['episodes']['next']
if next is None:
break
return episode_df
except Exception as e:
print('Failed to upload to call get_episodes(): '+ str(e))
episodes = get_episodes("tim ferriss")
sorted_episodes = episodes.sort_values(by='release_date', ascending = False)
print(sorted_episodes)
Run the python demo
python get-episodes.py
Python Result
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论