Youtube Video ID From URL - Objective C

后端 未结 16 781
失恋的感觉
失恋的感觉 2020-12-22 23:23

I basically have a Youtube url as an NSString, but I need to extract the video id that is displayed in the url. I found many tutorials on how to do this in php or and other

相关标签:
16条回答
  • 2020-12-22 23:34

    Update 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])
    }
    

    Old answer:
    A bit swifter way of @Alex's Swift 3 answer w/o the use of NSString:
    We can force try the regex, because we know it is valid.

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

    Or, if you still want 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)
    }
    
    0 讨论(0)
  • 2020-12-22 23:37

    I used the highest voted answer to write a better, more restrictive regex.

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

    and then you can get the ID

    NSTextCheckingResult *match = [regex firstMatchInString:url
                                                    options:0
                                                      range:NSMakeRange(0, [url length])];
    NSRange videoIDRange = [match rangeAtIndex:1];
    NSString *youTubeID = [url substringWithRange:videoIDRange];
    
    0 讨论(0)
  • 2020-12-22 23:38

    Merging some of your answers, I'd say this is the best answer:

    + (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;
    }
    
    0 讨论(0)
  • 2020-12-22 23:44

    So a YouTube URL looks something like:

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

    The video ID you're interested in is is the part at the end (oHg5SJYRHA0).... though it's not necessarily at the end, as YouTube URLs can contain other parameters in the query string.

    Your best bet is probably to use a regular expression and Foundation's NSRegularExpression class. I'd presume this approach is used in the other-language tutorials you've found -- note that the content of regular expressions is pretty much the same in any language or toolkit which includes them, so any regex found in those tutorials should work for you. (I'd advise against your approach of breaking on v= and taking exactly 11 characters, as this is prone to various modes of failure to which a regex is more robust.)

    To find the video ID you might want a regex like v=([^&]+). The v= gets us to the right part of the query URL (in case we get something like watch?fmt=22&v=oHg5SJYRHA0). The parentheses make a capture group so we can extract only the video ID and not the other matched characters we used to find it, and inside the parentheses we look for a sequence of one or more characters which is not an ampersand -- this makes sure we get everything in the v=whatever field, and no fields after it if you get a URL like watch?v=oHg5SJYRHA0&rel=0.

    Whether you use this or another regex, it's likely that you'll be using capture groups. (If not, rangeOfFirstMatchInString:options:range: is just about all you need, as seen in Dima's answer.) You can get at the contents of capture groups (as NSTextCheckingResult objects) using firstMatchInString:options:range: or similar methods:

    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];
    }
    
    0 讨论(0)
  • 2020-12-22 23:48

    Here is the swift version using @jt_ik's 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 ""
        }
    }
    
    0 讨论(0)
  • 2020-12-22 23:49

    Swift 3 version for @Alex answer

    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
    }
    
    0 讨论(0)
提交回复
热议问题