CAFECA-IO / KnowledgeManagement

Creating, Sharing, Using and Managing the knowledge and information of CAFECA
https://mermer.com.tw/knowledge-management
MIT License
0 stars 1 forks source link

(小範圍實驗) 任務 4: 詳細議案資料抓取及影片下載實作 #173

Closed TzuHanLiang closed 3 months ago

TzuHanLiang commented 3 months ago

實作目標:

使用爬蟲抓取詳細議案資料並下載影片文件。

方法:

修改爬蟲腳本,使其能夠進入每個議案的詳細頁面並根據抓取到的下載鏈接下載影片文件。 使用 Requests 庫進行影片文件的下載。 抓取並保存每個議案的詳細資料及影片。

驗證:

執行爬蟲腳本,確認影片文件可以成功下載並保存到本地或數據庫。

TzuHanLiang commented 3 months ago

爬蟲下載視頻教程

用於說明如何使用 Python 和 Selenium 從一個具有反爬蟲機制的網站上下載視頻。這個教程將透過幾個步驟引導操作者完成從獲取視頻源地址到使用 ffmpeg 下載視頻的整個過程。

第一步:瞭解如何一般使用 Python 下載網頁上的視頻

通常情況下,可以使用 Python 的 requests 庫直接從網頁上的 <video> 標籤中獲得視頻源地址並下載視頻。然而,如果遇到具有動態加載技術或反爬蟲機制的網站,這種方法可能不適用。我們這裡要下載的立法院會議相關資訊的網站就有反爬蟲機制。

第二步:使用 Selenium 獲取視頻源地址

因為一般方法無法直接獲取到視頻源,所以我們需要使用 Selenium 來模擬瀏覽器操作,從而繞過反爬蟲機制。Selenium 可以模擬真實用戶的行為,如點擊和滾動,以觸發 JavaScript 的執行並獲取動態加載的內容。

第三步:處理 Blob URL 的問題

透過使用 Chrome 的開發者工具直接看我們要下載視頻 (https://ivod.ly.gov.tw/Play/Clip/300K/153887) 的html 結構發現,該視頻元素的源地址是一個 Blob URL ,要了解 blob URL 本身並不是視頻文件的直接來源,而是一個臨時的 URL,它指向在瀏覽器中存儲的一個對象。這意味著我們無法直接從 blob URL 下載視頻,而需要透過其他方法來獲取實際的視頻數據。這通常需要分析網頁上的 JavaScript 代碼或使用網路請求監聽工具來找到視頻的實際請求地址。

第四步:獲取 HLS 格式的 m3u8 視頻源地址

一樣透過 Chrome 的開發者工具來分析視頻是如何被加載的,在source -> ivod.ly.gov.tw -> script -> play.js:

canAutoplay.video().then(function(o) {
        var cap = o.result === true;
        _player = new Clappr.Player({
          source: _filelink,
          parentId: '#fPlayer',
          width: _rtspW,
          height: _rtspH,
          autoPlay: cap,
          plugins: [
            PlaybackRatePlugin
          ],
          playbackRateConfig: {
            defaultValue: 1,
            options: [
                //{value: 0.25, label: '0.25x'},
                {value: 0.5, label: '0.5x'},
                {value: 0.75, label: '0.75x'},
                {value: 1, label: '1x'},
                //{value: 1.25, label: '1.25x'},
                {value: 1.5, label: '1.5x'},
                //{value: 1.75, label: '1.75x'},
                {value: 2, label: '2x'},
            ],
            // rateSuffix: 'x',
          },
        });

        settingPlayer();

      });

發現視頻播放器的源地址是通過 _filelink 變量設置的。如果我們想使用 Python 和 Selenium 捕獲實際的視頻源(_filelink 變量),我們需要進一步模擬瀏覽器操作以解析和取得視頻文件的 URL。可以使用 Selenium 執行 JavaScript 代碼來獲取這個變量的值:

filelink = driver.execute_script("return _filelink;")
print("視頻源地址:", filelink)

視頻源地址: https://ivod-lyvod.cdn.hinet.net/vod_1/_definst_/mp4:300KClips/4f10fa8b3f7cd819a8acd1da281beef20fec08313b105ec06824d40b1933d675aa6d9d5be5f1c9245ea18f28b6918d91.mp4/playlist.m3u8

第五步:使用 ffmpeg 下載視頻

直接觀察視頻源地址,可以發現這是一個 HLS (HTTP Live Streaming) 格式的播放列表文件(m3u8)。使用 ffmpeg 可以有效地下載這種格式的視頻。確保你已經在各個操作系統上安裝了 ffmpeg

第六步:安裝ffmpeg

確認並安裝 FFmpeg

首先,在終端機中執行以下命令來檢查是否已安裝:

ffmpeg -version

如果這個命令返回了版本信息,這意味著 ffmpeg 已經安裝。如果沒有,則需要安裝它。根據使用者的操作系統,安裝方法會有所不同:

指定 FFmpeg 的完整路徑

如果 ffmpeg 已經安裝但不在你的系統路徑中,你可以在 Python 腳本中指定 ffmpeg 可執行文件的完整路徑。修改你的 Python 腳本中調用 ffmpeg 的部分,如下所示:

ffmpeg_path = '/path/to/your/ffmpeg'  # 替換成你的 ffmpeg 安裝路徑
command = [
    ffmpeg_path,
    '-i', m3u8_url,
    '-c', 'copy',
    '-bsf:a', 'aac_adtstoasc',
    output_filename
]

確保將 /path/to/your/ffmpeg 替換為實際的路徑。

第七步:Python 腳本範例

以下是整個流程的 Python 腳本示例:

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service
import time
import subprocess

# 設定瀏覽器驅動和選項
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--no-sandbox')
options.add_argument('start-maximized')
options.add_argument('disable-infobars')
options.add_argument('--disable-extensions')

# 初始化 Selenium 驅動
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)

# 設定輸出文件名
output_file = "downloaded

Uploading downloaded_video.mp4…

_video.mp4"

# 下載視頻
def download_video(m3u8_url, output_filename):
    command = [
        'ffmpeg',
        '-i', m3u8_url,
        '-c', 'copy',
        '-bsf:a', 'aac_adtstoasc',
        output_filename
    ]

    try:
        subprocess.run(command, check=True)
        print(f"視頻已成功下載至:{output_filename}")
    except subprocess.CalledProcessError as e:
        print(f"錯誤:{e}")

# 獲取視頻源地址
def get_video_source():
    # 訪問網頁
    driver.get('https://ivod.ly.gov.tw/Play/Clip/300K/153887')
    # 給網頁加載留出時間
    time.sleep(10)  # 等待 JavaScript 加載
    # 執行 JavaScript 代碼來獲取 _filelink 變量的值
    filelink = driver.execute_script("return _filelink;")
    print("視頻源地址:", filelink)
    driver.quit()
    return filelink

# 頻源地址
m3u8_url = get_video_source()

if m3u8_url:
    # 下載視頻
    download_video(m3u8_url, output_file)

# 關閉瀏覽器
driver.quit()
TzuHanLiang commented 3 months ago

https://github.com/CAFECA-IO/KnowledgeManagement/assets/17249354/1fad4a3d-6782-4503-bfc0-f7729da5cf88

TzuHanLiang commented 3 months ago

took 5hrs done