利用selenium和ffmpeg爬取m3u8 ts視頻《進擊的巨人》


需求

想看下動漫《進擊的巨人》,發現到處被和諧,找不到資源,但是在一個視頻網站找到了在線播放,https://www.55cc.cc/dongman/17890/player-2-1.html,然而不能下載下來(喜歡的東西我一般都看很多遍)


找了下,網站沒發現robots協議,加上我用的和真人瀏覽差不多的效率來爬取,應該ok的


於是想爬蟲爬取下,但是看源代碼發現視頻是m3u8的ts流,而且是雙層m3u8的,並且m3u8地址還隱藏在js代碼中,於是有2種處理方法:

    1.直接requests源碼,把js代碼的部分逐字解析,找出m3u8地址。

    2.直接調用瀏覽器渲染,將渲染后的網頁代碼拿到,就可以看到iframe標簽中src地址了

image

獲取到首層m3u8地址后就簡單了,直接requests請求到第二層m3u8地址,這就是真實地址了,下載后可以看到是很多的ts流小文件,於是有2種處理方法了:

    1.直接逐個獲取ts地址,然而寫到本地磁盤的同一個文件,最后轉碼到mp4(ts格式太占空間)

    2.直接調用ffmpeg,能根據m3u8地址下載ts流並合並為一個文件且同步轉碼為mp4

image

上述均采用第二種方法,於是寫出個簡單的該網站的視頻爬蟲

源代碼

from selenium import webdriver
from bs4 import BeautifulSoup
import re
import requests
import os

if __name__ == '__main__':
    urls = ['https://www.55cc.cc/dongman/17890/player-2-'+str(n)+'.html' for n in range(1,14,)]
    for url in urls:
        browser = webdriver.Firefox()
        browser.get(url)
        htmldata=browser.page_source
        browser.close()
        soup = BeautifulSoup(htmldata,'html.parser')
        m3u8 = re.findall(r'(https://\S+)',soup.select('iframe[name="iFrame_play"]')[0].get('src')[1::1])[0]
        r = requests.get(m3u8).text
        m3u8_rel = m3u8.replace('index.m3u8','')+re.split('\n',r)[-1]
        ffmpeg = '"C:\\soft\\ffmpeg\\bin\\ffmpeg.exe"'
        output = "f:\\進擊的巨人\\第三季\\"+soup.title.string.replace('集在線觀看_動漫_五五影院','').replace(' ','')+".mp4"
        cmd = ffmpeg+" -i "+m3u8_rel+" -vcodec copy -acodec copy "+output
        os.system(cmd)

執行結果

image

總結

每次都要啟動瀏覽器,有點兒膈應人,后面還是改成headless瀏覽器即無界面瀏覽器(無頭瀏覽器)來渲染

12集都要順序執行下載,有點兒慢,后續改成並發執行,一次性同步並發執行12條cmd命令來下載,即多進程方式

優化后

把共12集由原來的串行爬取改為並行爬取,增加效率

image


from selenium import webdriver
from bs4 import BeautifulSoup
import re
import requests
import os

if __name__ == '__main__':
    urls = ['https://www.55cc.cc/dongman/17890/player-2-'+str(n)+'.html' for n in range(1,14,)]
    cmds = []
    command = ''
    for url in urls:
        browser = webdriver.Firefox()
        browser.get(url)
        htmldata=browser.page_source
        browser.close()
        soup = BeautifulSoup(htmldata,'html.parser')
        m3u8 = re.findall(r'(https://\S+)',soup.select('iframe[name="iFrame_play"]')[0].get('src')[1::1])[0]
        r = requests.get(m3u8).text
        m3u8_rel = m3u8.replace('index.m3u8','')+re.split('\n',r)[-1]        
        output = "f:\\進擊的巨人\\第三季\\"+soup.title.string.replace('集在線觀看_動漫_五五影院','').replace(' ','')+".mp4"
        cmd ="ffmpeg -i "+m3u8_rel+" -vcodec copy -acodec copy "+output
        cmds.append(cmd)
        #os.system(cmd)
    for i in cmds:
        command+='start cmd /c "'+i+'"&'
    os.system(command[:-1:])

知識點

嘗試過you-get來爬,不過好像不好用,也許是我菜


瀏覽器動態渲染 webkit;

python中動態網頁爬取方式:

  dryscape 作者已經不再維護了,並且作者推薦的庫僅是python2,已涼涼;

  selenium 可以,但是缺點是必須要打開瀏覽器;

  Phantom JS,無頭瀏覽器 ,無界面瀏覽器, headless ,借助之可以模擬webkit執行,但是Phantom JS停止更新了且selenium不支持它了,也涼涼;

  chrome headless 或者firefox headless可以替代Phantom JS(建議使用,畢竟官方出品,比開源項目動不動有大坑,比如phantomjs坑1000+,或者沒人維護等等毛病)

  puppeteer也可以替代Phantom JS ,Pyppeteer是其python實現庫但是有問題不成熟,不建議用

  tampermonkey油猴插件,自動交互,用js注入,可以對網頁各種花式操作,比如給網頁注入個下載按鈕啥的(油猴可以自動交互但不好監控網絡請求,chrome extension 可以監控請求但沒法監控響應,cdp 全部都可以做但是不好操作 dom)

  cheerio 針對DOM的

  appium是針對手機端的,一般由於手機端性能問題,反爬策略較少,對於pc端實在沒法子的,可以從手機端操作


selenium被識別的程度越來越高,阿里的網站瞬間能識別,但是識別了並不會告訴你,而是返回給你和真人不一樣的結果


一般小型網站,直接webkit渲染即可,最簡單通用的方式是用 headless 的瀏覽器,完全模擬人工操作,增大 IP 池,降低訪問評率。缺點是效率低,資源成本高

大型網站,是有價值去仔細分析的,一般都是前后分離,傳輸數據都是json,找到接口requests即可,但是對於加密的,直接請求又可能不行


無頭瀏覽器的資源占用太多,能不用就不用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM