[python爬蟲] Selenium切換視窗控制程式碼及呼叫Chrome瀏覽器

Eastmount發表於2016-11-21
        因為我的部落格是根據我每個階段自己做的事情而寫的,所以前言可能有點跑題,但它更有利於讓我回憶這個階段自己的所作所為。這篇文章主要介紹Selenium爬蟲獲取當前視窗控制程式碼、切換視窗控制程式碼以及呼叫Chrome瀏覽器幾個知識點,其中獲取當前控制程式碼的方法是非常重要的一個知識點,只有真正遇到的時候才能體會到它的強大。
        最近課程比較多,寫部落格的內容也比較雜,包括網站搭建、HTML設計、計算機圖形學、Python資料探勘、Flash動畫等。同時,這周也有老師讓我幫忙寫幾個爬蟲,自己進一步理解了爬蟲的好處:一方面,人文課題如果運用計算機相關程式設計知識,確實能夠解決很多問題並提升效率;另一方面,我爬蟲主要使用Selenium、BeautifulSoup和Scrapy,其中Selenium能夠結合瀏覽器解決登入驗證碼、掃二維碼、效果預覽、自動測試等問題;BeautifulSoup的優勢是速度,兩種方法都是通過分析DOM樹結構實現的。
        希望這篇文章對你有所幫助,如果有錯誤或不足之處,還請海涵~更多爬蟲主題參考我的專欄:http://blog.csdn.net/column/details/eastmount-spider.html


一. 呼叫Chrome瀏覽器


        首先,假設通過Firefox()瀏覽器定向爬取CSDN首頁導航欄資訊,審查元素程式碼如下圖所示,在div class="menu"路徑的ul、li、a下,同時可以定位ul class="clearfix"。

        程式碼如下所示:

# coding=utf-8  
import os   
from selenium import webdriver

#PhantomJS無介面瀏覽器
##driver = webdriver.PhantomJS(executable_path="G:\phantomjs-1.9.1-windows\phantomjs.exe")  

#開啟火狐瀏覽器
driver = webdriver.Firefox()
url = "http://www.csdn.net/"
driver.get(url)

#xpath路徑定位導航欄
elem_dh = driver.find_elements_by_xpath("//div[@class='menu']/ul/li/a")
for elem in elem_dh:
    print elem.text                    #獲取正文
    print elem.get_attribute('href')   #獲取屬性值
    
        然後轉換成chrome瀏覽器,只需要在"C:\Program Files (x86)\Google\Chrome\Application\"路徑下放置個chromedriver.exe驅動,再進行呼叫即可,程式碼如下所示:

# coding=utf-8  
import os   
from selenium import webdriver

#PhantomJS無介面瀏覽器
##driver = webdriver.PhantomJS(executable_path="G:\phantomjs-1.9.1-windows\phantomjs.exe")  

#開啟火狐瀏覽器
#driver = webdriver.Firefox()

#谷歌瀏覽器
chromedriver = "C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe"
os.environ["webdriver.chrome.driver"] = chromedriver
driver = webdriver.Chrome(chromedriver)

#WebDriverException: Message: unknown error: session deleted because of page crash

url = "http://www.csdn.net/"
driver.get(url)

#xpath路徑定位導航欄
elem_dh = driver.find_elements_by_xpath("//div[@class='menu']/ul/li/a")
for elem in elem_dh:
    print elem.text                    #獲取正文
    print elem.get_attribute('href')   #獲取屬性值
    print '\n'
    
        執行結果如下圖所示:
>>> ================================ RESTART ================================
>>> 
極客頭條
http://geek.csdn.net/
知識庫
http://lib.csdn.net/
學院
http://edu.csdn.net/
論壇
http://bbs.csdn.net/
部落格
http://blog.csdn.net/
下載
http://download.csdn.net/
問答
http://ask.csdn.net/
商城
http://mall.csdn.net/
ITeye
http://www.iteye.com/
CODE
https://code.csdn.net/
活動
http://huiyi.csdn.net/
CTO
http://cto.csdn.net/
外包
http://www.csto.com/
程式設計師
http://special.csdncms.csdn.net/programmer-covers
APP
http://www.csdn.net/app
>>> 


二. 獲取當前控制程式碼並切換視窗控制程式碼

        在使用Selenium爬取知識過程,通常會遇到_blank彈出新窗體,或窗體是彈出的那種情況,而且有的需要登入,如:新浪微博、微信公眾號、京東等,使用webdriver.Firefox()重新開啟新窗體是無法載入已有資訊的。這時候就需要通過獲取當前控制程式碼再進行視窗切換。
        這裡使用該方法實現獲取CSDN導航欄的每條導航的標題資訊,因為它是_blank彈出新窗體。需要注意每次視窗控制程式碼移動都需要重新定位它們的主窗體。
        核心程式碼:

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

#獲取所有視窗控制程式碼
all_handles = driver.window_handles 
for handle in all_handles:
    if handle!=now_handle:
        #輸出待選擇的視窗控制程式碼
        print handle
        driver.switch_to_window(handle)
        time.sleep(1)

        #具體操作
        elem_bt = driver.find_element_by_xpath("...")
        driver.close() #關閉當前視窗

#輸出主視窗控制程式碼
print now_handle
driver.switch_to_window(now_handle) #返回主視窗
        如下圖所示:<a href="xxxx" target="_blank">極客頭條</a>



例項程式碼如下所示,它會依次開啟每個導航欄,在爬取關閉。

# coding=utf-8  
import os
import time
from selenium import webdriver

#By:Eastmoun 2016-11-21 凌晨4:26

#開啟火狐瀏覽器
driver = webdriver.Firefox()
url = "http://www.csdn.net/"
driver.get(url)

#xpath路徑定位導航欄
elem_dh = driver.find_elements_by_xpath("//div[@class='menu']/ul/li/a")

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


#迴圈獲取介面
for elem in elem_dh:
    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_sub = driver.find_element_by_xpath("//ul[@class='btns']/li/a")
            print elem_sub.text
            print elem_sub.get_attribute('href')
            print ''

            #關閉當前視窗
            driver.close()
            

    #輸出主視窗控制程式碼
    print now_handle
    driver.switch_to_window(now_handle) #返回主視窗 開始下一個跳轉
    

        輸出結果如下所示:

>>> ================================ RESTART ================================
>>> 
{833ee0ee-c408-432a-ab54-1222a22f580c}
極客頭條
http://geek.csdn.net/
{50e7dfc6-72d8-4577-99ca-47344a068528}
彈出介面資訊
http://geek.csdn.net/
最新最熱 - 極客頭條 - CSDN.NET
登入 
https://passport.csdn.net/account/login?ref=toolbar

{833ee0ee-c408-432a-ab54-1222a22f580c}
知識庫
http://lib.csdn.net/
{4501a3d1-8ab3-4a5e-984b-ace648494f94}
彈出介面資訊
http://lib.csdn.net/
知識庫 - 你身邊的技術百科全書 - CSDN
登入 
https://passport.csdn.net/account/login?ref=toolbar

{833ee0ee-c408-432a-ab54-1222a22f580c}
學院
http://edu.csdn.net/
{4525da42-fd77-4f04-b2f9-1687d75c1e19}
彈出介面資訊
http://edu.csdn.net/
CSDN學院 - CSDN.NET
登入 
https://passport.csdn.net/account/login?ref=toolbar

{833ee0ee-c408-432a-ab54-1222a22f580c}
論壇
http://bbs.csdn.net/
{c24493c1-c937-4a90-85a1-e11f7be870c4}
彈出介面資訊
http://bbs.csdn.net/home
CSDN論壇首頁 - CSDN.NET-CSDN論壇-CSDN.NET-中國最大的IT技術社群
登入 
https://passport.csdn.net/account/login?ref=toolbar

{833ee0ee-c408-432a-ab54-1222a22f580c}
部落格
http://blog.csdn.net/
{a4686eae-b437-4b97-97a2-160024359ade}
彈出介面資訊
http://blog.csdn.net/
部落格頻道 - CSDN.NET
登入 
https://passport.csdn.net/account/login?ref=toolbar

{833ee0ee-c408-432a-ab54-1222a22f580c}
下載
http://download.csdn.net/
{42cf058e-e093-4619-beae-4454aaba29a3}
彈出介面資訊
http://download.csdn.net/
下載頻道 - CSDN.NET
登入 
https://passport.csdn.net/account/login?ref=toolbar

{833ee0ee-c408-432a-ab54-1222a22f580c}
問答
http://ask.csdn.net/
{cb0633e2-45a5-406d-9aaa-79ea994e1f6a}
彈出介面資訊
http://ask.csdn.net/
程式設計技術問答-CSDN問答頻道
登入 
https://passport.csdn.net/account/login?ref=toolbar

{833ee0ee-c408-432a-ab54-1222a22f580c}
商城
http://mall.csdn.net/
{126f85af-d5e4-4d40-a89e-6fbb575a972b}
彈出介面資訊
http://mall.csdn.net/
CSDN商城
登入 
https://passport.csdn.net/account/login?ref=toolbar
        PS:這段程式碼主要是讓你熟悉獲取當前窗體及切換窗體,真正爬蟲用到的時候是非常方便的,而且必須要使用。




三. 一段程式碼 線上筆記

        下面這段程式碼是我的線上筆記,由於程式碼非常有用,所以我隱藏了些東西,但絕對好用,而且是結合上面的內容。同時,在登入過程中,我建議大家time.sleep()函式暫停,輸入驗證碼、掃描二維碼都是可行的。

# -*- coding: utf-8 -*-
# By: Eastmount 2016-11-21 凌晨4點半

from selenium import webdriver  
from selenium.webdriver.common.keys import Keys  
import time
import os
  

#模擬登陸
chromedriver = "C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe"
os.environ["webdriver.chrome.driver"] = chromedriver
driver = webdriver.Chrome(chromedriver)
now_handle = driver.current_window_handle #獲取當前視窗控制程式碼

#driver = webdriver.Firefox()
#暫停10秒手動輸入網址
time.sleep(3)   
  
#使用者名稱 密碼
driver.get("xxxxxxxxxxx")
elem_user = driver.find_element_by_id("account")  
elem_user.send_keys("******")  
elem_pwd = driver.find_element_by_id("pwd")  
elem_pwd.send_keys("******")  
elem_pwd.send_keys(Keys.RETURN)
#暫定60秒掃二維碼 跳轉到定向頁面
time.sleep(60)  

#登入使用者管理 獲取相關標籤
print driver.current_url
elem_user = driver.find_elements_by_xpath("//td[@class='table_cell user']/div/a[1]")  
now_handle = driver.current_window_handle #獲取當前視窗控制程式碼
print now_handle   #輸出當前獲取的視窗控制程式碼

#單擊操作
for elem in elem_user:
    print '########################################'
    print elem.text
    #點選進入檢視詳細使用者
    elem.click()

    """
    NoSuchElementException: Message: no such element
    因為總是獲取當前控制程式碼 故找不到相關的介面,需要視窗控制程式碼轉換
    """
    all_handles = driver.window_handles #獲取所有視窗控制程式碼
    for handle in all_handles:
        if handle!=now_handle:
            #輸出待選擇的視窗控制程式碼
            print handle
            driver.switch_to_window(handle)
            time.sleep(1)
            
            #點選"圖文訊息"
            elem_tw = driver.find_element_by_xpath("//li[@class='tab_nav tab_appmsg width5']/a")
            #elem_tw = driver.find_element_by_xpath("//div[@class='tab_navs_wrp']/ul/li/a")

            print elem_tw.text
            print elem_tw.get_attribute("href")
            elem_tw.click()
            time.sleep(1)

            #點選 '從素材庫中選擇'按鈕
            elem_sc = driver.find_element_by_xpath("//span[@class='create_access']/a")
            print elem_sc.text
            print elem_sc.get_attribute("href")
            elem_sc.click()
            time.sleep(1)

            #點選素材 '11-14 星期二中獎名單' 注意是id
            #elem_dj = driver.find_element_by_xpath("//div[@class='edit_mask appmsg_mask']")
            #elem_dj = driver.find_element_by_xpath("//div[@id='appmsg503811334']/div/div[2]")
            elem_dj = driver.find_element_by_xpath("//div[@id='appmsg503811334']")
            print elem_dj.text
            print elem_dj.get_attribute("href")
            elem_dj.click()
            time.sleep(1)
            
            #SyntaxError: Failed to execute 'evaluate' on 'Document': The string
            #'//div[@class='appmsg503811334']/div/' is not a valid XPath expression.

            #WebDriverException: Message: unknown error: Element is not clickable
            #at point (473, 361). Other element would receive the click:
            #<div class="appmsg_content">...</div>

            #獲取'確定按鈕'
            elem_bt = driver.find_element_by_xpath("//div[@class='dialog_ft']/span[1]/button")
            print elem_bt.text
            print elem_bt.get_attribute("class")
            elem_bt.click()
            time.sleep(1)

            #點選 '傳送'
            elem_fs = driver.find_element_by_xpath("//span[@id='js_submit']/button")
            print elem_fs.text
            print elem_fs.get_attribute("class")
            elem_fs.click()
            time.sleep(1)

            #關閉當前視窗
            driver.close() 
            

    #輸出主視窗控制程式碼
    print now_handle
    driver.switch_to_window(now_handle) #返回主視窗
    #break

    print '\n\n'
    

#暫停換頁
#登入使用者管理 獲取相關標籤
print '********************************************'
print '********************************************'
print u'換頁操作1'
#elem_next = driver.find_elements_by_xpath("//a[@class='btn page_next']")
#elem_next.click()

time.sleep(10)
elem_user = driver.find_elements_by_xpath("//td[@class='table_cell user']/div/a[1]")  
now_handle = driver.current_window_handle #獲取當前視窗控制程式碼
print now_handle   #輸出當前獲取的視窗控制程式碼

#單擊操作
for elem in elem_user:
    print '########################################'
    print elem.text
    #點選進入檢視詳細使用者
    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)
            
            #點選"圖文訊息"
            elem_tw = driver.find_element_by_xpath("//li[@class='tab_nav tab_appmsg width5']/a")
            print elem_tw.text
            print elem_tw.get_attribute("href")
            elem_tw.click()
            time.sleep(1)

            #點選 '從素材庫中選擇'按鈕
            elem_sc = driver.find_element_by_xpath("//span[@class='create_access']/a")
            print elem_sc.text
            print elem_sc.get_attribute("href")
            elem_sc.click()
            time.sleep(1)

            #點選素材 注意是id
            elem_dj = driver.find_element_by_xpath("//div[@id='appmsg503811334']")
            print elem_dj.text
            print elem_dj.get_attribute("href")
            elem_dj.click()
            time.sleep(1)
            
            #獲取'確定按鈕'
            elem_bt = driver.find_element_by_xpath("//div[@class='dialog_ft']/span[1]/button")
            print elem_bt.text
            print elem_bt.get_attribute("class")
            elem_bt.click()
            time.sleep(1)

            #點選 '傳送'
            elem_fs = driver.find_element_by_xpath("//span[@id='js_submit']/button")
            print elem_fs.text
            print elem_fs.get_attribute("class")
            elem_fs.click()
            time.sleep(1)

            driver.close() #關閉當前視窗
            

    #輸出主視窗控制程式碼
    print now_handle
    driver.switch_to_window(now_handle) #返回主視窗
    #break
    print '\n\n'
    

        最後希望這篇文章對你有所幫助,因為第三部分程式碼涉密,消除了些東西,但原理和方法更重要,希望你也能靈活應用。同時明天評估專家就來了,雖然幹活到2點,但還是想寫一篇文章,記錄最近兩天研究的東西,很重要的一個知識點。繼續享受部落格和教學吧,同時期待我最近欣賞的某個人吧!楊老師加油~
       (By:Eastmount 2016-11-21 凌晨4點半  http://blog.csdn.net/eastmount/ )



相關文章