2015-04-03 90 views
2

在iTunes搜索API doc有一個名爲栗色尋找一個藝術家的例子,該網址是像這樣:如何實體類型的搜索結合起來,蘋果的iTunes搜索API

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" 
     }, 

這很好。然而,這是我的問題:我想創建一個搜索查詢,儘可能具體通過結合搜索藝術家和歌曲名稱和專輯名稱..

因此,例如,我得到了這首歌曲:

  • 歌曲:橫跨大分水嶺
  • 專輯:大分水嶺
  • 藝術家: Semisonic

我可以只搜索藝術家名稱:

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人..但我只是萬t搜索查詢具體到足以避免任何客戶端過濾某種東西)。

我該如何結合這些搜索?如果我只需添加兩個搜索在一起(在這個例子中我在尋找既歌曲藝術家):

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

那麼蘋果將簡單地忽略第一個搜索類型(即歌曲)並返回藝術家的結果只要)。

想法?

回答

1

嗯,這更多的是一種「變通」的答案..但它是我使用的解決方案..所以還不如傳播愛吧?

這是一個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:@""]; 
} 

獎金 這是解決我們目前正在使用..我完全知道一些術語可能出現,打破了這種算法..所以我們有一個單元測試,我們逐步添加條款,以確保我們不斷改進我們的算法wh ile不會導致迴歸錯誤..我會發布它,如果我得到足夠的投票在這個答案嘿。

1

abbood,

對不起,你不能從這裏到達那裏! (除非別人找到了新的東西。)

我目前正在開發一個應用程序,它將結合多個查詢的結果。

對於更冒險的Apple向聯屬合作伙伴提供「從iTunes和App Store提供的完整元數據集的數據饋送」。要使用這個,我會把一個數據庫服務放在雲中的某個地方,並用它來做更詳細的查詢,並顯示Search API沒有返回的細節。

如果我的應用程序完成並且實際上被超過5人使用,我可能會看完整個數據庫版本。

大衛

+0

看着我[回覆](http://stackoverflow.com/a/29530049/766570)David – abbood 2015-04-09 04:54:19

+0

@DavidReich嗨大衛,你有沒有去過使用Apple DataFeed的艱辛之路?如果是這樣,你有什麼要做的聯盟合作伙伴? – 2017-09-17 07:34:17

+1

@ThreadPitt我從來沒有完成應用程序。我發現Apple使用的關鍵字在URL搜索API返回的記錄中不存在,並且DataFeed中不存在。例如...我做了一個返回音頻書籍記錄的搜索。這些記錄沒有我使用的搜索字詞!我認爲這也不在DataFeed中。 (這是幾年前,現在。)我擡頭看亞馬遜的有聲讀物。搜索詞是「敘述者」的名字。在這之後我放棄了! 會員也是幾年前。除常規開發者帳戶之外的更多步驟。 – 2017-09-17 15:21:36