来自 URL 的 Youtube 视频 ID - Swift3
Posted
技术标签:
【中文标题】来自 URL 的 Youtube 视频 ID - Swift3【英文标题】:Youtube Video Id from URL - Swift3 【发布时间】:2017-05-01 04:04:37 【问题描述】:基本上我有一个 Youtube URL 作为字符串,我想从该 URL 中提取视频 ID。我在目标 c 中找到了一些代码,如下所示:
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];
当我将此代码转换为 swift3 时:
var error: Error? = nil
var regex = try! NSRegularExpression(pattern: "?.*v=([^&]+)", options: .caseInsensitive)
var match = regex!.firstMatch(in: youtubeURL, options: [], range: NSRange(location: 0, length: youtubeURL.length))!
if match
var videoIDRange = match.rangeAt(1)
var substringForFirstMatch = (youtubeURL as NSString).substring(with: videoIDRange)
给出错误:
致命错误:“试试!”表达式意外引发错误:Error Domain=NSCocoaErrorDomain Code=2048 “值“?.*v=([^&]+)”无效。”
任何人都可以帮助我解决这个错误或任何人解释如何从 Swift 3 中的 url 获取视频 ID。
提前致谢
【问题讨论】:
【参考方案1】:更安全版本(无需强制解包!
):
extension String
var youtubeID: String?
let pattern = "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)"
let regex = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive)
let range = NSRange(location: 0, length: count)
guard let result = regex?.firstMatch(in: self, range: range) else
return nil
return (self as NSString).substring(with: result.range)
例子:
"https://www.youtube.com/watch?v=C0DPdy98e4c".youtubeID // "C0DPdy98e4c"
"https://youtube.com/watch?v=C0DPdy98e4c".youtubeID // "C0DPdy98e4c"
"www.youtube.com/watch?v=C0DPdy98e4c".youtubeID // "C0DPdy98e4c"
"youtube.com/watch?v=C0DPdy98e4c".youtubeID // "C0DPdy98e4c"
"https://youtu.be/C0DPdy98e4c".youtubeID // "C0DPdy98e4c"
"youtu.be/C0DPdy98e4c".youtubeID // "C0DPdy98e4c"
致谢:Usman Nisar's answer
【讨论】:
非常好。对我来说工作得很好。 这似乎可行,但传递https://www.twitch.tv/directory/all/tags/6ea6bca4-4712-4ab9-a906-e3336a9d8039
似乎返回 directory
作为 videoID。【参考方案2】:
我有另一种使用 URLComponents 的方法。然后,您只需从 url 中选择“v”参数(如果存在)。
func getYoutubeId(youtubeUrl: String) -> String?
return URLComponents(string: youtubeUrl)?.queryItems?.first(where: $0.name == "v" )?.value
然后像这样传入一个 Youtube url:
print (getYoutubeId(youtubeUrl: "https://www.youtube.com/watch?v=Y7ojcTR78qE&spfreload=9"))
【讨论】:
单行return URLComponents(string: youtubeUrl)?.queryItems?.first(where: $0.name == "v" )?.value
你会如何处理短网址? (例如:“youtu.be/sWx8TtRBOfk")
@IslamQ。这会起作用: URLComponents(string: "youtu.be/sWx8TtRBOfk")?.path.replacingOccurrences(of: "/", with: "")
@IslamQ.,查看this 回答您的问题。【参考方案3】:
斯威夫特 5
var youtubeURLs = [
"http://www.youtube.com/watch?v=-wtIMTCHWuI",
"http://www.youtube.com/v/-wtIMTCHWuI?version=3&autohide=1",
"http://youtu.be/-wtIMTCHWuI",
"http://www.youtube.com/oembed?url=http%3A//www.youtube.com/watch?v%3D-wtIMTCHWuI&format=json",
"https://youtu.be/uJ2PZaO1N5E",
"https://www.youtube.com/embed/M7lc1UVf-VE",
"http://www.youtube.com/attribution_link?a=JdfC0C9V6ZI&u=%2Fwatch%3Fv%3DEhxJLojIE_o%26feature%3Dshare",
"https://www.youtube.com/attribution_link?a=8g8kPrPIi-ecwIsS&u=/watch%3Fv%3DyZv2daTWRZU%26feature%3Dem-uploademail"
]
func getVideoID(from urlString: String) -> String?
guard let url = urlString.removingPercentEncoding else return nil
do
let regex = try NSRegularExpression.init(pattern: "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)", options: .caseInsensitive)
let range = NSRange(location: 0, length: url.count)
if let matchRange = regex.firstMatch(in: url, options: .reportCompletion, range: range)?.range
let matchLength = (matchRange.lowerBound + matchRange.length) - 1
if range.contains(matchRange.lowerBound) &&
range.contains(matchLength)
let start = url.index(url.startIndex, offsetBy: matchRange.lowerBound)
let end = url.index(url.startIndex, offsetBy: matchLength)
return String(url[start...end])
catch
print(error.localizedDescription)
return nil
for url in youtubeURLs
print("Video id: \(getVideoID(from: url) ?? "NA") for url: \(url)")
结果:
Video id: -wtIMTCHWuI for url: http://www.youtube.com/watch?v=-wtIMTCHWuI
Video id: -wtIMTCHWuI for url: http://www.youtube.com/v/-wtIMTCHWuI?version=3&autohide=1
Video id: -wtIMTCHWuI for url: http://youtu.be/-wtIMTCHWuI
Video id: -wtIMTCHWuI for url: http://www.youtube.com/oembed?url=http%3A//www.youtube.com/watch?v%3D-wtIMTCHWuI&format=json
Video id: uJ2PZaO1N5E for url: https://youtu.be/uJ2PZaO1N5E
Video id: M7lc1UVf-VE for url: https://www.youtube.com/embed/M7lc1UVf-VE
Video id: EhxJLojIE_o for url: http://www.youtube.com/attribution_link?a=JdfC0C9V6ZI&u=%2Fwatch%3Fv%3DEhxJLojIE_o%26feature%3Dshare
Video id: yZv2daTWRZU for url: https://www.youtube.com/attribution_link?a=8g8kPrPIi-ecwIsS&u=/watch%3Fv%3DyZv2daTWRZU%26feature%3Dem-uploademail
【讨论】:
【参考方案4】:这是从任何 youtube url 中提取 youtube 视频 ID 的代码: (斯威夫特)
func extractYoutubeId(fromLink link: String) -> String
let regexString: String = "((?<=(v|V)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=embed/))([\\w-]++)"
let regExp = try? NSRegularExpression(pattern: regexString, options: .caseInsensitive)
let array: [Any] = (regExp?.matches(in: link, options: [], range: NSRange(location: 0, length: (link.characters.count ))))!
if array.count > 0
let result: NSTextCheckingResult? = array.first as? NSTextCheckingResult
return (link as NSString).substring(with: (result?.range)!)
return ""
【讨论】:
这似乎有效,但传递https://www.twitch.tv/directory/all/tags/6ea6bca4-4712-4ab9-a906-e3336a9d8039
似乎返回 directory
作为 videoID。
extractYoutubeId 仅适用于 youtube 视频网址。【参考方案5】:
使用优雅的flatMap
的Swift 4 版本:
func extractYouTubeId(from url: String) -> String?
let typePattern = "(?:(?:\\.be\\/|embed\\/|v\\/|\\?v=|\\&v=|\\/videos\\/)|(?:[\\w+]+#\\w\\/\\w(?:\\/[\\w]+)?\\/\\w\\/))([\\w-_]+)"
let regex = try? NSRegularExpression(pattern: typePattern, options: .caseInsensitive)
return regex
.flatMap $0.firstMatch(in: url, range: NSMakeRange(0, url.count))
.flatMap Range($0.range(at: 1), in: url)
.map String(url[$0])
此方法使用检测大多数可能的 YouTube URL 格式(.be/*
、/embed/
、/v/
- 您可以找到完整列表 here)的正则表达式。
【讨论】:
【参考方案6】:您的第一个问题是您没有在表达中转义?
。 ?
是保留字符,如果您想在表达式中使用它,则必须使用 \
转义,并且由于 \
也用于转义 "
字符,因此您必须使用双反斜杠转义 ?
,例如 @ 987654327@。所以根据以上信息,下面的代码正确提取了videoId
let youtubeURL = "https://www.youtube.com/watch?v=uH8o-JTHJdM"
let regex = try! NSRegularExpression(pattern: "\\?.*v=([^&]+)", options: .caseInsensitive)
let match = regex.firstMatch(in: youtubeURL, options: [], range: NSRange(location: 0, length: youtubeURL.characters.count))
if let videoIDRange = match?.rangeAt(1)
let substringForFirstMatch = (youtubeURL as NSString).substring(with: videoIDRange)
else
//NO video URL
【讨论】:
【参考方案7】:Youtube url 的一些示例:
let urls: [String] = [
"www.youtube-nocookie.com/embed/up_lNV-yoK4?rel=0",
"http://www.youtube.com/watch?v=peFZbP64dsU",
"http://www.youtube.com/watch?v=cKZDdG9FTKY&feature=channel",
"http://youtube.com/v/dQw4w9WgXcQ?feature=youtube_gdata_player",
"http://youtube.com/?v=dQw4w9WgXcQ&feature=youtube_gdata_player",
"http://youtu.be/6dwqZw0j_jY",
"http://youtu.be/dQw4w9WgXcQ?feature=youtube_gdata_playe",
"http://youtube.com/vi/dQw4w9WgXcQ?feature=youtube_gdata_player",
"http://youtube.com/?vi=dQw4w9WgXcQ&feature=youtube_gdata_player",
"http://youtube.com/watch?vi=dQw4w9WgXcQ&feature=youtube_gdata_player",
"http://www.youtube.com/user/Scobleizer#p/u/1/1p3vcRhsYGo?rel=0",
"http://www.youtube.com/user/SilkRoadTheatre#p/a/u/2/6dwqZw0j_jY",
"1p3vcRhsY02"
]
我的扩展基于Islam Q. 解决方案:
private extension String
var youtubeID: String?
let pattern = "((?<=(v|V|vi)/)|(?<=be/)|(?<=(\\?|\\&)v=)|(?<=vi=)|(?<=/u/[0-9_]/)|(?<=embed/))([\\w-]++)"
let regex = try? NSRegularExpression(pattern: pattern, options: .caseInsensitive)
let range = NSRange(location: 0, length: count)
guard let result = regex?.firstMatch(in: self, range: range) else
return count == 11 ? self : nil
let id = (self as NSString).substring(with: result.range)
return id.count == 11 ? id : nil
【讨论】:
【参考方案8】:要从 Youtube Url 获取视频 ID,请使用代码 # Swift4 :
var videoId = ""
if youtubeLink.lowercased().contains("youtu.be")
linkString = youtubeLink
if let range = linkString.range(of: "be/")
videoId = youtubeLink[range.upperBound...].trimmingCharacters(in: .whitespaces)
else if youtubeLink.lowercased().contains("youtube.com")
linkString = youtubeLink
if let range = linkString.range(of: "?v=")
videoId = youtubeLink[range.upperBound...].trimmingCharacters(in: .whitespaces)
希望能有所帮助! :)
【讨论】:
以上是关于来自 URL 的 Youtube 视频 ID - Swift3的主要内容,如果未能解决你的问题,请参考以下文章
C# 正则表达式通过 url 从 youtube 和 vimeo 获取视频 ID