日历

2019年十一月
« 10月    
 123
45678910
11121314151617
18192021222324
252627282930  

最近评论

    linux企业应用

    爬取网页视频,解析m3u8文件

    m3u8是苹果公司推出一种视频播放标准,是m3u的一种,不过 编码方式是utf-8,是一种文件检索格式,将视频切割成一小段一小段的ts格式的视频文件,然后存在服务器中(现在为了减少I/o访问次数,一般存在服务器的内存中),通过m3u8解析出来路径,然后去请求。m3u8网址的获得可以参照网上的方法,这里先不说了。
    比如网址:
    HD%u9ad8%u6e05%24https%3A%2F%2Fyouku.com-l-youku.com%2F20190207%2F20335_d1f19bfb%2Findex.m3u8
    是经过加密的,规则:
    所有以 %xx 十六进制形式编码的字符都用 ASCII 字符集中等价的字符代替。
    以 %uxxxx 格式(Unicode 字符)编码的字符用十六进制编码 xxxx 的 Unicode 字符代替。
    比如上面链接的“HD%u9ad8%u6e05%24”代表“HD高清$”,不是链接的一部分,因此我们忽略即可。
    下面的代码是将上面提到的m3u8地址进行2次key的替换,代码是在windows10 + visualstadio2017环境下运行的。
    也可以参照这个网址:https://blog.csdn.net/qq_39797956/article/details/88076404

    Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click

    Dim strBefore As String
    ‘出现unescape的位置
    Dim intUnescape As Int32
    ‘出现“.m3u8”的位置
    Dim intM3U8 As Int32
    ‘找到http出现的位置
    Dim intHttp As Int32
    ‘第一层key的url链接
    Dim m3u8_url_1 As String
    ‘第二层key的url链接
    Dim m3u8_url_2 As String
    Dim logFile As String
    logFile = IO.Path.Combine(IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName), “下载”) & DateTime.Now.ToString(“yyyy-MM-dd_HH-mm”) & “.txt”

    ‘若文件夹不存在则新建文件夹
    If Not IO.Directory.Exists(IO.Path.GetDirectoryName(logFile)) Then
    ‘新建文件夹
    IO.Directory.CreateDirectory(IO.Path.GetDirectoryName(logFile))
    End If

    Dim now As String = DateTime.Now.ToString(“yyyy-MM-dd_HH-mm-ss”)
    Dim init As String = “LOG : ” & DateTime.Now.ToString(“yyyy/MM/dd”) & vbCrLf _
    & “Save Path : ” & IO.Path.GetDirectoryName(logFile) & vbCrLf _
    & “Task Start: ” & DateTime.Now.ToString(“yyyy/MM/dd HH:mm:ss”) & vbCrLf

    init += vbCrLf & vbCrLf
    IO.File.WriteAllText(logFile, init, System.Text.Encoding.UTF8)
    ‘以在最后追加方式打开文件
    Dim fs As New IO.StreamWriter(logFile, True)

    ‘HD%u9ad8%u6e05%24https%3A%2F%2Fyouku.com-l-youku.com%2F20190207%2F20335_d1f19bfb%2Findex.m3u8
    strBefore = Me.txtBefore.Text
    intUnescape = strBefore.IndexOf(“unescape”)
    If intUnescape < 0 Then intUnescape = 0
    intM3U8 = strBefore.IndexOf(“.m3u8”)
    intHttp = strBefore.IndexOf(“http”, intUnescape, intM3U8)
    ‘未解码的m3u8链接
    m3u8_url_1 = strBefore.Substring(intHttp, intM3U8 – intHttp + 5)
    fs.Write(“未解码的m3u8链接是:”)
    fs.WriteLine(m3u8_url_1)

    ‘将2个%之间的16进制的Unicode进行解码
    ‘percentIndex %第一次出现的位置
    Dim percentStart As Int32
    ‘%第二次出现的位置
    Dim percentEnd As Int32
    While True
    ‘percentIndex %第一次出现的位置
    percentStart = m3u8_url_1.IndexOf(“%”)
    ‘%第二次出现的位置
    percentEnd = m3u8_url_1.IndexOf(“%”, percentStart + 1)

    If percentStart <> -1 Then
    Dim arr As Array = m3u8_url_1.Split(“%”)
    m3u8_url_1 = m3u8_url_1.Replace(m3u8_url_1.Substring(percentStart, percentEnd – percentStart), hexToAscii(arr(1)))
    Else
    Exit While
    End If

    End While

    ‘得到的网址是https://youku.com-l-youku.com/20190207/20335_d1f19bfb/index.m3u8
    Me.txtResult.Text = m3u8_url_1
    fs.Write(“第一层KEY的连接 是:”)
    fs.WriteLine(m3u8_url_1)

    Dim wb As WebClient = New WebClient
    ‘获取网页内容
    Dim pageData As Object = wb.DownloadData(m3u8_url_1)

    ‘将网页内容转换成字符串 “#EXTM3U” & vbLf & “#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=800000,RESOLUTION=1080×608” & vbLf & “1000k/hls/index.m3u8”
    ‘Dim pageStr As String = System.Text.Encoding.UTF8.GetString(pageData)
    Dim pageStr As String = System.Text.Encoding.Default.GetString(pageData)
    fs.WriteLine(“对应的网页内容 是:”)
    fs.WriteLine(pageStr)
    ‘字符串种有换行符,使用换行符进行分割字符串,最后一段字符串是 arr2(arr2.Length – 1)
    Dim arr2 As Array = Split(pageStr, vbLf)
    Dim firstKey As String = “/” & arr2(arr2.Length – 1)
    ‘将https://youku.com-l-youku.com/20190207/20335_d1f19bfb/index.m3u8中的index.m3u8替换为 “1000k/hls/index.m3u8”

    intM3U8 = m3u8_url_1.IndexOf(“.m3u8”)
    Dim lastSalsh As Int32
    lastSalsh = m3u8_url_1.LastIndexOf(“/”)
    ‘获取第二层KEY的连接地址
    m3u8_url_2 = m3u8_url_1.Replace(m3u8_url_1.Substring(lastSalsh, m3u8_url_1.Length – lastSalsh), firstKey)
    Me.txt1.Text = m3u8_url_2
    fs.Write(vbLf & “第二层KEY的连接 是:”)
    fs.WriteLine(m3u8_url_2)

    Dim str As String
    Dim j As Int32 = 0
    Dim intRealLength As Int32 = 0
    Dim list As New List(Of String)
    ‘下载第二层key的m3u8文件
    pageData = wb.DownloadData(m3u8_url_2)
    pageStr = System.Text.Encoding.Default.GetString(pageData)
    fs.WriteLine(“对应的网页内容是 :”)
    fs.WriteLine(pageStr)
    ‘获取第二层KEY的连接地址是一个记录TS的文件,内容大体如下:
    ‘#EXTINF:4.700000,
    ‘284e2012ca2000000.ts
    ‘#EXTINF:3.566667,
    ‘284e2012ca2000001.ts
    ‘下面需要将https://youku.com-l-youku.com/20190207/20335_d1f19bfb/1000k/hls/index.m3u8中的index.m3u8替换成各个”284e2012ca2000001.ts”
    Dim arr3 As Array = Split(pageStr, vbLf)
    ‘根据上面可以得知第二层key的m3u8文件中ts的记录接近文件行数的一半
    ‘如果使用list,下面的数组可以不使用
    Dim tsArr(Int(arr3.Length / 2)) As String
    Dim secondKey As String
    Dim tsUrlPath As String

    intM3U8 = m3u8_url_2.IndexOf(“.m3u8”)
    lastSalsh = m3u8_url_1.LastIndexOf(“/”)

    For i = 0 To arr3.Length – 1
    str = arr3(i)
    If str.IndexOf(“ts”) <> -1 Then
    tsArr(intRealLength) = str
    intRealLength = intRealLength + 1
    secondKey = “/” & str
    ‘获取ts文件的url
    tsUrlPath = m3u8_url_2.Replace(m3u8_url_2.Substring(lastSalsh, m3u8_url_2.Length – lastSalsh), secondKey)
    ‘将ts文件的url连接添加到list中,方便后面下载
    list.Add(tsUrlPath)
    fs.WriteLine(tsUrlPath)
    End If
    Next

    fs.Close()

    MsgBox(“结束了”, vbOK, “haha”)

    Dim fileExists As Boolean
    fileExists = My.Computer.FileSystem.FileExists(logFile)
    If fileExists Then
    ‘My.Computer.FileSystem.DeleteFile(filePath)
    End If

    End Sub

    Function hexToAscii(ByVal str As String) As String

    Dim d As Int32
    ‘HD%u9ad8%u6e05%24
    ‘如果是u9ad8,字母u表示是unicode,字母u不用转换,只转换后面的4个16进制数就行了
    If (str.Length = 5 Or str.Length = 7) And str(0) = “u” Then
    ‘截取u后面的4个16进制数据
    str = str.Substring(1, 4)
    str = “&H” + str
    Return ChrW(str)
    ‘Return Chr(str) ‘用这个函数不行
    ElseIf str.Length = 2 Then
    ‘转成十进制
    d = System.Convert.ToInt32(str, 16)
    ‘转成ASCII码
    Return Chr(d)

    Else
    Return vbNullString
    End If

    End Function

    下面是代码运行出来的日志,节选一部分。

    LOG : 2019/11/07
    Save Path : D:\软件开发\视频下载助手\WindowsApplication1\bin\Debug
    Task Start: 2019/11/07 15:44:18

    未解码的m3u8链接是:https%3A%2F%2Fyouku.com-l-youku.com%2F20190207%2F20335_d1f19bfb%2Findex.m3u8
    第一层KEY的连接 是:https://youku.com-l-youku.com/20190207/20335_d1f19bfb/index.m3u8
    对应的网页内容 是:
    #EXTM3U
    #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=800000,RESOLUTION=1080×608
    1000k/hls/index.m3u8

    第二层KEY的连接 是:https://youku.com-l-youku.com/20190207/20335_d1f19bfb/1000k/hls/index.m3u8
    对应的网页内容是 :
    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-TARGETDURATION:7
    #EXT-X-MEDIA-SEQUENCE:0
    #EXTINF:4.700000,
    284e2012ca2000000.ts
    #EXTINF:3.566667,
    284e2012ca2000001.ts
    #EXTINF:5.433333,
    284e2012ca2000002.ts
    #EXTINF:5.000000,
    284e2012ca2000003.ts
    #EXTINF:2.366667,
    284e2012ca2000004.ts
    #EXTINF:4.433333,
    284e2012ca2000005.ts
    #EXTINF:2.566667,
    284e2012ca2000006.ts
    #EXTINF:4.400000,
    284e2012ca2000007.ts
    #EXTINF:4.733333,
    284e2012ca2000008.ts
    #EXTINF:3.366667,
    284e2012ca2000009.ts

    评论已关闭。