快速解析get_video_info(YouTube信息数据)

时间:2019-03-01 22:26:41

标签: swift parsing youtube

要获得直接指向YouTube视频的链接,我请求获取get_video_info文件,在该文件中,该链接为该文件,但我必须对其进行解析,我找到了通过PHP对其进行解析的解决方案,但我想直接从中进行解析我的应用程序

我是这样从我的代码中获取数据的:

        let youtubeContentID = "sZz7tiToK1U"
    if let infoURL = URL(string:"https://www.youtube.com/get_video_info?video_id=\(youtubeContentID)") {
        let request = URLRequest(url: infoURL)
        let session = URLSession(configuration: .default)
        let task = session.dataTask(with: request, completionHandler: { (data, response, error) -> Void in
            if let error = error {
                print(error)
            } else if let data = data, let result = NSString(data: data, encoding: String.Encoding.utf8.rawValue) {

               print(result)

            }
        })
        task.resume()
    }
}

我得到的数据带有许多这样的Ascii符号:

c = WEB&vss_host = s.youtube.com&innertube_api_version = v1&xhr_apiary_host = youtubei.youtube.com&apiary_host_firstparty =&status = ok&t = 1&enabled_engage_types = 3%2C6%2C4%2C5%2C17%2C1_ssl = 1 %%&video %253D%2522vp9%2522%26eotf%3Dbt709%26projection_type%3D1%26lmt%3D1550114115045036%26bitrate%3D16962786%26size%3D3840x2160%26index%3D221-1771%26quality_label%3D2160p%26xtags%3D%26F% --- sn-nuj-wxqek.googlevideo.com%252Fvideoplayback%253Fexpire%253D1551500605%2526usequic%253Dno%2526gir%253Dyes%2526mime%253Dvideo%25252Fwebm%2526requiressl%253Dyes%2526keepalive%253Dyes%2526f%2526fir%25D %253Dyoutube%2526aitags%253D133%25252C134%25252C135%25252C136%25252C137%25252C160%25252C242%25252C243%25252C244%25252C247%25252C248%25252C271%25252C278%25252C313%25252C394%25252C395%25252C396%25252C397%2526signature%253D9C28A5C103FA95701CD3655795DDB7F2C0954828.55534AC9C7BEE5D644C3A34C2CD4A4EEC9E2FD38%2526lmt%253D1550114115045036 %2526ip%253D129.208.30.232%2526key%253Dyt6%2526c%253DWEB%2526ei%253D3bB5XKeFFNWd1wbBpqjgAg%2526txp%253D5531432%2526id%253Do-AIOVogCB8KFe32o_VgxSx-LqaEjNBZxiZ1jl81VTXZhF%2526sparams%253Daitags%25252Cclen%25252Cdur%25252Cei%25252Cgir%25252Cid%25252Cinitcwndbps%25252Cip %25252Cipbits%25252Citag%25252Ckeepalive%25252%t2522Cmime%25252Cmm%25252Cmn%25252Cms%25252Cmv%25252Cpl%25252Csquiressl%25252Csource%25252Cusequic%25252Cexpire%2526initcwndbps%253D%26g25%25m25%25D%25D%25D%25D%25D%25D%25D%26D25%25D%25D%25D%25D%26D%25D%25D%26D%25D%26D%25D%25D %2526dur%253D428.933%2526pl%253D19%2526ipbits%253D0%2526mm%253D31%25252C29%2526mn%253Dsn-nuj-wxqek%25252Csn-hgn7yn7l%26clen%3D547103152%26init%3D0-220%26itag%3 %26fps%3D30%2Ctype%3Dvideo%252Fwebm%253B%2Bcodecs%253D%2522vp9%2522%26eotf%3Dbt709%26projection_type%3D1%26lmt%3D1550113771564979%26bitrate%3D6318874%26size%3D2560x1440%263% %26xtags%3D%26url%3Dhttps%253A%252F%252Fr2 --- sn-nuj-wxqek.googlevideo.com %252Fvideoplayback%253Fexpire%253D1551500605%2526usequic%253Dno%2526gir%253Dyes%2526mime%253Dvideo%25252Fwebm%2526requiressl%253Dyes%2526keepalive%253Dyes%2526fvip%253D2%2526clen%253D155%25%C%253D%25D25%25%25%25%25%25%25% %25252C137%25252C160%25252C242%25252C243%25252C244%25252C247%25252C248%25252C271%25252C278%25252C313%25252C394%25252C395%25252C396%25252C397%2526signature%253D4D7BF761EE4A6DFD048DE3D48550FCE80E61B7D0.D625BCC9645471ABA478F79C197B2208F354E15F%2526lmt%253D1550113771564979%2526ip%253D129.208.30.232%2526key%253Dyt6 %2526c%253DWEB%2526ei%253D3bB5XKeFFNWd1wbBpqjgAg%2526txp%253D5531432%2526id%253Do-AIOVogCB8KFe32o_VgxSx- .... ext

1 个答案:

答案 0 :(得分:0)

我发现代码可以处理此YouTube请求,它是在2015年创建的,因此无法在新的Swift上运行,因此我对其进行了编辑以在Swift 4上运行,只需将此代码复制到新的Swift文件中,然后调用函数h264videosWithYoutubeID(youtubeID:您的TouTube ID),您将获得正确的网址:

import UIKit

public extension NSURL {

func dictionaryForQueryString() -> [String: AnyObject]? {
    if let query = self.query {
        return query.dictionaryFromQueryStringComponents()
    }


    let result = absoluteString?.components(separatedBy: "?")
    if result!.count > 1 {
        return result!.last?.dictionaryFromQueryStringComponents()
    }
    return nil
}
}

public extension NSString {

func stringByDecodingURLFormat() -> String {
    let result = self.replacingOccurrences(of: "+", with: " ")
    return result.removingPercentEncoding!
}

func dictionaryFromQueryStringComponents() -> [String: AnyObject] {
    var parameters = [String: AnyObject]()
    for keyValue in components(separatedBy: "&") {
        let keyValueArray = keyValue.components(separatedBy: "=")
        if keyValueArray.count < 2 {
            continue
        }
        let key = keyValueArray[0].stringByDecodingURLFormat()
        let value = keyValueArray[1].stringByDecodingURLFormat()
        parameters[key] = value as AnyObject
    }
    return parameters
}
}

public class YoutubeUrlReciver: NSObject {
static let infoURL = "http://www.youtube.com/get_video_info?video_id="
static var userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2)  AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.79 Safari/537.4"

public static func youtubeIDFromYoutubeURL(youtubeURL: NSURL) -> String? {
    if let
        youtubeHost = youtubeURL.host,
        let youtubePathComponents = youtubeURL.pathComponents {
        let youtubeAbsoluteString = youtubeURL.absoluteString
        if youtubeHost == "youtu.be" as String? {
            return youtubePathComponents[1]
        } else if youtubeAbsoluteString?.range(of: "www.youtube.com/embed") != nil {
            return youtubePathComponents[2]
        } else if youtubeHost == "youtube.googleapis.com" ||
            youtubeURL.pathComponents!.first == "www.youtube.com" as String? {
            return youtubePathComponents[2]
        } else if let
            queryString = youtubeURL.dictionaryForQueryString(),
            let searchParam = queryString["v"] as? String {
            return searchParam
        }
    }
    return nil
}

public static func h264videosWithYoutubeID(youtubeID: String) -> [String: AnyObject]? {
    let urlString = String(format: "%@%@", infoURL, youtubeID) as String
    let url = NSURL(string: urlString)!
    let request = NSMutableURLRequest(url: url as URL)
    request.timeoutInterval = 5.0
    request.setValue(userAgent, forHTTPHeaderField: "User-Agent")
    request.httpMethod = "GET"
    var responseString = NSString()
    let session = URLSession(configuration: URLSessionConfiguration.default)
    let group = DispatchGroup()
    group.enter()
    session.dataTask(with: request as URLRequest, completionHandler: { (data, response, _) -> Void in
        if let data = data as NSData? {
            responseString = NSString(data: data as Data, encoding: String.Encoding.utf8.rawValue)!
        }
        group.leave()
    }).resume()
    group.wait()
    let parts = responseString.dictionaryFromQueryStringComponents()
    if parts.count > 0 {
        var videoTitle: String = ""
        var streamImage: String = ""
        if let title = parts["title"] as? String {
            videoTitle = title
        }
        if let image = parts["iurl"] as? String {
            streamImage = image
        }
        if let fmtStreamMap = parts["url_encoded_fmt_stream_map"] as? String {
            // Live Stream
            if let _: AnyObject = parts["live_playback"]{
                if let hlsvp = parts["hlsvp"] as? String {
                    return [
                        "url": "\(hlsvp)" as AnyObject,
                        "title": "\(videoTitle)" as AnyObject,
                        "image": "\(streamImage)" as AnyObject,
                        "isStream": true as AnyObject
                    ]
                }
            } else {
                let fmtStreamMapArray = fmtStreamMap.components(separatedBy: ",")
                for videoEncodedString in fmtStreamMapArray {
                    var videoComponents = videoEncodedString.dictionaryFromQueryStringComponents()
                    videoComponents["title"] = videoTitle as AnyObject
                    videoComponents["isStream"] = false as AnyObject
                    return videoComponents as [String: AnyObject]
                }
            }
        }
    }
    return nil
}
public static func h264videosWithYoutubeURL(youtubeURL: NSURL,completion: ((
    _ videoInfo: [String: AnyObject]?, _ error: NSError?) -> Void)?) {
    DispatchQueue.global().async {
        if let youtubeID = self.youtubeIDFromYoutubeURL(youtubeURL: youtubeURL), let videoInformation = self.h264videosWithYoutubeID(youtubeID: youtubeID) {
            DispatchQueue.main.async {
                completion?(videoInformation, nil)
            }
        }else{
            DispatchQueue.main.async {
                completion?(nil, NSError(domain: "com.player.youtube.backgroundqueue", code: 1001, userInfo: ["error": "Invalid YouTube URL"]))
            }
        }
    }
}
}