首先聲明:此小視頻非彼小視頻,大家心照不宣即可
目標:https://www.vmovier.com/ 這網站名字好像叫場庫
""" 首先向https://www.vmovier.com/發送請求 獲取響應,解析響應 將所有標題和鏈接過濾出來 向過濾出的鏈接發請求下載視頻 向src屬性發送請求,獲取響應,將內容保存到本地 注意:這是一個動態的頁面 是js的數據 需要捕獲接口 使用抓包工具Fiddler 接口信息:https://www.vmovier.com/post/getbytab?tab=new&page=1&pagepart=2&type=0&controller=index&last_postid=58197 """ import requests from bs4 import BeautifulSoup import time import json from lxml import etree import re from selenium import webdriver from selenium.webdriver.chrome.options import Options #創建一個參數對象,用來控制Chrome以無界面模式打開 chrome_options = Options() #開啟無頭模式 chrome_options.add_argument('--headless') #禁用GPU chrome_options.add_argument('--disable-gpu') #驅動路徑 path =r'D:\chromedriver\chromedriver.exe' #添加頭部 作為全局 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36' } #此處有一個跳轉 感覺像是反爬機制 所以我們要再過濾一次 過濾出跳轉后的url這個函數用來處理此跳轉 def FanPa(r): #正則獲取src屬性 match_obj = re.compile(r'<meta property="article:published_first" content="新片場,(.*)" />') url = re.findall(match_obj,r.text) # print(url) # exit() return url #解析首頁,返回所有的標題鏈接 def handle_title(): #輸入你想要的爬取的頁數 page = int(input("請輸入您要爬取的頁數:")) print("開始爬取第%s頁....." % page) #將捕獲接口拿過來 因為是動態的頁面 所以捕獲接口 向接口發送數據 #page=頁數 pagepart=每頁的第幾次刷新 每頁有三次刷新分別是1 2 3 可以寫一個循環 for T in range (1,4): url = "https://www.vmovier.com/post/getbytab?tab=new&page=% s&pagepart=%d" %(page,T) # print(url) # exit() r = requests.get(url=url,headers=headers) #解析內容,因為返回的是json數據 直接解析json格式即可 # 后來發現不是嚴格json格式 就使用json對象取出了data部分 用正則過濾出來的 #我們需要的標題和鏈接分別是h1標簽下的title和href #將json數據轉化為Python對象 obj = json.loads(r.text) # print(obj) # exit() #取出所有和視頻相關的數據 標題和url 使用正則 data = obj['data'] #print(data) # # exit() match_obj_url = re.compile(r'<a href="(.*)" title=".*全文" target="_blank">閱讀全文...</a>') url = re.findall(match_obj_url,data) # print(url) # print(len(url)) match_obj_title = re.compile(r'<a href=".*" title="(.*)全文" target="_blank">閱讀全文...</a>') title = re.findall(match_obj_title,data) # print(title) # print(len(title)) # exit() #循環data列表 依次取出每一個視頻信息 # 其中標題信息可以直接用 但是url拼接后不是最終url 還有2次跳轉 for i in range (0,15):#兩個列表各有15條數據 一一對應 end_title = title[i] #print(end_title) a_href = "https://www.vmovier.com" + url[i] # print(a_href) # exit() #這個不是最終視頻url 需要處理一次跳轉 r = requests.get(url=a_href,headers=headers) end_href = FanPa(r)# 這是倒數第二層url # print(end_href) # exit() video_src = get_video_url(end_href) # print(video_src) # exit() #找到視頻原始地址后開始下載 print("開始下載%s..." % end_title) filepath = 'shipin/' + end_title +'.mp4' r = requests.get(url=video_src) with open(filepath,'wb')as fp: fp.write(r.content) print("%s下載完成" % end_title) #發送請求, 獲取內容 解析內容,獲取src def get_video_url(end_href): # print(end_href)# 這里end_href是一個只有一個元素的列表 所以要加下標 # # exit() # r = requests.get(url=end_href[0],headers=headers) # print(r.text) # exit() #這里打印返回頁面 發現沒有我們想找的video鏈接 # 很可能又是反爬機制 所以使用終極武器 無頭瀏覽器來解決 browser = webdriver.Chrome(executable_path=path,options=chrome_options) browser.get(end_href[0]) time.sleep(3) #獲取源碼,生成tree對象,然后查找video里的src屬性 # print(browser.page_source) # exit() soup = BeautifulSoup(browser.page_source,'lxml') video_src =soup.find('video',id="xpc_video")['src'] # print(video_src) # exit() return video_src def main(): #解析首頁,返回所有的標題鏈接 handle_title() if __name__ == '__main__': main()
主要需要注意的問題是:
1、對於這種懶加載的網頁 一般要捕獲其接口,從接口返回信息中過濾出標題和url
2、這個網站有一個跳轉過程,感覺像是反爬的機制,可以通過一步步輸出HTML頁面去判斷是否是我們需要的頁面
3、有一些地方 比如json返回的數據 不是嚴格的json格式 我們就把數據取出來 使用正則表達式去過濾
4、有的時候requests模塊發送請求不能獲得我們想要的頁面 可能需要使用無界面瀏覽器驅動去獲取頁面內容
結果: