1. 程式人生 > >Python網路爬蟲(四):視訊下載器

Python網路爬蟲(四):視訊下載器

這一節實現一個下載 iqiyi VIP視訊的爬蟲。
需要的準備:旋風視訊VIP解析網站或其他解析網站

原理理解:

視訊解析網站獲取視訊的過程中,首先會向視訊伺服器傳送GET請求,獲得伺服器發來的資訊;接到資訊後,再向伺服器POST資料,即將類似於密碼的資料上傳給伺服器;伺服器驗證資訊後,返回所請求的視訊地址資訊。視訊網站根據該地址資訊獲得視訊的資源地址(即在伺服器上的快取地址),開啟該地址即可進行播放。

爬蟲的實現:

一. 獲得視訊的資源地址

  1. 利用fildder對該地址進行抓包;
  2. 找到 POST /xfsub_api/url.php HTTP/1.1 項,檢視json中的內容:
    這裡寫圖片描述
  3. 開啟4中所獲的地址,得到了視訊的快取地址,即資源地址。
    這裡寫圖片描述
  4. 利用該資源地址就可以輕鬆下載視訊了。

二、根據資源地址下載視訊

這裡採用urllib.request.urlretrieve()函式進行下載。

urlretrieve() 函式用於直接將遠端資料下載到本地。

urlretrieve(url, filename=None, reporthook=None, data=None)

引數說明:
*引數 finename 指定了儲存本地路徑(如果引數未指定,urllib會生成一個臨時檔案儲存資料。)
*引數 reporthook 是一個回撥函式,當連線上伺服器、以及相應的資料塊傳輸完畢時會觸發該回調,我們可以利用這個回撥函式來顯示當前的下載進度。
*引數 data 指 post 到伺服器的資料,該方法返回一個包含兩個元素的(filename, headers)元組,filename 表示儲存到本地的路徑,header 表示伺服器的響應頭。

例項:

# urlretrieve_test.py
# encoding:utf-8

import urllib
import os
def Schedule(a,b,c):
    '''
    回撥函式:用於顯示下載進度
    a:已經下載的資料塊
    b:資料塊的大小
    c:遠端檔案的大小
   '''
    per = 100.0 * a * b / c
    if per > 100 :
        per = 100
    print '%.2f%%' % per

url = 'http://www.python.org/ftp/python/2.7.5/Python-2.7.5.tar.bz2'
#local = url.split('/')[-1] local = os.path.join('/data/software','Python-2.7.5.tar.bz2') urllib.urlretrieve(url,local,Schedule) ######output###### #0.00% #0.07% #0.13% #0.20% #.... #99.94% #100.00%

split()函式和os.path.split()

split():拆分字串。通過指定分隔符對字串進行切片,並返回分割後的字串列表(list)
os.path.split():按照路徑將檔名和路徑分割開

1、split()函式

str.split(str=”“,num=string.count(str))[n]

引數說明:
str: 表示為分隔符,預設為空格,但是不能為空(”)。若字串中沒有分隔符,則把整個字串作為列表的一個元素
num:表示分割次數。如果存在引數num,則僅分隔成 num+1 個子字串,並且每一個子字串可以賦給新的變數
[n]: 表示選取第n個分片
注意:當使用空格作為分隔符時,對於中間為空的項會自動忽略

2、os.path.split()函式

os.path.split(‘PATH’)

引數說明:
PATH指一個檔案的全路徑作為引數:
如果給出的是一個目錄和檔名,則輸出路徑和檔名
如果給出的是一個目錄名,則輸出路徑和為空檔名

程式碼整理:

# video_downloader.py

import requests,re, json, sys
from bs4 import BeautifulSoup
from urllib import request

class video_downloader():
    def __init__(self, url):
        #*****這些url是從抓包軟體中獲得的*****
        self.server = 'http://api.xfsub.com'        #解析網站域名
        self.api = 'http://api.xfsub.com/xfsub_api/?url='
        self.get_url_api = 'http://api.xfsub.com/xfsub_api/url.php'#post資訊發往的伺服器
        self.url = url.split('#')[0]     #去掉多餘的字串
        self.target = self.api + url
        self.s = requests.session()      #身份證,用來持續訪問伺服器

    """
    函式說明:獲取key、time、url等引數(POST給伺服器)

    """
    def get_key(self):
        req = self.s.get(url=self.target)   #獲得解析網站傳送的key等資訊
        req.encoding = 'utf-8'              #編碼
        self.info = json.loads(re.findall('"url.php",\ (.+),', req.text)[0])   #json.loads用於將json格式資料轉換為python格式,是個字典

    """
    函式說明:獲取視訊地址

    """
    def get_url(self):
        data = {'time':self.info['time'],
            'key':self.info['key'],
            'url':self.info['url'],
            'type':''}
        req = self.s.post(url=self.get_url_api,data=data)   #將key等傳送給另外一個伺服器
        url = self.server + json.loads(req.text)['url']     #伺服器返回一個json檔案
        req = self.s.get(url)                               #再對新網址傳送請求命令
        bf = BeautifulSoup(req.text,'xml')                  #返回xml檔案                     #因為檔案是xml格式的,所以要進行xml解析。
        video_url = bf.find('file').string                  #獲得視訊地址                        #匹配到視訊地址
        return video_url

    #**********以上兩步相當於把解析網址申請視訊的過程用程式碼進行了一遍********

    """
    函式說明:回撥函式,列印下載進度

    """
    def Schedule(self, a, b, c):
        per = 100.0*a*b/c
        if per > 100 :
            per = 1
        sys.stdout.write("  " + "%.2f%% 已經下載的大小:%ld 檔案大小:%ld" % (per,a*b,c) + '\r')
        sys.stdout.flush()

    """
    函式說明:視訊下載

    """
    def video_download(self, url, filename):
        request.urlretrieve(url=url,filename=filename,reporthook=self.Schedule)


if __name__ == '__main__':
    url = 'http://www.iqiyi.com/v_19rrnqzc4g.html#vfrm=19-9-0-1'
    filename = '王牌特工:特工學院'
    vd = video_downloader(url)
    print('%s下載中:' % filename)
    vd.get_key()
    video_url = vd.get_url()
    print('  獲取地址成功:%s' % video_url)
    vd.video_download(video_url, filename+'.mp4')
    print('\n下載完成!')

注:
程式在idle中執行時,下載速度很慢很慢;而在windows命令列中執行,則下載的較快,500多M大概幾分鐘下完。