4

itunes search api docには、 maroonというアーティストを検索する例があり、URL は次のようになります。

https://itunes.apple.com/search?term=maroon&entity=allArtist&attribute=allArtistTerm

これは、次のように始まる 50 を超える結果を返します。

{
    "resultCount": 50,
    "results": [
        {
            "wrapperType": "artist",
            "artistType": "Artist",
            "artistName": "Maroon 5",
            "artistLinkUrl": "https://itunes.apple.com/us/artist/maroon-5/id1798556?uo=4",
            "artistId": 1798556,
            "amgArtistId": 529962,
            "primaryGenreName": "Pop",
            "primaryGenreId": 14,
            "radioStationUrl": "https://itunes.apple.com/station/idra.1798556"
        },
        {
            "wrapperType": "artist",
            "artistType": "Software Artist",
            "artistName": "MaroonEntertainment",
            "artistLinkUrl": "https://itunes.apple.com/us/artist/maroonentertainment/id537029262?uo=4",
            "artistId": 537029262,
            "radioStationUrl": "https://itunes.apple.com/station/idra.537029262"
        },

いいですね。ただし、ここに私の問題があります。アーティストと曲名とアルバム名の両方の検索を組み合わせて、できるだけ具体的な検索クエリを作成したいと思います..

たとえば、こんな曲を手に入れました。

  • 曲名:アクロス・ザ・グレート・ディバイド
  • アルバム:グレート・ディバイド
  • アーティスト:セミソニック

アーティスト名のみを検索できます。

https://itunes.apple.com/search?term=Semisonic&entity=allArtist&attribute=allArtistTerm

曲の用語のみを検索できます。

https://itunes.apple.com/search?term=Across the Great Divide&entity=song&attribute=songTerm

アルバム名のみを検索できます。

https://itunes.apple.com/search?term=Great Divide&entity=album&attribute=albumTerm

しかし、これらの人は誰も私が望む結果を与えてくれません (私が探している結果をおそらく 50 の他の人の中から見つけることができます..しかし、クライアント側のフィルタリングのようなものを避けるために、検索クエリを十分に具体的にしたいだけです)。

これらの検索を組み合わせるにはどうすればよいですか? 単純に 2 つの検索を追加すると (この例では、曲アーティストの両方を検索しています):

https://itunes.apple.com/search?term=Across the Great Divide&entity=song&attribute=songTerm&term=Semisonic&entity=allArtist&attribute=allArtistTerm

その場合、Apple は最初の検索タイプ (曲など) を単純に無視し、アーティストのみの結果を返します)。

アイデア?

4

2 に答える 2

2

まあ、これは「回避策」の答えです..しかし、それは私が使用している解決策です..それで、愛を広めた方がいいでしょうか?

これは 100% クライアント側のソリューションです (つまり、iTunes 音楽のデータベース全体を自分のサーバーにダウンロードすることができます..その後、その周りにさまざまな検索ラッパーを作成できます..しかし、それ自体がプロジェクトです)。

これは私が得たものです:

// this is just a wrapper around the apple search api.. it makes your 
// average joe http get request
[[AppleServer shared] searchForSongWithTitle:track.title andAlbumName:track.albumName completion:^(NSArray *results, NSError *error){
    if ([results count] >0) {
        NSLog(@"[%d] unfiltered songs retrieved from apple search api", [results count]);
        NSDictionary *filteredResult = [[self class] filterResults:results ToMatchTrack:track];
        if (!filteredResult) {
            NSLog(@"Filtering may be too strict, we got [%d] results from apple search api but none past our filter", [results count]);
            return;
        }

        .. process results


+ (NSDictionary *)filterResults:(NSArray *)results ToMatchTrack:(VBSong *)track
{

    NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSDictionary *evaluatedTrack, NSDictionary *bindings){    
        BOOL result =
         ([track.title isLooselyEqualToString:evaluatedTrack[@"trackName"]] &&
          [track.artistName isLooselyEqualToString:evaluatedTrack[@"artistName"]] &&
          [track.albumName isLooselyEqualToString:evaluatedTrack[@"collectionName"]]);

        NSLog(@"match?[%d]", result);

        return result;
    }];

    return [[results filteredArrayUsingPredicate:predicate] firstObject];
}

ここでの重要なメソッドはisLooselyEqualToString..次のように NSString カテゴリで定義されています。

/**
 * Tests if one string equals another substring, relaxing the following contraints
 *   - one string can be a substring of another
 *   - it's a case insensitive comparison
 *   - all special characters are removed from both strings
 *
 *     ie this should return true for this comparison:
 *     - comparing self:"Circus One (Presented By Doctor P and Flux Pavilion)" 
                and str:"Circus One presented by Doctor P"
 *
 * @param str string to compare self against
 * @return if self is the same as str, relaxing the contraints described above
 */
- (BOOL)isLooselyEqualToString:(NSString *)str
{
    return [[self removeSpecialCharacters] containSubstringBothDirections:[str removeSpecialCharacters]];
}

/**
 * Tests if one string is a substring of another
 *     ie this should return true for both these comparisons:
 *     - comparing self:"Doctor P & Flux Pavilion" and substring:"Flux Pavilion"
 *     - comparing self:"Flux Pavilion" and substring:"Doctor P & Flux Pavilion"
 *
 * @param substring to compare self against
 * @return if self is a substring of substring
 */
-(BOOL)containSubstringBothDirections:(NSString*)substring
{
    if (substring == nil) return self.length == 0;

    if ([self rangeOfString:substring options:NSCaseInsensitiveSearch].location == NSNotFound) {
        if ([substring rangeOfString:self options:NSCaseInsensitiveSearch].location == NSNotFound) {
            return NO;
        } else {
            return YES;
        }
    } else {
        return YES;
    }
}

- (NSString *)removeSpecialCharacters
{
    NSMutableCharacterSet *specialCharsSet = [[NSCharacterSet letterCharacterSet] mutableCopy];
    [specialCharsSet formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]];
    return [[self componentsSeparatedByCharactersInSet:[specialCharsSet invertedSet]] componentsJoinedByString:@""];
}

ボーナス これは私たちが現在使用しているソリューションです..このアルゴリズムを破るいくつかの用語が出てくる可能性があることを十分に認識しています.回帰バグを引き起こさない..この回答に十分な票が集まったら投稿します。

于 2015-04-09T04:53:58.620 に答える
1

アブード、

申し訳ありませんが、ここからはアクセスできません。(他の誰かが何か新しいものを見つけた場合を除きます。)

現在、複数のクエリの結果を組み合わせるアプリを開発しています。

もっと冒険的な人のために、Apple は「iTunes と App Store からの完全なメタデータ セットのデータ フィード」をアフィリエイト パートナーに提供しています。これを使用するには、データベース サービスをクラウドのどこかに配置し、それを使用してより詳細なクエリを作成し、Search API によって返されない詳細を表示します。

アプリを完成させて、実際に 5 人以上が使用している場合は、データベース全体のバージョンを作成することを検討するかもしれません。

デビッド

于 2015-04-09T04:27:21.117 に答える