我基本上有一個Youtube網址作爲NSString,但我需要提取顯示在URL中的視頻ID。我發現很多關於如何在php或其他基於網絡的編程語言中做到這一點的教程,但沒有在目標c ...Youtube視頻ID從URL - 目標C
我基本上尋找一種方法,要求NSString url作爲參數和作爲另一個nsstring返回視頻ID ...
任何人都知道如何做到這一點或任何教程呢?
我基本上有一個Youtube網址作爲NSString,但我需要提取顯示在URL中的視頻ID。我發現很多關於如何在php或其他基於網絡的編程語言中做到這一點的教程,但沒有在目標c ...Youtube視頻ID從URL - 目標C
我基本上尋找一種方法,要求NSString url作爲參數和作爲另一個nsstring返回視頻ID ...
任何人都知道如何做到這一點或任何教程呢?
所以YouTube的URL類似於:
http://www.youtube.com/watch?v=oHg5SJYRHA0
你感興趣的是視頻ID是在年底(oHg5SJYRHA0
)部分....雖然它不一定是在年底,因爲YouTube網址可以在查詢字符串中包含其他參數。
最好的辦法是使用正則表達式和Foundation的NSRegularExpression
類。我認爲這種方法在你找到的其他語言教程中使用 - 請注意,正則表達式的內容在包含它們的任何語言或工具包中幾乎相同,所以在這些教程中找到的任何正則表達式都應該可以工作爲你。 (我建議不要採用打破v=
的方法,並採用正確的11個字符,因爲這容易導致各種失敗模式的正則表達式更強大。)
要找到視頻ID,您可能需要一個正則表達式像v=([^&]+)
。 v=
讓我們訪問查詢網址的右側部分(如果我們得到類似watch?fmt=22&v=oHg5SJYRHA0
的東西)。圓括號使捕獲組因此我們只能提取視頻ID而不提取其他我們用來找到它的匹配字符,在括號內我們尋找一個或多個字符序列,這不是一個&符號 - 這個請確保我們獲得了v=whatever
字段中的所有內容,並且如果您獲得了像watch?v=oHg5SJYRHA0&rel=0
這樣的URL,則不會有任何字段。
無論您使用這個還是另一個正則表達式,您可能會使用捕獲組。 (如果沒有的話,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];
}
不是regexes有點矯枉過正**和**不夠靈活,在同一時間?我發現這一切*只是可怕的。* – 2013-07-22 22:13:02
不適合我,你應該刪除?從你的正則表達式 – 2017-03-16 19:11:25
你可能看到的教程只是關於如何使用正則表達式的說明,這也是你想要在這種情況下使用的。
您需要使用的可可類是NSRegularExpression。
您的實際正則表達式字符串將取決於您期待的網址格式,因爲它看起來像youtube有幾個。一般功能看起來像:
+ (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;
}
你應該使用'nil'而不是'NULL'。 http://stackoverflow.com/a/1564419/11976 – 2012-07-16 17:54:31
更新,因爲我同意,但總的來說這沒關係。 – Dima 2012-07-16 18:03:06
我想通了我自己......
NSArray *videoURLSplit = [videoURL componentsSeparatedByString:@"v="];
NSString *videoID = [[videoURLSplit objectAtIndex:1] substringToIndex:11];
NSLog(@"%@",videoID);
很簡單......所有視頻網址包含V = VIDEO_ID我剛剛分離的網址爲數組,然後採取前v =後面的第一個11位數字,因爲可能有更多http GET信息在url中...
感謝您的幫助!
請小心,因爲這實際上並非如此。還有其他幾種格式的視頻可以進來,例如'http://youtu.be/###########'和'youtube.com/v/######### ##'。 – Dima 2012-07-16 18:08:00
當youtube開始使用超過11個字符的ID時會發生什麼情況。你也需要考慮這一點。 – eternalmatt 2012-07-16 18:11:40
@迪瑪謝謝你,但我加載了http://www.youtube.com/watch?nomobile=1在web視圖中的這個特定的地址,我只允許用戶搜索視頻並點擊它們,所以幾乎每次網址應該是... http://www.youtube.com/v=VIDEO_ID – 2012-07-16 18:12:12
對不起 - 我沒有足夠的代表處,以註釋添加到所選擇的答案。
花了很多時間試圖爲正則表達式找到正確的語法後,我遇到了這個幫助我的東西。希望它可以幫助別人!
NSString *regexString = @"(?<=v(=|/))([-a-zA-Z0-9_]+)|(?<=youtu.be/)([-a-zA-Z0-9_]+)";
摘自here。這適用於以下網址格式:
這對我來說,只是提及你可以訪問範圍編號0來得到它: NSRange videoIDRange = [match rangeAtIndex:0]; NSString * videoID = [message substringWithRange:videoIDRange]; – 2013-02-22 11:56:07
Dis da da cooolest answer evaaa!如果它與dat dima homie的答案相結合 – GangstaGraham 2013-06-19 04:16:40
這裏是我的解決方案,將r從StackOveFlow引用。 (Youtube I.D parsing for new URL formats)
我做了一些修改。
///這是.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
你甚至不需要正則表達式。以下作品在URL中的視頻ID的長度和位置,無論:
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);
比正則表達式好得多。仍然不會像[youtube-dl]那樣考慮[this](http://stackoverflow.com/questions/11509164/youtube-video-id-from-url-objective-c/17798344#comment15209148_11509927),但是哦。 ;) – Ryan 2013-07-23 19:46:21
@minitech我的原則:如果我們開發buggy黑客,那麼我們至少應該是優雅的:P謝謝。 (順便說一句:如果我正確理解了你的觀點,我的錯誤很容易通過用'?#'字符集中的字符分隔URL來解決......) – 2013-07-23 19:50:58
+1:這隻適用於我... – 2014-06-02 08:09:01
- (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;
}
我使用的最高投票的答案寫一個更好的,更嚴格的正則表達式。
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];
這裏是正則表達式它涵蓋這些情況
目標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
}
斯威夫特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
}
This works對我來說,謝謝! – 2015-03-06 16:35:26
@ZianChen,歡迎您 – Alex 2015-04-21 14:21:36
爲什麼不讓這些方法變爲靜態?不必使用自己的... – 2016-09-21 15:09:03
基於這樣的回答:PHP Regex to get youtube video ID?
我適應一個正則表達式的C/objc/C++字符串,這裏最重要的是,正則表達式沒有得到來自Facebook的視頻或其他服務。 iOS的正則表達式是基於: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;
}
匹配:
不匹配:
下面是一個使用@ jt_ik的正則表達式迅速版本:
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 ""
}
}
它不適用於包含「vi」的鏈接。 – 2016-10-07 05:30:05
這裏有很多很好的答案,但我認爲它可能會b e有益於從字符串解析多個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
)
感謝@Alex的正則表達式
謝謝你的詳細答案,但我一直無法弄清楚什麼是YT_ID_EXTRACT_REGEX – Rimon 2015-06-28 07:29:30
沒關係,搞清楚了。對於其他人也想知道,只需添加 '#define YT_ID_EXTRACT_REGEX @「(?<= v(= | /))([ - a-zA-Z0-9 _] +)|(?<= youtu.be/) ([ - a-zA-Z0-9 _] +]「'而不是這行'NSString * extractRegex = @」(?<= v(= | /))([ - a-zA- Z0-9 _] +)|(?<= youtu.be/)([-a-zA-Z0-9_]+)「' – Rimon 2015-06-28 07:33:25
@RimonRagaie抱歉代碼中存在錯誤,現在我改變了它,但有點太晚了。希望答案的其餘部分有所幫助。 – 2015-06-28 17:05:59
合併一些你的答案,我d說這是bes噸答案:
+ (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;
}
夫特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
}
夫特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
}
更新夫特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])
}
老答案:的
有點更快的方式@亞歷克斯的斯威夫特3回答W/O使用的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.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)
}
有您正在使用一個不同的格式?你能舉個例子嗎? – Stavash 2012-07-16 17:12:38
@stavash不只是基本的Youtube桌面網址... – 2012-07-16 17:40:42
你可以提供一個示例URL和你已經嘗試過的東西。 – eternalmatt 2012-07-16 17:53:45