從cctv網頁版flash提取視頻鏈接
cctv網頁版到現在還是主要用flash播放視頻,而chrome瀏覽器用flash比較麻煩,所以我花了點時間研究一下cctv的flash是怎么下載視頻的。首先,要知道flash下載的數據,用chrome和firefox的開發人員面板的Network頁的XHR或者Media標簽是看不到的,因為flash是自己獨立地處理數據和播放視頻的。
用IE10或以上瀏覽器,打開這個鏈接http://tv.cctv.com/2018/04/01/VIDEYI7D9VFtnbOjIeIP4Pcn180401.shtml,然后打開開發人員工具,點開網絡標簽,點開始捕獲,再刷新頁面。
首先根據類型是application/x-shockwave-flash,看到flash的引用是http://player.cntv.cn/standard/cntvplayerQC20181126.swf?v=0.171.5.8.9.6.3.5.2,這個鏈接不是根據視頻地址變化而變化的。
繼續往下面找,看到很多video/MP2T的標簽,這個是ts流媒體文件的類型,所以在以上兩行記錄之間的其他行里繼續找由Flash發起的請求,就看到了http://vdn.apps.cntv.cn/api/getHttpVideoInfo.do?,而且接收大小有10.6KB,跟我們平常見到index.m3u8文件大小差不多。
就打開看看吧。雙擊那一行,選擇“響應正文”標簽,一看,應該是個json文件,有很多mp4的鏈接。
全選這段文本,復制到json在線格式化的網站。我們看到有mp4鏈接,有m3u8鏈接。
別着急,在開發面板繼續找,找到了application/x-mpegURL類型,是m3u8文件。可以看出,1200應該指碼率。見圖片1的紅框
我們在json格式化頁面直接搜索以下文本:“http://hls.cntv.lxdns.com/asp/hls/1200/0303000a/3/default/dff2ea4f955f4e5283cd61d7e5e6dc82/1200.m3u8”,是找不到對應結果的,但是有一個hls_url是"http://hls.cntv.lxdns.com/asp/hls/main/0303000a/3/default/dff2ea4f955f4e5283cd61d7e5e6dc82/main.m3u8?maxbr=2048",與前者比較像,我們把后者用瀏覽器打開,下載的文件里就有對應碼率1200的鏈接。我們以后要下載的話,就按瀏覽器播放視頻用的1200碼率下載就好了。
在開發面板雙擊上述1200.m3u8的一行,看“響應正文”,是一個標准的m3u8文件,其中每個文件名N.ts是要接在“http://hls.cntv.lxdns.com/asp/hls/1200/0303000a/3/default/dff2ea4f955f4e5283cd61d7e5e6dc82/”后面的。m3u8文件主要有兩種描述路徑的格式,因為這里是較簡單的一種,所以就不提及較復雜的那一種了。
所以現在重點回到了getHttpVideoInfo.do參數的分析。完整的url是"http://vdn.apps.cntv.cn/api/getHttpVideoInfo.do?pid=dff2ea4f955f4e5283cd61d7e5e6dc82&tz=-8&from=000news&idl=32&idlr=32&modifyed=false&url=http://tv.cctv.com/2018/04/01/VIDEYI7D9VFtnbOjIeIP4Pcn180401.shtml&tsp=1598349127&vn=1540&vc=3204F3DC432A4C0DE9C770BE00B8ED93&uid=C2BD12DEC005F94C4858A92ED76D622D",這么長,哪些參數是可以舍棄的呢?到現在大家都應該對"dff2ea4f955f4e5283cd61d7e5e6dc82"這個重復出現的文本比較有印象了。於是我們大膽求證,用瀏覽器訪問http://vdn.apps.cntv.cn/api/getHttpVideoInfo.do?pid=dff2ea4f955f4e5283cd61d7e5e6dc82,就能獲取到了帶hls_url的json。(謝謝cctv的程序員)當然,要讀懂json還是要有一點編程基礎的。
然后在網頁正文里搜索“dff2ea4f955f4e5283cd61d7e5e6dc82",能搜索到兩個結果。這樣我們只需要用正則表達式匹配而獲取guid就可以了。
以下用Ruby代碼示例。
在網頁<head>標簽看到用utf-8編碼。我們先把網頁的裸html用腳本下載下來,可以搜索到var guid這一個語句。所以不用另外下載其他js腳本。
require 'open-uri' require 'json' Header = { 'User-agent' =>'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36', } def download(link) return URI.open(link, Header).read end # 以后者為示例,運行命令: ruby cctv.rb cctv鏈接 link1 = (ARGV[0] || 'http://tv.cctv.com/2018/04/01/VIDEYI7D9VFtnbOjIeIP4Pcn180401.shtml') html = download(link1) # 獲取視頻guid test = /var\sguid\s=\s"(.*?)"/.match(html) raise "找不到guid" if (test == nil) guid = test[1] # 獲取m3u8列表 json = download("http://vdn.apps.cntv.cn/api/getHttpVideoInfo.do?pid=#{guid}") hls_url = JSON.load(json)['hls_url'] # 注意某些特殊字符可能導致json解析失敗 hls_url.gsub!('main', '1200') # 替換碼率為'1200' hls_url = hls_url[0, hls_url.index('?')] # 去除 '?maxbr=2048' m3u8 = download(hls_url) File.write("#{guid}.m3u8", m3u8) # 開始下載ts文件 lines = m3u8.split(/\r|\n/) lines.select{|x| x[0] != '#'}.each do |line| fn = line link = hls_url.sub('1200.m3u8', fn) bin = download(link) File.open(fn, 'wb') do |fio| fio.print bin end print '.' sleep(rand(2)) # 限制下載的頻率 end puts '', "生成命令: ffmpeg -i #{guid}.m3u8 -c:v copy -c:a copy result.mp4" # 重要說明,用ffmpeg直接處理m3u8文件,仍有可能導致合並后的視頻文件出現錯亂、卡屏現象,這個問題我不知道是什么回事。