Подтвердить что ты не робот

Youtube ID видео с URL - цель C

У меня в основном есть Youtube-url как NSString, но мне нужно извлечь идентификатор видео, отображаемый в URL-адресе. Я нашел много учебников о том, как это сделать на php или других языках программирования на основе Интернета, но ни один из них в объективном c...

Я в основном ищу метод, который запрашивает URL-адрес NSString в качестве параметра и возвращает идентификатор видео в качестве другой nsstring...

Кто-нибудь знает, как это сделать или какие-либо учебники там?

4b9b3361

Ответ 1

Таким образом, URL-адрес YouTube выглядит примерно так:

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

Идентификатор видео, который вас интересует, - это часть в конце (oHg5SJYRHA0).... хотя это не обязательно в конце, так как URL-адреса YouTube могут содержать другие параметры в строке запроса.

Лучше всего, вероятно, использовать регулярное выражение и Foundation NSRegularExpression. Я предполагаю, что этот подход используется в других учебниках, которые вы нашли, - обратите внимание, что содержание регулярных выражений практически одинаково на любом языке или наборе инструментов, который включает их, поэтому любое регулярное выражение, найденное в этих учебниках, должно работать для тебя. (Я бы посоветовал вам не подходить к v= и принимать ровно 11 символов, поскольку это подвержено различным режимам отказа, к которым регулярное выражение более надежное.)

Чтобы найти идентификатор видео, вам может понадобиться регулярное выражение, например v=([^&]+). v= возвращает нас в нужную часть URL-адреса запроса (если мы получим что-то вроде watch?fmt=22&v=oHg5SJYRHA0). Скобки создают группу захвата, поэтому мы можем извлекать только идентификатор видео, а не другие совпадающие символы, которые мы использовали для его поиска, а внутри круглых скобок мы ищем последовательность из одного или нескольких символов, которые не являются амперсандами - это гарантирует мы получаем все в поле v=whatever и после него не будут полей, если вы получите URL-адрес, например watch?v=oHg5SJYRHA0&rel=0.

Если вы используете это или другое регулярное выражение, вероятно, вы будете использовать группы захвата. (Если нет, rangeOfFirstMatchInString:options:range: - это все, что вам нужно, как видно из ответа Димы.) Вы можете получить содержимое групп захвата (как NSTextCheckingResult), используя firstMatchInString:options:range: или аналогичные методы:

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];
}

Ответ 2

Здесь 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
}

Ответ 3

Извините - у меня недостаточно комментариев, чтобы добавить комментарий к выбранному ответу.

Проведя возраст, пытаясь найти правильный синтаксис для регулярного выражения, я столкнулся с этим, что помогло мне. Надеюсь, это может помочь кому-то еще!

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

Взято из здесь. Это работает для следующих форматов URL:

Ответ 4

Уроки, которые вы, вероятно, видите, - это просто инструкции по использованию регулярных выражений, которые также вы хотите использовать в этом случае.

Класс Cocoa, который вам нужно использовать, это NSRegularExpression.

Ваша фактическая строка регулярного выражения будет зависеть от формата, который вы ожидаете от URL-адреса, поскольку он похож на то, что у 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;
}

Ответ 5

Вам даже не нужны регулярные выражения. Следующие действия выполняются независимо от длины идентификатора видео и его позиции в 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);

Ответ 6

На основе этого ответа: PHP Regex получит идентификатор видео youtube?

Я адаптировал регулярное выражение для строки c/objc/С++, важная часть здесь заключается в том, что регулярное выражение не получает видеоролики из facebook или других сервисов. iOS regex основан на: 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;
}

Матчи:

Не соответствует:

Ответ 7

- (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;
}

Ответ 8

Я использовал самый высокий голосовой ответ для написания лучшего, более ограничивающего регулярного выражения.

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

а затем вы можете получить идентификатор

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

Ответ 9

Вот мое решение, которое ссылается на StackOveFlow. (Youtube I.D синтаксический анализ для новых форматов 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

Ответ 10

Здесь есть много хороших ответов, но я подумал, что некоторым может быть полезно проанализировать несколько строк 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 для регулярного выражения

Ответ 11

Объединив некоторые ваши ответы, я бы сказал, что это лучший ответ:

+ (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;
}

Ответ 12

версия 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
}

Ответ 13

Обновить 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 ответа без использования 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)
}

Ответ 14

Вот быстрая версия с использованием @jt_ik regex:

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

Ответ 15

версия 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
}

Ответ 16

Я понял это сам...

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

Очень просто... Все видеоролики содержат v = VIDEO_ID Я просто отделил URL-адрес в массив, а затем взял первые 11 цифр того, что после v =, поскольку в URL-адресе может быть больше информации HTTP GET...

Спасибо за помощь, хотя!