当前位置: 首页 > 知识库问答 >
问题:

可接受从Spotify搜索API保存结果?

晏永康
2023-03-14

在阅读Spotify web API的TOS时,不允许开发人员在创建数据库时聚合API中的数据。我不知道我试图完成的是否算作“聚合”

我有一个网站,允许用户对婚礼上播放的歌曲提出建议。我让他们输入歌曲名、艺术家和专辑名,这样DJ就可以很容易地找到音乐。所有这些都是用户提供的。然后,歌曲由新娘/新郎批准,并由其他嘉宾投票,生成一个播放列表,让DJ知道哪些音乐将在活动中流行。

我想提供的是一种方式,让用户使用这些信息,并能够搜索Spotify上排名前几位的搜索结果,选择正确的曲目,并将Spotify曲目与他们的建议关联起来。这让其他客人听到他们建议的歌曲,如果他们不熟悉它,并允许管理员根据新娘/新郎的口味允许或不允许歌曲。

为了避免API调用超过速率限制,我希望能够将搜索结果返回的Spotify URI与用户提供的歌曲信息一起存储,以便我可以在网站上为建议的歌曲生成播放按钮。

这算不算聚合,或者在web搜索API的当前TOS下允许这样做?

共有2个答案

钱稳
2023-03-14

我用这个:

<?php
namespace App\Services;

use DB;
use Exception;
use App\Genre;
use App\Album;
use App\Artist;
use Illuminate\Support\Str;

class ArtistSaver {

    /**
     * Save artist to database and return it.
     * 
     * @param  array $data
     * @return Artist
     */
    public function save($data)
    {
        $artist = Artist::whereName($data['mainInfo']['name'])->first();

        if ( ! $artist) {
            $artist = Artist::create($data['mainInfo']);
        } else {
            $artist->fill($data['mainInfo'])->save();
        }

        $this->saveAlbums($data, $artist);

        if (isset($data['albums'])) {
            $this->saveTracks($data['albums'], $artist);
        }

        if (isset($data['similar'])) {
            $this->saveSimilar($data['similar'], $artist);
        }

        if (isset($data['genres']) && ! empty($data['genres'])) {
            $this->saveGenres($data['genres'], $artist);
        }

        return $artist;
    }

    /**
     * Save and attach artist genres.
     *
     * @param array $genres
     * @param Artist $artist
     */
    public function saveGenres($genres, $artist) {

        $existing = Genre::whereIn('name', $genres)->get();
        $ids = [];

        foreach($genres as $genre) {
            $dbGenre = $existing->filter(function($item) use($genre) { return $item->name === $genre; })->first();

            //genre doesn't exist in db yet, so we need to insert it
            if ( ! $dbGenre) {
                try {
                    $dbGenre = Genre::create(['name' => $genre]);
                } catch(Exception $e) {
                    continue;
                }
            }

            $ids[] = $dbGenre->id;
        }

        //attach genres to artist
        $artist->genres()->sync($ids, false);
    }

    /**
     * Save artists similar artists to database.
     *
     * @param $similar
     * @param $artist
     * @return void
     */
    public function saveSimilar($similar, $artist)
    {
        $names = array_map(function($item) { return $item['name']; }, $similar);

        //insert similar artists that don't exist in db yet
        $this->saveOrUpdate($similar, array_flatten($similar), 'artists');

        //get ids in database for artist we just inserted
        $ids = Artist::whereIn('name', $names)->lists('id');

        //attach ids to given artist
        $artist->similar()->sync($ids);
    }

    /**
     * Save artist albums to database.
     * 
     * @param  array $data  
     * @param  Artist|null $artist
     * $param  int|null
     * @return void      
     */
    public function saveAlbums($data, $artist = null, $albumId = null)
    {
        if (isset($data['albums']) && count($data['albums'])) {
            $b = $this->prepareAlbumBindings($data['albums'], $artist, $albumId);
            $this->saveOrUpdate($b['values'], $b['bindings'], 'albums');
        }
    }

    /**
     * Save albums tracks to database.
     * 
     * @param  array $albums
     * @param  Artist|null $artist
     * @param  Album|null $trackAlbum
     * @return void
     */
    public function saveTracks($albums, $artist, $tracksAlbum = null)
    {
        if ( ! $albums || ! count($albums)) return;

        $tracks = [];

        foreach($albums as $album) {
            if ( ! isset($album['tracks']) || empty($album['tracks'])) continue;

            if ($tracksAlbum) {
                $id = $tracksAlbum['id'];
            } else {
                $id = $this->getIdFromAlbumsArray($album['name'], $artist['albums']);
            }

            foreach($album['tracks'] as $track) {
                $track['album_id'] = $id;
                $tracks[] = $track;
            }
        }

        if ( ! empty($tracks)) {
            $this->saveOrUpdate($tracks, array_flatten($tracks), 'tracks');
        }
    }

    private function getIdFromAlbumsArray($name, $albums) {
        $id = false;

        foreach($albums as $album) {
            if ($name === $album['name']) {
                $id = $album['id']; break;
            }
        }

        if ( ! $id) {
            foreach($albums as $album) {
                if (Str::slug($name) == Str::slug($album['name'])) {
                    $id = $album['id']; break;
                }
            }
        }

        return $id;
    }

    /**
     * Unset tracks key from album arrays and flatten them into single array.
     * 
     * @param  array $albums
     * @param  Artist|null $artist
     * @param  int|null $albumId
     * @return array       
     */
    private function prepareAlbumBindings($albums, $artist = null, $albumId = null)
    {
        $flat = [];

        foreach($albums as $k => $album) {
            if (isset($albums[$k]['tracks'])) unset($albums[$k]['tracks']);

            if ( ! isset($albums[$k]['artist_id']) || ! $albums[$k]['artist_id']) {
                $albums[$k]['artist_id'] = $artist ? $artist->id : 0;
            }

            //can't insert null into auto incrementing id because
            //mysql will increment the id instead of keeping the old one
            if ($albumId) {
                $albums[$k]['id'] = $albumId;
            }

            foreach($albums[$k] as $name => $data) {
                if ($name !== 'tracks') {
                    $flat[] = $data;
                }
            }
        }


        return ['values' => $albums, 'bindings' => $flat];
    }

    /**
     * Compiles insert on duplicate update query for multiple inserts.
     *
     * @param array  $values
     * @param array  $bindings
     * @param string $table
     *
     * @return void
     */
    public function saveOrUpdate(array $values, $bindings, $table)
    {
        if (empty($values)) return;

        $first = head($values);

        //count how many inserts we need to make
        $amount = count($values);

        //count in how many columns we're inserting
        $columns = array_fill(0, count($first), '?');

        $columns = '(' . implode(', ', $columns) . ') ';

        //make placeholders for the amount of inserts we're doing
        $placeholders = array_fill(0, $amount, $columns);
        $placeholders = implode(',', $placeholders);

        $updates = [];

        //construct update part of the query if we're trying to insert duplicates
        foreach ($first as $column => $value) {
            $updates[] = "$column = COALESCE(values($column), $column)";
        }

        $prefixed = DB::getTablePrefix() ? DB::getTablePrefix().$table : $table;

        $query = "INSERT INTO {$prefixed} " . '(' . implode(',' , array_keys($first)) . ')' . ' VALUES ' . $placeholders .
            'ON DUPLICATE KEY UPDATE ' . implode(', ', $updates);

        DB::statement($query, $bindings);
    }
}
文华美
2023-03-14

你所做的听起来很好。

你问的服务条款部分是为了防止人们在没有用户互动的情况下制作自动工具来抓取Spotify目录。如果你正在编写一个“普通”应用程序,并从Spotify应用程序接口缓存数据,因为用户实际上在做一些事情,比如搜索、浏览等,你没有问题。

资料来源:我在Spotify工作。

 类似资料:
  • API流改变了吗? 我再也不能为搜索曲目或艺术家进行简单的公共API调用了? 此外,我在Spotify文档中看到,如果查询字符串中提供了market=from_token,则需要授权。否则,可选。

  • 我正在建立一个网站,我正在使用Spotify应用编程接口作为音乐库。我想添加更多的过滤器和订单选项来搜索Traks比api允许我,所以我想知道什么轨道/歌曲数据可以从API保存到我的数据库,如艺术家名称或流行度。 我想保存:姓名、艺术家、专辑和其他一些东西。这是可能的还是违反了条款和条件? 提前感谢!

  • 我正在学习node,我正在尝试使用spotifyapi搜索并返回一个艺术家。页面加载了所有内容,但是当我尝试搜索时,我得到了这个错误 经过一番挖掘,我发现我出现这个错误的原因是: 在中,chunk正在返回 请求的路径(假定)是api.spotify.com/v1/search?q=sam

  • 我们的Spotify链接如下所示: 我们刚刚注意到所有这些链接似乎都被破坏了--Spotify只是返回一个网页,上面写着“对不起,找不到那个”。我很难在网上找到任何有关这方面的信息。有没有人知道Spotify最近是否改变了他们的API,我们可以做什么来修复这些URL?

  • 我正在尝试搜索Spotify中的曲目元数据。我想看看Spotify是否有一首来自YouTube视频的歌曲。这是我用于进行搜索的URL模板: 由于很难确定搜索查询的哪一部分是艺术家还是曲目,因此我将这两种类型添加为搜索查询的类型。 然而,当我得到一个YouTube的视频,标题是这样的:“凯蒂·佩里——我们是这样做的(官方视频)[·莱特拉·西班牙语——歌词英语”,并将其用作我的搜索词时,我得到了0个结

  • 我目前正在尝试将Spotify应用程序迁移到api的新1.0版本。 我在搜索方面有问题。我想用搜索字符串搜索目录,并从搜索结果中获取所有曲目信息、艺术家姓名和专辑名称。但是,搜索结果中似乎不包括唱片集名称(仅URI:s)。 之后我是否必须异步加载所有结果曲目的所有唱片集名称?如果可能的话,我想避免这种情况。 我正在这样寻找