一、目的:爬取陽光視頻網的多個視頻,下載到本地
二、網站分析:
1.網站結構分為:視頻列表頁和視頻詳情頁
2.右鍵檢查視頻列表網頁:
發現:每條視頻都是一個class叫"title-box"的div,然后視頻詳情頁的鏈接在這個div下面的a標簽
3.進入視頻詳情頁,檢查網頁:
發現:視頻地址在id為"vs"的div標簽下面的video標簽里面
三、爬取過程:
1.最初爬取代碼:
#需求:爬取陽光寬頻網的視頻,下載到本地
from selenium import webdriver import time import requests #陽光寬頻網爬取類
class ygkp: video_url_list = [] url_list = [] #1.驅動——返回驅動driver
def get_driver(self): # 1.selenium配置
# 1.1 設置請求頭
options = webdriver.ChromeOptions() options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36") driver = webdriver.Chrome(options=options) return driver # #1.5 關閉底部banner頁
# def close_bottom_banner(self,driver):
# #定位關閉按鈕
# close_bt = driver.find_element_by_class_name("close-banner-icon")
# #點擊關閉按鈕
# close_bt.click()
#2.視頻列表頁——返回視頻網頁鏈接元素列表
def get_video_list_page(self,driver): #2.進入網站
driver.get("https://365yg.com/") time.sleep(5) #3.獲取視頻詳情頁鏈接
video_div_url_list = driver.find_elements_by_class_name("title-box") #print("video_div_url_list" + str(video_div_url_list))
for div in video_div_url_list: #print("div" + str(div))
a = div.find_element_by_tag_name("a") self.video_url_list.append(a) #url = a.get_attribute("href")
#self.url_list.append(url)
#3.視頻詳情頁——返回視頻的URL
def get_video_url(self,driver,num): time.sleep(5) if num == 1: driver.switch_to.window(driver.window_handles[num+1]) else: driver.switch_to.window(driver.window_handles[-1]) driver.save_screenshot("01.png") div = driver.find_element_by_id("vs") #print("video_div" + str(div))
time.sleep(5) video_src = div.find_element_by_tag_name("video").get_attribute("src") #print("video_src" + str(video_src))
return video_src #4.下載視頻
def download_video(self,num,video_src): response = requests.get(video_src).content with open("shipin" + str(num+1) + ".mp4", "wb") as f: f.write(response)
#5.運行
def run(self): #1.獲取驅動
driver = self.get_driver() #2.獲取視頻詳情頁列表
self.get_video_list_page(driver=driver) print(str(len(self.video_url_list))) #3.關閉底部banner頁
#self.close_bottom_banner(driver=driver)
#print("video_url_list"+str(self.video_url_list))
#4.點擊每個視頻鏈接
for i, video_web_url in enumerate(self.video_url_list): driver.switch_to.window(driver.window_handles[0]) print("video_web_url" + str(i+1) +":" + str(video_web_url)) #print("url" + str(i+1) + ":" + str(self.url_list[i]))
time.sleep(10) video_web_url.click() #driver.execute_script("arguments[0].click();", video_web_url)
#5.獲取每個視頻的URL地址
video_src = self.get_video_url(driver=driver,num=i) #6.下載url
self.download_video(num=i,video_src=video_src) ygkp().run()
結果報錯:
2.
在網上查詢到,有兩種解決辦法:
#方法1:
element = driver.find_element_by_css('div[class*="loadingWhiteBox"]') driver.execute_script("arguments[0].click();", element) #方法2:
element = driver.find_element_by_css('div[class*="loadingWhiteBox"]') webdriver.ActionChains(driver).move_to_element(element ).click(element ).perform()
我都試了一遍,結果,不會再報這個錯誤,但是后面會反復進入同一個詳情頁,反復下載同一個視頻
再次查詢ElementClickInterceptedException: Message: element click intercepted報錯原因:發現原來是由於已經定位到的目標元素被其他元素遮擋,所以無法點擊該元素。
查看網頁:
發現:視頻列表頁,底部有banner頁,擋住了第五條視頻。所以,無法點擊。就像用戶操作鼠標一樣,當banner頁覆蓋了第五條視頻時,用戶無法用鼠標點擊到該條視頻。這應該就是所說的——頁面元素存在遮擋
再次查看報錯信息:
也是在點擊第五條視頻時,出現錯誤。
解決方法:第一次進入視頻列表網頁時,就先立即關閉banner頁,然后再逐個點擊視頻。
檢查網頁:
關閉banner的X按鈕,class叫“close-banner-icon”
修改后代碼:
#需求:爬取陽光寬頻網的視頻,下載到本地
from selenium import webdriver import time import requests #陽光寬頻網類
class ygkp: video_url_list = [] url_list = [] #1.驅動——返回驅動driver
def get_driver(self): # 1.selenium配置
# 1.1 設置請求頭
options = webdriver.ChromeOptions() options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36") driver = webdriver.Chrome(options=options) return driver #1.5 關閉底部banner頁
def close_bottom_banner(self,driver): #定位關閉按鈕
close_bt = driver.find_element_by_class_name("close-banner-icon") #點擊關閉按鈕
close_bt.click() #2.視頻列表頁——返回視頻網頁鏈接元素列表
def get_video_list_page(self,driver): #2.進入網站
driver.get("https://365yg.com/") time.sleep(5) #3.獲取視頻詳情頁鏈接
video_div_url_list = driver.find_elements_by_class_name("title-box") #print("video_div_url_list" + str(video_div_url_list))
for div in video_div_url_list: #print("div" + str(div))
a = div.find_element_by_tag_name("a") self.video_url_list.append(a) #url = a.get_attribute("href")
#self.url_list.append(url)
#3.視頻詳情頁——返回視頻的URL
def get_video_url(self,driver,num): time.sleep(5) if num == 1: driver.switch_to.window(driver.window_handles[num+1]) else: driver.switch_to.window(driver.window_handles[-1]) driver.save_screenshot("01.png") div = driver.find_element_by_id("vs") #print("video_div" + str(div))
time.sleep(5) video_src = div.find_element_by_tag_name("video").get_attribute("src") #print("video_src" + str(video_src))
return video_src #4.下載視頻
def download_video(self,num,video_src): response = requests.get(video_src).content with open("shipin" + str(num+1) + ".mp4", "wb") as f: f.write(response) #5.運行
def run(self): #1.獲取驅動
driver = self.get_driver() #2.獲取視頻詳情頁列表
self.get_video_list_page(driver=driver) print(str(len(self.video_url_list))) #3.關閉底部banner頁
self.close_bottom_banner(driver=driver) #print("video_url_list"+str(self.video_url_list))
#4.點擊每個視頻鏈接
for i, video_web_url in enumerate(self.video_url_list): driver.switch_to.window(driver.window_handles[0]) print("video_web_url" + str(i+1) +":" + str(video_web_url)) #print("url" + str(i+1) + ":" + str(self.url_list[i]))
time.sleep(10) video_web_url.click() #driver.execute_script("arguments[0].click();", video_web_url)
#5.獲取每個視頻的URL地址
video_src = self.get_video_url(driver=driver,num=i) #6.下載url
self.download_video(num=i,video_src=video_src) ygkp().run()
這樣就能正常爬取了
四、補充:
查看視頻列表長度,發現:每次只能獲取7條視頻。
這是因為,網站視頻列表是動態加載的。每次滑動到底部會再加載新的7條視頻。
如果我們要想爬取所有視頻,該怎么辦呢?
解決方法:先爬取最初的7條視頻,然后每次爬取之前,都將網頁滾動到瀏覽器底部,待加載出新的視頻后,再次爬取。為了防止視頻element有重復,可以使用set集合存放視頻element。
#需求:爬取陽光寬頻網的視頻,下載到本地
from selenium import webdriver import time import requests #陽光寬頻網類
class ygkp: video_url_list = set() url_list = set() #1.驅動——返回驅動driver
def get_driver(self): # 1.selenium配置
# 1.1 設置請求頭
options = webdriver.ChromeOptions() options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36") driver = webdriver.Chrome(options=options) return driver #1.5 關閉底部banner頁
def close_bottom_banner(self,driver): #定位關閉按鈕
close_bt = driver.find_element_by_class_name("close-banner-icon") #點擊關閉按鈕
close_bt.click() #2.視頻列表頁——返回視頻網頁鏈接元素列表
def get_video_list_page(self,driver): # #2.進入網站
# driver.get("https://365yg.com/")
# time.sleep(5)
#3.獲取視頻詳情頁鏈接
video_div_url_list = driver.find_elements_by_class_name("title-box") #print("video_div_url_list" + str(video_div_url_list))
for div in video_div_url_list: #print("div" + str(div))
a = div.find_element_by_tag_name("a") self.video_url_list.add(a) url = a.get_attribute("href") self.url_list.add(url) #3.視頻詳情頁——返回視頻的URL
def get_video_url(self,driver,num): time.sleep(5) if num == 1: driver.switch_to.window(driver.window_handles[num+1]) else: driver.switch_to.window(driver.window_handles[-1]) driver.save_screenshot("01.png") div = driver.find_element_by_id("vs") #print("video_div" + str(div))
time.sleep(5) video_src = div.find_element_by_tag_name("video").get_attribute("src") #print("video_src" + str(video_src))
return video_src #4.下載視頻
def download_video(self,num,video_src): response = requests.get(video_src).content with open("shipin" + str(num+1) + ".mp4", "wb") as f: f.write(response)
#5.運行
def run(self): #1.獲取驅動
driver = self.get_driver() # 2.進入網站
driver.get("https://365yg.com/") time.sleep(5) # 3.關閉底部banner頁
self.close_bottom_banner(driver=driver) #2.獲取視頻詳情頁列表
for i in range(5): self.get_video_list_page(driver=driver) print(str(len(self.video_url_list))) driver.execute_script("window.scrollTo(0,document.body.scrollHeight)") time.sleep(5) #print("video_url_list"+str(self.video_url_list))
#4.點擊每個視頻鏈接
# for i, video_web_url in enumerate(self.video_url_list):
# driver.switch_to.window(driver.window_handles[0])
# print("video_web_url" + str(i+1) +":" + str(video_web_url))
# print("url" + str(i+1) + ":" + str(self.url_list[i]))
# time.sleep(10)
# video_web_url.click()
# #driver.execute_script("arguments[0].click();", video_web_url)
# #5.獲取每個視頻的URL地址
# video_src = self.get_video_url(driver=driver,num=i)
# #6.下載url
# self.download_video(num=i,video_src=video_src)
ygkp().run()
運行結果:
可以看到:視頻列表的長度增加了。
如果想爬取所有視頻,可以將for循環改成while循環。
五:總結:
我學到了:
1.元素element定位有多種方式:
https://i.cnblogs.com/EditPosts.aspx?postid=11127907
2. 獲取element的屬性值:get_attribute("屬性名")
3.下載視頻、圖片:
https://i.cnblogs.com/EditPosts.aspx?postid=11127907
4.報錯:element click intercepted的原因
是由於網頁上,存在頁面元素相互遮擋,無法點擊到目標元素
解決方法:
#方法1:
element = driver.find_element_by_css('div[class*="loadingWhiteBox"]') driver.execute_script("arguments[0].click();", element) #方法2:
element = driver.find_element_by_css('div[class*="loadingWhiteBox"]') webdriver.ActionChains(driver).move_to_element(element ).click(element ).perform()
方法3:
關閉掉,遮擋元素;總之,想法設法將被遮擋的點擊目標元素,露出來。
5.selenium滑動瀏覽器:
#移動到元素element對象的“頂端”與當前窗口的“頂部”對齊
driver.execute_script("arguments[0].scrollIntoView();", element);
driver.execute_script("arguments[0].scrollIntoView(true);", element); #移動到元素element對象的“底端”與當前窗口的“底部”對齊
driver.execute_script("arguments[0].scrollIntoView(false);", element); #移動到頁面最底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight)"); #移動到指定的坐標(相對當前的坐標移動)
driver.execute_script("window.scrollBy(0, 700)"); #結合上面的scrollBy語句,相當於移動到700+800=1600像素位置
driver.execute_script("window.scrollBy(0, 800)"); #移動到窗口絕對位置坐標,如下移動到縱坐標1600像素位置
driver.execute_script("window.scrollTo(0, 1600)"); #結合上面的scrollTo語句,仍然移動到縱坐標1200像素位置
driver.execute_script("window.scrollTo(0, 1200)");
6.python中set集合的用法: