爬蟲11天——selenium實戰


一、目的:爬取陽光視頻網的多個視頻,下載到本地

二、網站分析:

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集合的用法:

 

 

 

 

 

 

 

 

 


免責聲明!

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



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