Python網路爬蟲(四):視訊下載器
這一節實現一個下載 iqiyi VIP視訊的爬蟲。
需要的準備:旋風視訊VIP解析網站或其他解析網站
原理理解:
在視訊解析網站獲取視訊的過程中,首先會向視訊伺服器傳送GET請求,獲得伺服器發來的資訊;接到資訊後,再向伺服器POST資料,即將類似於密碼的資料上傳給伺服器;伺服器驗證資訊後,返回所請求的視訊地址資訊。視訊網站根據該地址資訊獲得視訊的資源地址(即在伺服器上的快取地址),開啟該地址即可進行播放。
爬蟲的實現:
一. 獲得視訊的資源地址
- 利用fildder對該地址進行抓包;
- 找到 POST /xfsub_api/url.php HTTP/1.1 項,檢視json中的內容:
- 開啟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大概幾分鐘下完。