[python爬蟲] Selenium高階篇之視窗移動、彈出對話方塊自登入

Eastmount發表於2017-08-10

在我們使用Selenium Python製作自動爬蟲和網頁自動測試的時候,通常會遇到彈出新的窗體或對話方塊的時候,此時你捕獲的窗體已經被打斷,從而干擾你的爬蟲。
那怎麼解決這個問題呢?

本篇文章主要記錄兩段程式碼解決這類問題:
    第一個是click()函式點選超連結後,需要捕獲彈出新窗體的資訊,此時需要呼叫switch_to_window()函式切換窗體,再捕獲新的資料;
    第二個是click()函式點選超連結後,彈出登入的對話方塊,比如百度首頁登入,此時需要呼叫switch_to_alert()函式獲取該alert物件。

文章主要是結合實際問題進行敘述,內容比較基礎,希望對您有所幫助,如果存在錯誤或不足之處,還請海涵。更多爬蟲主題參考我的專欄:http://blog.csdn.net/column/details/eastmount-spider.html


一. Switch_to_window函式實現窗體切換

在使用Selenium爬取知識過程,通常會遇到_blank彈出新窗體,或窗體是彈出的那種情況,而且有的需要登入,如:新浪微博、公眾號、京東等,使用webdriver.Firefox()重新開啟新窗體是無法載入已有資訊的。這時候就需要通過獲取當前控制程式碼再進行視窗切換。

這裡使用該方法實現獲取CSDN知識庫的關鍵詞的標題及超連結資訊,因為它是_blank彈出新窗體,再獲取彈出窗體的技術介紹。需要注意每次視窗控制程式碼移動都需要重新定位它們的主窗體。

核心程式碼:

# -*- coding: utf-8 -*-
from selenium import webdriver  
from selenium.webdriver.common.keys import Keys  
import time
import os

#訪問連結
driver = webdriver.Firefox()
url = "http://lib.csdn.net/"
driver.get(url) 
elem_div = driver.find_elements_by_xpath("//ul[@class='list01 clearfix']/li/div[2]/a")

#獲取當前視窗控制程式碼
now_handle = driver.current_window_handle
print now_handle

for elem in elem_div:
    print elem.text                    #獲取正文
    print elem.get_attribute('href')   #獲取屬性值

    #點選進入新的介面 _blank彈出  
    elem.click()

    #獲取所有視窗控制程式碼  
    all_handles = driver.window_handles  
      
    #彈出兩個介面,跳轉到不是主窗體介面  
    for handle in all_handles:  
        if handle!=now_handle:     
            #輸出待選擇的視窗控制程式碼  
            print handle  
            driver.switch_to_window(handle)  
            time.sleep(1)  
  
            print u'彈出介面資訊'  
            print driver.current_url  
            print driver.title  
  
            #獲取登入連線資訊  
            elem_p = driver.find_element_by_xpath("//div[@class='coltop clearfix']/div[2]")  
            print elem_p.text   
  
            #關閉當前視窗  
            driver.close()  
              
    #輸出主視窗控制程式碼  
    print now_handle  
    driver.switch_to_window(now_handle) #返回主視窗 開始下一個跳轉    
步驟如下:
    1.首先,current_window_handle獲取當前首頁窗體並儲存;
    2.然後呼叫find_elements_by_xpath()獲取首頁多個關鍵詞超連結(多個<li>),for迴圈訪問;
    3.在迴圈中點選超連結,彈出新的窗體,迴圈找到不是首頁窗體的,呼叫switch_to_window進行跳轉;
    4.爬取新窗體關鍵詞的介紹資訊,位於div[@class='coltop clearfix']/div[2]下;
    5.關閉當前窗體,重新返回首頁窗體的超連結,迴圈執行3-5步驟。

部分輸出如下所示:

主窗體: {3f9dc2dc-d468-4695-9fb8-493b9d1dd245}
Android
http://lib.csdn.net/base/android
{9e7fbd44-b487-479d-8c5a-c5dd387a1b48}
Android知識庫 - 知識庫 - 你身邊的技術百科全書 - CSDN
標準知識圖譜
我的知識圖譜(27234)
Android是一個基於Linux核心的移動作業系統,由Google成立的Open Handset Alliance(OHA,開放手持裝置聯盟)持續領導與開發,主要設計用於觸控熒幕移動裝置如智慧手機和平板電腦。
知識節點: 搭建App開...熟悉Android...APP基礎軟體架構設...App高階開... 更多

{3f9dc2dc-d468-4695-9fb8-493b9d1dd245} React
http://lib.csdn.net/base/react
{82d2e23b-dc70-424c-a2db-bf8710844ca7}
React知識庫 - 知識庫 - 你身邊的技術百科全書 - CSDN
標準知識圖譜
我的知識圖譜(2012)
React是一個Facebook和Instagram用來建立使用者介面的JavaScript庫,用於構建“可預期的”和“宣告式的”Web使用者介面。 該框架的推出主要為了開發隨著時間資料不斷變化的大規模應用程式。
知識節點: 基礎語法外掛檢視與資料...工程化路由細化 更多
CSDN知識庫如下圖所示,首頁顯示了多個技術的關注資訊及資源數量。


審查元素如下圖所示,Android技術等均在<ul>標籤下,通過多個<li></li>實現,此時獲取Android超連結的url,並點選其操作。


點選後,會彈出新的窗體,而Selenium卻定位了當前首頁的窗體,此時就需要利用switch_to_window來切換窗體。


審查元素對應的HTML原始碼如下:



二. Switch_to_alert函式捕獲彈出對話方塊

注意:一定不要嘗試該方法登陸百度、新浪、淘寶這些網站後爬取資料,賬號可能被永久封號的。
比如百度首頁,點選登入介面會彈出對話方塊如下圖所示:





首先,需要獲取“登入”的位置,超連結<a>直接xpath定位總是失敗,故作者才採用的<div id='u1'>進行定位,超連結位於第7個超連結。
#失敗
elem_login = driver.find_element_by_xpath("//a[@name='tj_login']")
#成功
elem_login = driver.find_element_by_xpath("//div[@id='u1']/a[7]")

然後,彈出的對話方塊採用driver.switch_to_alert()方法選擇alert物件。



獲取使用者名稱和密碼後,需要設定sleep暫停,輸入驗證碼,然後自動登入即可,登入後即可爬取相關資訊。
核心程式碼如下:

# -*- coding: utf-8 -*-
from selenium import webdriver  
from selenium.webdriver.common.keys import Keys  
import time
import os

#訪問連結
driver = webdriver.Firefox()
url = "https://www.baidu.com/"
driver.get(url) 
#失敗
elem_login = driver.find_element_by_xpath("//a[@name='tj_login']")
#成功
elem_login = driver.find_element_by_xpath("//div[@id='u1']/a[7]")

#獲取當前視窗控制程式碼
now_handle = driver.current_window_handle
print now_handle

#獲取當前登入按鈕資訊
print elem_login.text                    
print elem_login.get_attribute('href')
elem_login.click()
time.sleep(2)

#選擇彈出的對話方塊
driver.switch_to_alert()

#獲取使用者名稱和密碼
elem_name = driver.find_element_by_xpath("//input[@name='userName']")
elem_name.send_keys(u"eastmount")
elem_pwd = driver.find_element_by_xpath("//input[@name='password']")
elem_pwd.send_keys("12345678")
time.sleep(10)
elem_pwd.send_keys(Keys.RETURN)
登入後如下圖所示:




最後希望這篇文章對你有所幫助,原理和方法更重要,希望你也能靈活應用。繼續享受部落格和教學吧,同時期待我最近欣賞的某個人吧!楊老師綠么加油~
    不願清醒,寧願一直沉迷放縱。
    不知歸路,寧願一世無悔追逐。
    再苦再累,也笑看庭前花開花落。
(By:Eastmount 2017-08-10 晚上11點半  http://blog.csdn.net/eastmount/ )


相關文章