YouTube的videoID从URL – 目标C

我基本上有一个YouTube的url作为NSString,但我需要提取在URL中显示的videoID。 我发现许多教程如何在PHP或其他基于Web的编程语言,但没有在客观的C …

我基本上是寻找一个方法,要求一个NSStringurl作为参数,并返回videoID为另一个NSString …

任何人都知道如何做到这一点或任何教程呢?

所以,一个YouTubeurl看起来像这样:

http://www.youtube.com/watch?v=oHg5SJYRHA0

您感兴趣的videoID是最后一部分( oHg5SJYRHA0 ),尽pipe它不一定在最后,因为YouTubeurl可以在查询string中包含其他参数。

你最好的select可能是使用正则expression式和Foundation的NSRegularExpression类。 我认为这种方法被用在你发现的其他语言教程中 – 请注意,正则expression式的内容在包含它们的任何语言或工具包中都是相同的,所以在这些教程中find的任何正则expression式都应该可以工作为你。 (我build议不要打破v=方法,并且正好采用11个字符,因为这很容易导致各种失败模式,而正则expression式更强大。)

要findvideoID,你可能需要像v=([^&]+)这样的正则expression式。 v=让我们到查询url的右边部分(如果我们得到类似watch?fmt=22&v=oHg5SJYRHA0 )。 圆括号组成了一个捕获组,所以我们只能提取videoID而不是我们用来find它的其他匹配的字符,在圆括号内我们寻找一个或多个字符的序列,这不是一个&符号 – 这可以确保我们可以在v=whatever字段中得到所有的v=whatever ,如果你得到了像watch?v=oHg5SJYRHA0&rel=0这样的URL,那么它后面没有字段watch?v=oHg5SJYRHA0&rel=0

无论你使用这个还是另一个正则expression式,很可能你会使用捕获组。 (如果没有, rangeOfFirstMatchInString:options:range:几乎就是你需要的所有东西,就像在Dima的答案中看到的那样)。你可以使用firstMatchInString:options:range:或者类似的方法获得捕获组的内容(作为NSTextCheckingResult对象)

 NSError *error = NULL; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"?.*v=([^&]+)" options:NSRegularExpressionCaseInsensitive error:&error]; NSTextCheckingResult *match = [regex firstMatchInString:youtubeURL options:0 range:NSMakeRange(0, [youtubeURL length])]; if (match) { NSRange videoIDRange = [match rangeAtIndex:1]; NSString *substringForFirstMatch = [youtubeURL substringWithRange:videoIDRange]; } 

这里是RegExp它涵盖了这些情况

目标C

 - (NSString *)extractYoutubeIdFromLink:(NSString *)link { NSString *regexString = @"((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)"; NSRegularExpression *regExp = [NSRegularExpression regularExpressionWithPattern:regexString options:NSRegularExpressionCaseInsensitive error:nil]; NSArray *array = [regExp matchesInString:link options:0 range:NSMakeRange(0,link.length)]; if (array.count > 0) { NSTextCheckingResult *result = array.firstObject; return [link substringWithRange:result.range]; } return nil; } 

迅速

 func extractYoutubeIdFromLink(link: String) -> String? { let pattern = "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)" guard let regExp = try? NSRegularExpression(pattern: pattern, options: .CaseInsensitive) else { return nil } let nsLink = link as NSString let options = NSMatchingOptions(rawValue: 0) let range = NSRange(location: 0,length: nsLink.length) let matches = regExp.matchesInString(link as String, options:options, range:range) if let firstMatch = matches.first { return nsLink.substringWithRange(firstMatch.range) } return nil } 

Swift 3

 func extractYoutubeIdFromLink(link: String) -> String? { let pattern = "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)" guard let regExp = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive) else { return nil } let nsLink = link as NSString let options = NSRegularExpression.MatchingOptions(rawValue: 0) let range = NSRange(location: 0, length: nsLink.length) let matches = regExp.matches(in: link as String, options:options, range:range) if let firstMatch = matches.first { return nsLink.substring(with: firstMatch.range) } return nil } 

对不起 – 我没有足够的代表添加评论选定的答案。

花了很多时间试图find正则语法的正则expression式,我遇到了这个帮助我。 希望它可以帮助别人!

 NSString *regexString = @"(?<=v(=|/))([-a-zA-Z0-9_]+)|(?<=youtu.be/)([-a-zA-Z0-9_]+)"; 

从这里采取。 这适用于以下URL格式:

你可能看到的教程只是关于如何使用正则expression式的说明,这也是你想在这种情况下使用的。

您将需要使用的Cocoa类是NSRegularExpression 。

你真正的正则expression式string将取决于你期待的url的格式,因为它看起来像youtube有几个。 一般function如下所示:

 + (NSString *)extractYoutubeID:(NSString *)youtubeURL { NSError *error = NULL; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"your regex string goes here" options:NSRegularExpressionCaseInsensitive error:&error]; NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:youtubeURL options:0 range:NSMakeRange(0, [youtubeURL length])]; if(!NSEqualRanges(rangeOfFirstMatch, NSMakeRange(NSNotFound, 0))) { NSString *substringForFirstMatch = [youtubeURL substringWithRange:rangeOfFirstMatch]; return substringForFirstMatch; } return nil; } 

你甚至不需要正则expression式。 无论videoID的长度及其在url中的位置如何,以下内容均适用:

 NSString *vID = nil; NSString *url = @"http://www.youtube.com/watch?v=cAcqdjLCN7s"; NSString *query = [url componentsSeparatedByString:@"?"][1]; NSArray *pairs = [query componentsSeparatedByString:@"&"]; for (NSString *pair in pairs) { NSArray *kv = [pair componentsSeparatedByString:@"="]; if ([kv[0] isEqualToString:@"v"]) { vID = kv[1]; break; } } NSLog(@"%@", vID); 

基于这个答案: PHP的正则expression式来获得youtubevideoID?

我修改了c / objc / c ++string的正则expression式,这里的重要部分是正则expression式不会从Facebook或其他服务获取video。 iOS正则expression式基于: ICU

 NSString *regexString = @"^(?:http(?:s)?://)?(?:www\\.)?(?:m\\.)?(?:youtu\\.be/|youtube\\.com/(?:(?:watch)?\\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user)/))([^\?&\"'>]+)"; NSError *error; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexString options:NSRegularExpressionCaseInsensitive error:&error]; NSTextCheckingResult *match = [regex firstMatchInString:message options:0 range:NSMakeRange(0, [message length])]; if (match && match.numberOfRanges == 2) { NSRange videoIDRange = [match rangeAtIndex:1]; NSString *videoID = [message substringWithRange:videoIDRange]; return videoID; } 

火柴:

不匹配:

 - (NSString*)getYoutubeVideoID:(NSString*)url { NSError *error = NULL; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(?<=watch\\?v=|/videos/|embed\\/)[^#\\&\\?]*" options:NSRegularExpressionCaseInsensitive error:&error]; NSTextCheckingResult *match = [regex firstMatchInString:url options:0 range:NSMakeRange(0, [url length])]; NSString *substringForFirstMatch; if (match) { NSRange videoIDRange = [match rangeAtIndex:0]; substringForFirstMatch = [url substringWithRange:videoIDRange]; } return substringForFirstMatch; } 

我用最高的答案来写一个更好,更严格的正则expression式。

 NSString *regex = @"(?:youtube.com.+v[=/]|youtu.be/)([-a-zA-Z0-9_]+)"; 

然后你可以得到这个ID

 NSTextCheckingResult *match = [regex firstMatchInString:url options:0 range:NSMakeRange(0, [url length])]; NSRange videoIDRange = [match rangeAtIndex:1]; NSString *youTubeID = [url substringWithRange:videoIDRange]; 

这是我从StackOveFlow引用的解决scheme。 ( Youtube ID分析新的URL格式 )

我做了一些修改。

///这是.h

 #import <Foundation/Foundation.h> @interface YoutubeParser : NSObject +(BOOL) isValidateYoutubeURL:(NSString * )youtubeURL; +(NSArray *) parseHTML:(NSString *)html ; @end ///This is the .m #import "YoutubeParser.h" @interface YoutubeParser () { } @end @implementation YoutubeParser #define YOUTUBE_PATTERN @"(https?://)?(www\\.)?(youtu\\.be/|youtube\\.com)?(/|/embed/|/v/|/watch\\?v=|/watch\\?.+&v=)([\\w_-]{11})(&.+)?" +(NSRegularExpression *)regex { static NSRegularExpression * regex = nil; regex = [NSRegularExpression regularExpressionWithPattern:YOUTUBE_PATTERN options:NSRegularExpressionCaseInsensitive error:nil]; return regex; } +(BOOL) isValidateYoutubeURL:(NSString * )youtubeURL { NSInteger cnt = [[YoutubeParser regex] numberOfMatchesInString:youtubeURL options:0 range:NSMakeRange(0, [youtubeURL length]) ]; return cnt > 0 ? YES : NO; } typedef void (^matching_block_t) (NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop); +(NSArray *) parseHTML:(NSString *)html { NSMutableArray * youtubeURLArray = [[NSMutableArray alloc] init]; matching_block_t parseTask = ^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { NSRange matchRange = [result range]; NSRange youtubeKey = [result rangeAtIndex:5]; //the youtube key NSString * strKey = [html substringWithRange:youtubeKey] ; NSLog(@"youtubeKey=%@ , with url=%@ " ,strKey , [html substringWithRange:matchRange]); [youtubeURLArray addObject:strKey]; }; [[YoutubeParser regex] enumerateMatchesInString:html options:0 range:NSMakeRange(0, [html length]) usingBlock:parseTask ]; return youtubeURLArray; } @end 

这里有很多很好的答案,但是我认为从stringparsing多个video_ID可能是有益的。 这可能是一个网页或一个不同的URL的数组。

页面内容的示例

 NSString *content = @"http://www.youtube.com/user/Scobleizer#p/u/1/1p3vcRhsYGo,http://youtu.be/NLqAF9hrVbY,http://www.youtube.com/watch?v=NLqAF9hrVbY,http://facebook.com,http://www.youtube.com/watch?v=cAcqdjLCN7s"; 

方法

 -(NSArray *)extractVideos:(NSString *)content { NSString *extractRegex = @"(?<=v(=|/))([-a-zA-Z0-9_]+)|(?<=youtu.be/)([-a-zA-Z0-9_]+)" NSMutableArray *extractedContent = [[NSMutableArray alloc] init]; if ([content hasPrefix:@"http://"] || [content hasPrefix:@"https://"]) { NSURL *extractURL = [NSURL URLWithString:content]; if ([extractURL.host rangeOfString:@"youtu"].location != NSNotFound) { NSRegularExpression *extractRegex = [NSRegularExpression regularExpressionWithPattern:extractRegex options:NSRegularExpressionCaseInsensitive error:nil]; NSArray *extractResults = [extractRegex matchesInString:content options:0 range:NSMakeRange(0, content.length)]; for (NSTextCheckingResult *match in extractResults) { [extractedContent addObject:[content substringWithRange:match.range]]; } } } return extractedContent; } 

产量

 ( NLqAF9hrVbY, QLqAF9eeVbY, cAcqdjLCN7s ) 

感谢正则expression式的@Alex

合并你的一些答案,我会说这是最好的答案:

 + (NSString *)extractYoutubeID:(NSString *)youtubeURL { NSError *error = NULL; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(?<=v(=|/))([-a-zA-Z0-9_]+)|(?<=youtu.be/)([-a-zA-Z0-9_]+)" options:NSRegularExpressionCaseInsensitive error:&error]; NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:youtubeURL options:NSMatchingReportProgress range:NSMakeRange(0, [youtubeURL length])]; if(rangeOfFirstMatch.location != NSNotFound) { NSString *substringForFirstMatch = [youtubeURL substringWithRange:rangeOfFirstMatch]; return substringForFirstMatch; } return nil; } 

Swift 2版本为@Alex答案

 func getYoutubeVideoId(youtubeLink:String) -> String?{ var youtubeId:String? = nil let pattern: String = "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)" do { let regex = try NSRegularExpression(pattern: pattern, options: .CaseInsensitive) if let regexMatch = regex.firstMatchInString(youtubeLink, options: NSMatchingOptions(rawValue: 0), range: NSRange(location: 0, length: youtubeLink.characters.count)) { youtubeId = (youtubeLink as NSString).substringWithRange(regexMatch.range) } } catch let error as NSError{ print("Error while extracting youtube id \(error.debugDescription)") } return youtubeId } 

更新Swift 4:

 static func extractYoutubeVideoId(from url: String) -> String? { let pattern = "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)" guard let range = url.range(of: pattern, options: .regularExpression) else { return nil } return String(url[range]) } 

老答案:
@ Alex的Swift 3有点快捷的方式回答w / o使用NSString:
我们可以强制尝试正则expression式,因为我们知道它是有效的。

 static func extractYoutubeVideoId(from url: String) -> String? { let pattern = "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)" let regex = try! NSRegularExpression(pattern: pattern, options: [.caseInsensitive]) let range = NSRange(location: 0, length: url.utf16.count) guard let firstMatch = regex.firstMatch(in: url, options: .init(rawValue: 0), range: range) else { return nil } let start = String.UTF16Index(firstMatch.range.location) let end = String.UTF16Index(firstMatch.range.location + firstMatch.range.length) return String(url.utf16[start..<end]) } 

或者,如果你还想要NSString:

 static func extractYoutubeVideoId(from url: String) -> String? { let pattern = "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)" let regex = try! NSRegularExpression(pattern: pattern, options: [.caseInsensitive]) let range = NSRange(location: 0, length: (url as NSString).length) guard let firstMatch = regex.firstMatch(in: url, options: .init(rawValue: 0), range: range) else { return nil } return (url as NSString).substring(with: firstMatch.range) } 

这是使用@ jt_ik的正则expression式的快速版本:

 func extractYoutubeID(youtubeURL: String) -> String { var error: NSError? let pattern: String = "(?<=v(=|/))([-a-zA-Z0-9_]+)|(?<=youtu.be/)([-a-zA-Z0-9_]+)" let regex = NSRegularExpression(pattern: pattern, options: .CaseInsensitive, error: &error)! if error == nil { if let regexMatch = regex.firstMatchInString(youtubeURL, options: nil, range: NSRange(location: 0, length: youtubeURL.utf16Count)) { return (youtubeURL as NSString).substringWithRange(regexMatch.range) } // Handle no match here return "" } else { // Handle error here println(error?.userInfo) return "" } } 

Swift 3版本为@Alex答案

 func extractYoutubeIdFromLink(link: String) -> String? { let pattern = "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)" guard let regExp = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive) else { return nil } let nsLink = link as NSString let options = NSRegularExpression.MatchingOptions(rawValue: 0) let range = NSRange(location: 0,length: nsLink.length) let matches = regExp.matches(in: link as String, options:options, range:range) if let firstMatch = matches.first { debugPrint(firstMatch) return nsLink.substring(with: firstMatch.range) } return nil } 

我自己想清楚了

 NSArray *videoURLSplit = [videoURL componentsSeparatedByString:@"v="]; NSString *videoID = [[videoURLSplit objectAtIndex:1] substringToIndex:11]; NSLog(@"%@",videoID); 

非常简单…所有的videourl都包含v = VIDEO_ID我只是将url分隔成一个数组,然后把v =后面的第一个11位数字,因为url中可能有更多的http GET信息…

感谢您的帮助!