Python 下載網絡mp4視頻資源


最近着迷化學, 特別是古代的冶煉技術,感嘆古人的聰明。

春秋時期的煉鐵方法是塊煉鐵,即在較低的冶煉溫度下,將鐵礦石固態還原獲得海綿鐵,再經鍛打成的鐵塊。冶煉塊煉鐵,一般采用地爐、平地築爐和豎爐3種。鐵礦石在溫度較高的煉鐵爐中高溫還原並滲碳,得到含碳達到3~4%的液態生鐵。戰國初期,我國已掌握了脫碳、熱處理技術方法,發明了韌性鑄鐵。

在中國,鋼鐵的總產量在唐代年產已達到1200噸,宋朝為4700噸,明朝最多達到4萬噸。在13世紀,中國是世界上最大的鐵的生產國和消費國,直到17世紀仍保持着這一領先地位。從漢代到明朝,中國人不僅在數量上處於領先地位,而且還擁有世界上最先進的鋼鐵冶煉技術。
鑄鐵脫碳鋼 將含碳3~4%的低硅鑄鐵器在氧化氣氛中加熱,在適當條件下,特別是厚度不大的情況下,可以避免石墨的形成。早期煉鐵溫度較低,含硅量低,石墨析出較慢,有利於脫碳,使制造韌性鑄鐵的工藝發展成為鑄鐵脫碳成鋼的方法。這種鋼稱為鑄鐵脫碳鋼,這類鋼板可加工成的鐵鏃、環首刀。

炒鋼 向熔化的生鐵鼓風,同時進行攪拌促使生鐵中的碳氧化。用這種方法可將生鐵制成熟鐵,再經過滲碳鍛打成鋼。也可有控制地把生鐵含碳量炒到需要的程度,再鍛制成鋼制品。這種鋼中含有的硅酸鐵夾雜物成分比較一致而數量較少。炒鋼技術始於西漢末年,到東漢已相當普及。江蘇出土新莽殘劍,徐州出土建初二年(77)五十煉鋼劍,山東臨沂蒼山出土的永初六年(112)三十煉鋼刀等所用的原料都屬於這一類型。曹操(155~220)在《內誡令》提到“百煉利器”,孫權(182~252)有以“百煉”命名的寶刀。初步可以認為百煉鋼是用炒鋼反復疊打變形,細化晶粒和夾雜物而成的,甚至可以用不同含碳鋼材復合組成。煉數大致相當於反復折疊鍛打后最后的層數。煉數增多,表明加工量加大,晶粒和夾雜進一步細化,質量提高。炒鋼技術的發明是煉鋼史上的一次革命。

來源:http://wenku.baidu.com/view/7c9bd28d84868762caaed5ed.html

 

哎! 就在查找古人是如何冶煉金屬、鑄造錢幣、分離金屬元素時,找到了這個大連理工大學講的“化學與社會”公開課。講的很有調理,讓讀者很容易理解,越看越覺的這個公開課是一個經典課程,想收藏頁面怕以后鏈接會失效,所以決定把這個經典的公開課下載下來。

那么問題來了,下載網頁嵌入的flash 視頻,不是容易的事。試了網上好多視頻下載插件(DownLoad Helper 、 VDownLoad嗅探器、flv視頻下載、ImovieBox)也么有分析出網頁的鏈接視頻。好吧,我使用F12 調試網頁工具查看網絡響應,發現有type=video/mp4,然后另存為就可以了,但問題是課程有近100個,不可能一個個打開鏈接,查看網頁Network點擊視頻讓其加載出type=video/mp4 類型,再另存為。這樣太麻煩了。開動腦筋想用程序直接把視頻下載鏈接分析出來,然后保存在本地。

 

1. 獲取鏈接地址

查看:http://ptr.chaoxing.com/course/2533204.html 源碼,課程的list寫在了clas=“p20” ul里面的li標簽列表中
通過PyQuery可以獲取所有課程的視頻播放地址

 

            d = self.pq('http://ptr.chaoxing.com/course/2533204.html')
            DomTree = d('.p20 ul li a')
            for my_div in DomTree.items():
                URL = 'http://ptr.chaoxing.com' + my_div.attr('href')  # 課時detail URL
                l = my_div.find('.l').html()  # 課時章節NO
                r = my_div.find('.r').html()  # 課時Name
                self.LessonList.append({'url': URL, "name": l + r})

 

2. 分析下載地址

 打開一個課程視頻播放時,都會XHR請求加載一個鏈接,該鏈接的內容是:

 

然而我們發現,每一個視頻地址頁面都會請求一個類似於這樣的地址:http://ptr.chaoxing.com/ananas/status/************?k=&_dc=1476770383911
該地址返回一個帶有視頻mp4路徑的Json格式字符串。其中filename為當前視頻課程的名稱,http為(standard)標准清晰視頻 sd.mp4, httphd為(high)高清視頻 hd.mp4
進一步的分析我們發現,在該地址請求之前有一個類型為Document的html加載出頁面內容區域的html flash播放器

 

當這個播放器加載完成通過all-classes.js?v=20141027:1的Ajax請求http://ptr.chaoxing.com/ananas/status/************?k=&_dc=***。查看網頁源代碼,查找status后的這一串字符串發現這個字符串應該是視頻播放的objectID

 

在iframe標簽的data屬性里面。試着復制一個視頻的objectID去模擬請求http://ptr.chaoxing.com/ananas/status/************發現居然成功了!不知道此方法是否也使用其他flash視頻下載。
這樣下載課程視頻的思路就出來了:在第一步獲取下載鏈接,通過每一個視頻頁面源碼中的objectID去請求http://ptr.chaoxing.com/ananas/status/************ 獲取下載地址。然后下載視頻教程。so easy!

 

3. 下載視頻

通過上一步分析地址,已經知道獲取flash視頻objectID並Ajax 請求http://ptr.chaoxing.com/ananas/status/************ 就能獲取視頻地址。這一步我們就下載視頻。
通過PyQuery 獲取視頻頁面中的objectID

    def getVideo(self, url):
        '''
        獲取視頻
        '''
        d = self.pq(url)
        DomTree = d("iframe")
        jsonData = DomTree.attr('data')
        objectid = json.loads(jsonData)['objectid']  # 獲取下載資源視頻的對象
        downloadUrl = self.pq('http://ptr.chaoxing.com/ananas/status/' + objectid)  # 獲取下載資源的URL
        jsonData = json.loads(downloadUrl.html())['httphd']  # 在這里,我們要下載的是高清視頻
        return jsonData    

在視頻下載中遇到了些小問題,可參考:https://www.zhihu.com/question/41132103

完整代碼:

 

# -*- coding: UTF8 -*-
from pyquery import PyQuery as pq
import sys, os
import json
import requests
from contextlib import closing


class SaveVideo():
    LessonList = []

    def __init__(self):
        pass

    # 獲取課時的列表
    def getLesson(self):
        try:
            # 該網站請求時必須帶上User-Agent
            d = self.pq('http://ptr.chaoxing.com/course/2533204.html')
            DomTree = d('.p20 ul li a')
            for my_div in DomTree.items():
                URL = 'http://ptr.chaoxing.com' + my_div.attr('href')  # 課時detail URL
                l = my_div.find('.l').html()  # 課時章節NO
                r = my_div.find('.r').html()  # 課時Name
                self.LessonList.append({'url': URL, "name": l + r})
        except Exception as e:
            print(e)

        if (len(self.LessonList) > 0):
            if not os.path.exists('./Video'):
                os.makedirs('./Video')

            for lesson in self.LessonList:
                video = self.getVideo(lesson['url'])
                if video:
                    self.downloadVideo(video, lesson['name'])

            print('完成下載!!!')

    def getVideo(self, url):
        '''
        獲取視頻
        '''
        d = self.pq(url)
        DomTree = d("iframe")
        jsonData = DomTree.attr('data')
        video=''
        try:
            objectid = json.loads(jsonData)['objectid']  # 獲取下載資源視頻的對象
            downloadUrl = self.pq('http://ptr.chaoxing.com/ananas/status/' + objectid)  # 獲取下載資源的URL
            video = json.loads(downloadUrl.html())['httphd']  # 在這里,我們要下載的是高清視頻
        except:
            pass
        return video

    def pq(self, url, headers=None):
        '''
        將PyQuery 請求寫成方法
        '''
        d = pq(url=url, headers={
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'})
        return d

    def downloadVideo(self, url, file_name=''):
        '''
        下載視頻
        :param url: 下載url路徑
        :return: 文件
        '''
        with closing(requests.get(url, stream=True)) as response:
            chunk_size = 1024
            content_size = int(response.headers['content-length'])
            file_D='./Video/' + file_name + '.mp4'
            if(os.path.exists(file_D)  and os.path.getsize(file_D)==content_size):
                print('跳過'+file_name)
            else:
                progress = ProgressBar(file_name, total=content_size, unit="KB", chunk_size=chunk_size, run_status="正在下載",fin_status="下載完成")
                with open(file_D, "wb") as file:
                    for data in response.iter_content(chunk_size=chunk_size):
                        file.write(data)
                        progress.refresh(count=len(data))

'''
下載進度
'''
class ProgressBar(object):
    def __init__(self, title, count=0.0, run_status=None, fin_status=None, total=100.0, unit='', sep='/',
                 chunk_size=1.0):
        super(ProgressBar, self).__init__()
        self.info = "[%s] %s %.2f %s %s %.2f %s"
        self.title = title
        self.total = total
        self.count = count
        self.chunk_size = chunk_size
        self.status = run_status or ""
        self.fin_status = fin_status or " " * len(self.statue)
        self.unit = unit
        self.seq = sep

    def __get_info(self):
        # 【名稱】狀態 進度 單位 分割線 總數 單位
        _info = self.info % (
            self.title, self.status, self.count / self.chunk_size, self.unit, self.seq, self.total / self.chunk_size,
            self.unit)
        return _info

    def refresh(self, count=1, status=None):
        self.count += count
        # if status is not None:
        self.status = status or self.status
        end_str = "\r"
        if self.count >= self.total:
            end_str = '\n'
            self.status = status or self.fin_status
        print(self.__get_info(), end=end_str)


if __name__ == '__main__':
    C = SaveVideo()
    C.getLesson()
    sys.exit()

通過pyinstaller打包

import sys

if __name__ == '__main__':
    from PyInstaller import __main__
    params = ['-F','-c','--noupx', '--icon=favicon.ico', 'save.py']
    __main__.run(params)

 

 

 

 

查看:

 

 

 

 

 

 

 

 

 

4:分享課程視頻

已經將視頻打包分享到雲盤中,有興趣的可以在這   下載


免責聲明!

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



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