Python爬蟲之路-selenium在爬蟲中的使用

Jiayu920716發表於2021-01-04

一.selenium的介紹

知識點:
  • 瞭解 selenium的工作原理
  • 瞭解 selenium以及chromedriver的安裝
  • 掌握 標籤物件click點選以及send_keys輸入

1. selenium執行效果展示

Selenium是一個Web的自動化測試工具,最初是為網站自動化測試而開發的,Selenium 可以直接呼叫瀏覽器,它支援所有主流的瀏覽器(包括PhantomJS這些無介面的瀏覽器),可以接收指令,讓瀏覽器自動載入頁面,獲取需要的資料,甚至頁面截圖等。我們可以使用selenium很容易完成之前編寫的爬蟲,接下來我們就來看一下selenium的執行效果

1.1 chrome瀏覽器的執行效果

在下載好chromedriver以及安裝好selenium模組後,執行下列程式碼並觀察執行的過程

from selenium import webdriver 

# 如果driver沒有新增到了環境變數,則需要將driver的絕對路徑賦值給executable_path引數
# driver = webdriver.Chrome(executable_path='/home/worker/Desktop/driver/chromedriver')

# 如果driver新增了環境變數則不需要設定executable_path
driver = webdriver.Chrome()

# 向一個url發起請求
driver.get("http://www.itcast.cn/")

# 把網頁儲存為圖片,69版本以上的谷歌瀏覽器將無法使用截圖功能
# driver.save_screenshot("itcast.png")

print(driver.title) # 列印頁面的標題

# 退出模擬瀏覽器
driver.quit() # 一定要退出!不退出會有殘留程式!

1.2 phantomjs無介面瀏覽器的執行效果

PhantomJS 是一個基於Webkit的“無介面”(headless)瀏覽器,它會把網站載入到記憶體並執行頁面上的 JavaScript。下載地址:http://phantomjs.org/download.html

from selenium import webdriver 

# 指定driver的絕對路徑
driver = webdriver.PhantomJS(executable_path='/home/worker/Desktop/driver/phantomjs') 
# driver = webdriver.Chrome(executable_path='/home/worker/Desktop/driver/chromedriver')

# 向一個url發起請求
driver.get("http://www.itcast.cn/")

# 把網頁儲存為圖片
driver.save_screenshot("itcast.png")

# 退出模擬瀏覽器
driver.quit() # 一定要退出!不退出會有殘留程式!

1.3 觀察執行效果

  • python程式碼能夠自動的呼叫谷歌瀏覽或phantomjs無介面瀏覽器,控制其自動訪問網站

1.4 無頭瀏覽器與有頭瀏覽器的使用場景

  • 通常在開發過程中我們需要檢視執行過程中的各種情況所以通常使用有頭瀏覽器
  • 在專案完成進行部署的時候,通常平臺採用的系統都是伺服器版的作業系統,伺服器版的作業系統必須使用無頭瀏覽器才能正常執行

2. selenium的作用和工作原理

利用瀏覽器原生的API,封裝成一套更加物件導向的Selenium WebDriver API,直接操作瀏覽器頁面裡的元素,甚至操作瀏覽器本身(截圖,視窗大小,啟動,關閉,安裝外掛,配置證照之類的)

在這裡插入圖片描述

  • webdriver本質是一個web-server,對外提供webapi,其中封裝了瀏覽器的各種功能
  • 不同的瀏覽器使用各自不同的webdriver

知識點:瞭解 selenium的工作原理

3. selenium的安裝以及簡單使用

我們以谷歌瀏覽器的chromedriver為例

3.1 在python虛擬環境中安裝selenium模組

pip/pip3 install selenium

3.2 下載版本符合的webdriver

以chrome谷歌瀏覽器為例

  1. 檢視谷歌瀏覽器的版本

在這裡插入圖片描述

在這裡插入圖片描述

  1. 訪問https://npm.taobao.org/mirrors/chromedriver,點選進入不同版本的chromedriver下載頁面

在這裡插入圖片描述

  1. 點選notes.txt進入版本說明頁面

在這裡插入圖片描述

  1. 檢視chrome和chromedriver匹配的版本

在這裡插入圖片描述

  1. 根據作業系統下載正確版本的chromedriver

在這裡插入圖片描述

  1. 解壓壓縮包後獲取python程式碼可以呼叫的谷歌瀏覽器的webdriver可執行檔案

    • windows為chromedriver.exe

    • linux和macos為chromedriver

  2. chromedriver環境的配置

    • windows環境下需要將 chromedriver.exe 所在的目錄設定為path環境變數中的路徑
    • linux/mac環境下,將 chromedriver 所在的目錄設定到系統的PATH環境值中

知識點:瞭解 selenium以及chromedriver的安裝

4. selenium的簡單使用

接下來我們就通過程式碼來模擬百度搜尋

import time
from selenium import webdriver

# 通過指定chromedriver的路徑來例項化driver物件,chromedriver放在當前目錄。
# driver = webdriver.Chrome(executable_path='./chromedriver')
# chromedriver已經新增環境變數
driver = webdriver.Chrome()

# 控制瀏覽器訪問url地址
driver.get("https://www.baidu.com/")

# 在百度搜尋框中搜尋'python'
driver.find_element_by_id('kw').send_keys('python')
# 點選'百度搜尋'
driver.find_element_by_id('su').click()

time.sleep(6)
# 退出瀏覽器
driver.quit()
  • webdriver.Chrome(executable_path='./chromedriver')中executable引數指定的是下載好的chromedriver檔案的路徑
  • driver.find_element_by_id('kw').send_keys('python')定位id屬性值是’kw’的標籤,並向其中輸入字串’python’
  • driver.find_element_by_id('su').click()定位id屬性值是su的標籤,並點選
    • click函式作用是:觸發標籤的js的click事件

知識點:掌握 標籤物件click點選以及send_keys輸入

二. selenium提取資料

知識點:
  • 瞭解 driver物件的常用屬性和方法
  • 掌握 driver物件定位標籤元素獲取標籤物件的方法
  • 掌握 標籤物件提取文字和屬性值的方法

1. driver物件的常用屬性和方法

在使用selenium過程中,例項化driver物件後,driver物件有一些常用的屬性和方法

  1. driver.page_source 當前標籤頁瀏覽器渲染之後的網頁原始碼
  2. driver.current_url 當前標籤頁的url
  3. driver.close() 關閉當前標籤頁,如果只有一個標籤頁則關閉整個瀏覽器
  4. driver.quit() 關閉瀏覽器
  5. driver.forward() 頁面前進
  6. driver.back() 頁面後退
  7. driver.screen_shot(img_name) 頁面截圖

知識點:瞭解 driver物件的常用屬性和方法

2. driver物件定位標籤元素獲取標籤物件的方法

在selenium中可以通過多種方式來定位標籤,返回標籤元素物件

find_element_by_id 						(返回一個元素)
find_element(s)_by_class_name 			(根據類名獲取元素列表)
find_element(s)_by_name 				(根據標籤的name屬性值返回包含標籤物件元素的列表)
find_element(s)_by_xpath 				(返回一個包含元素的列表)
find_element(s)_by_link_text 			(根據連線文字獲取元素列表)
find_element(s)_by_partial_link_text 	(根據連結包含的文字獲取元素列表)
find_element(s)_by_tag_name 			(根據標籤名獲取元素列表)
find_element(s)_by_css_selector 		(根據css選擇器來獲取元素列表)
  • 注意:
    • find_element和find_elements的區別:
      • 多了個s就返回列表,沒有s就返回匹配到的第一個標籤物件
      • find_element匹配不到就丟擲異常,find_elements匹配不到就返回空列表
    • by_link_text和by_partial_link_tex的區別:全部文字和包含某個文字
    • 以上函式的使用方法
      • driver.find_element_by_id('id_str')

知識點:掌握 driver物件定位標籤元素獲取標籤物件的方法

3. 標籤物件提取文字內容和屬性值

find_element僅僅能夠獲取元素,不能夠直接獲取其中的資料,如果需要獲取資料需要使用以下方法

  • 對元素執行點選操作element.click()

    • 對定位到的標籤物件進行點選操作
  • 向輸入框輸入資料element.send_keys(data)

    • 對定位到的標籤物件輸入資料
  • 獲取文字element.text

    • 通過定位獲取的標籤物件的text屬性,獲取文字內容
  • 獲取屬性值element.get_attribute("屬性名")

    • 通過定位獲取的標籤物件的get_attribute函式,傳入屬性名,來獲取屬性的值

  • 程式碼實現,如下:

    from selenium import webdriver
    
    driver = webdriver.Chrome()
    
    driver.get('http://www.itcast.cn/')
    
    ret = driver.find_elements_by_tag_name('h2')
    print(ret[0].text) # 
    
    ret = driver.find_elements_by_link_text('黑馬程式設計師')
    print(ret[0].get_attribute('href'))
    
    driver.quit()
    

知識點:掌握 元素物件的操作方法

三.selenium的其它使用方法

知識點:
  • 掌握 selenium控制標籤頁的切換
  • 掌握 selenium控制iframe的切換
  • 掌握 利用selenium獲取cookie的方法
  • 掌握 手動實現頁面等待
  • 掌握 selenium控制瀏覽器執行js程式碼的方法
  • 掌握 selenium開啟無介面模式
  • 瞭解 selenium使用代理ip
  • 瞭解 selenium替換user-agent

1. selenium標籤頁的切換

當selenium控制瀏覽器開啟多個標籤頁時,如何控制瀏覽器在不同的標籤頁中進行切換呢?需要我們做以下兩步:

  • 獲取所有標籤頁的視窗控制程式碼

  • 利用視窗控制程式碼字切換到控制程式碼指向的標籤頁

  • 具體的方法

    # 1. 獲取當前所有的標籤頁的控制程式碼構成的列表
    current_windows = driver.window_handles
    
    # 2. 根據標籤頁控制程式碼列表索引下標進行切換
    driver.switch_to.window(current_windows[0])
    
  • 參考程式碼示例:

    import time
    from selenium import webdriver
    
    driver = webdriver.Chrome()
    driver.get("https://www.baidu.com/")
    
    time.sleep(1)
    driver.find_element_by_id('kw').send_keys('python')
    time.sleep(1)
    driver.find_element_by_id('su').click()
    time.sleep(1)
    
    # 通過執行js來新開一個標籤頁
    js = 'window.open("https://www.sogou.com");'
    driver.execute_script(js)
    time.sleep(1)
    
    # 1. 獲取當前所有的視窗
    windows = driver.window_handles
    
    time.sleep(2)
    # 2. 根據視窗索引進行切換
    driver.switch_to.window(windows[0])
    time.sleep(2)
    driver.switch_to.window(windows[1])
    
    time.sleep(6)
    driver.quit()
    

知識點:掌握 selenium控制標籤頁的切換

2. switch_to切換frame標籤

iframe是html中常用的一種技術,即一個頁面中巢狀了另一個網頁,selenium預設是訪問不了frame中的內容的,對應的解決思路是driver.switch_to.frame(frame_element)。接下來我們通過qq郵箱模擬登陸來學習這個知識點
  • 參考程式碼:

    import time
    from selenium import webdriver
    
    driver = webdriver.Chrome()
    
    url = 'https://mail.qq.com/cgi-bin/loginpage'
    driver.get(url)
    time.sleep(2)
    
    login_frame = driver.find_element_by_id('login_frame') # 根據id定位 frame元素
    driver.switch_to.frame(login_frame) # 轉向到該frame中
    
    driver.find_element_by_xpath('//*[@id="u"]').send_keys('1596930226@qq.com')
    time.sleep(2)
    
    driver.find_element_by_xpath('//*[@id="p"]').send_keys('hahamimashicuode')
    time.sleep(2)
    
    driver.find_element_by_xpath('//*[@id="login_button"]').click()
    time.sleep(2)
    
    """操作frame外邊的元素需要切換出去"""
    windows = driver.window_handles
    driver.switch_to.window(windows[0])
    
    content = driver.find_element_by_class_name('login_pictures_title').text
    print(content)
    
    driver.quit()
    
  • 總結:

    • 切換到定位的frame標籤巢狀的頁面中

      • driver.switch_to.frame(通過find_element_by函式定位的frame、iframe標籤物件)
    • 利用切換標籤頁的方式切出frame標籤

      • windows = driver.window_handles
        driver.switch_to.window(windows[0])
        

知識點:掌握 selenium控制frame標籤的切換

3. selenium對cookie的處理

selenium能夠幫助我們處理頁面中的cookie,比如獲取、刪除,接下來我們就學習這部分知識

3.1 獲取cookie

driver.get_cookies()返回列表,其中包含的是完整的cookie資訊!不光有name、value,還有domain等cookie其他維度的資訊。所以如果想要把獲取的cookie資訊和requests模組配合使用的話,需要轉換為name、value作為鍵值對的cookie字典

# 獲取當前標籤頁的全部cookie資訊
print(driver.get_cookies())
# 把cookie轉化為字典
cookies_dict = {cookie[‘name’]: cookie[‘value’] for cookie in driver.get_cookies()}

3.2 刪除cookie

#刪除一條cookie
driver.delete_cookie("CookieName")

# 刪除所有的cookie
driver.delete_all_cookies()

知識點:掌握 利用selenium獲取cookie的方法

4. selenium控制瀏覽器執行js程式碼

selenium可以讓瀏覽器執行我們規定的js程式碼,執行下列程式碼檢視執行效果

import time
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("http://www.itcast.cn/")
time.sleep(1)

js = 'window.scrollTo(0,document.body.scrollHeight)' # js語句
driver.execute_script(js) # 執行js的方法

time.sleep(5)
driver.quit()
  • 執行js的方法:driver.execute_script(js)

知識點:掌握 selenium控制瀏覽器執行js程式碼的方法

5. 頁面等待

頁面在載入的過程中需要花費時間等待網站伺服器的響應,在這個過程中標籤元素有可能還沒有載入出來,是不可見的,如何處理這種情況呢?

  1. 頁面等待分類
  2. 強制等待介紹
  3. 顯式等待介紹
  4. 隱式等待介紹
  5. 手動實現頁面等待

5.1 頁面等待的分類

首先我們就來了解以下selenium頁面等待的分類

  1. 強制等待
  2. 隱式等待
  3. 顯式等待

5.2 強制等待(瞭解)

  • 其實就是time.sleep()
  • 缺點時不智慧,設定的時間太短,元素還沒有載入出來;設定的時間太長,則會浪費時間

5.3 隱式等待

  • 隱式等待針對的是元素定位,隱式等待設定了一個時間,在一段時間內判斷元素是否定位成功,如果完成了,就進行下一步

  • 在設定的時間內沒有定位成功,則會報超時載入

  • 示例程式碼

    from selenium import webdriver
    
    driver = webdriver.Chrome()  
    
    driver.implicitly_wait(10) # 隱式等待,最長等20秒  
    
    driver.get('https://www.baidu.com')
    
    driver.find_element_by_xpath()
    
    

5.4 顯式等待(瞭解)

  • 每經過多少秒就檢視一次等待條件是否達成,如果達成就停止等待,繼續執行後續程式碼

  • 如果沒有達成就繼續等待直到超過規定的時間後,報超時異常

  • 示例程式碼

    from selenium import webdriver  
    from selenium.webdriver.support.wait import WebDriverWait  
    from selenium.webdriver.support import expected_conditions as EC  
    from selenium.webdriver.common.by import By 
    
    driver = webdriver.Chrome()
    
    driver.get('https://www.baidu.com')
    
    # 顯式等待
    WebDriverWait(driver, 20, 0.5).until(
        EC.presence_of_element_located((By.LINK_TEXT, '好123')))  
    # 引數20表示最長等待20秒
    # 引數0.5表示0.5秒檢查一次規定的標籤是否存在
    # EC.presence_of_element_located((By.LINK_TEXT, '好123')) 表示通過連結文字內容定位標籤
    # 每0.5秒一次檢查,通過連結文字內容定位標籤是否存在,如果存在就向下繼續執行;如果不存在,直到20秒上限就丟擲異常
    
    print(driver.find_element_by_link_text('好123').get_attribute('href'))
    driver.quit() 
    

5.5 手動實現頁面等待

在瞭解了隱式等待和顯式等待以及強制等待後,我們發現並沒有一種通用的方法來解決頁面等待的問題,比如“頁面需要滑動才能觸發ajax非同步載入”的場景,那麼接下來我們就以淘寶網首頁為例,手動實現頁面等待

  • 原理:
    • 利用強制等待和顯式等待的思路來手動實現
    • 不停的判斷或有次數限制的判斷某一個標籤物件是否載入完畢(是否存在)
  • 實現程式碼如下:
import time
from selenium import webdriver
driver = webdriver.Chrome('/home/worker/Desktop/driver/chromedriver')

driver.get('https://www.taobao.com/')
time.sleep(1)

# i = 0
# while True:
for i in range(10):
    i += 1
    try:
        time.sleep(3)
        element = driver.find_element_by_xpath('//div[@class="shop-inner"]/h3[1]/a')
        print(element.get_attribute('href'))
        break
    except:
        js = 'window.scrollTo(0, {})'.format(i*500) # js語句
        driver.execute_script(js) # 執行js的方法
driver.quit()

知識點:掌握 手動實現頁面等待

6. selenium開啟無介面模式

絕大多數伺服器是沒有介面的,selenium控制谷歌瀏覽器也是存在無介面模式的,這一小節我們就來學習如何開啟無介面模式(又稱之為無頭模式)

  • 開啟無介面模式的方法
    • 例項化配置物件
      • options = webdriver.ChromeOptions()
    • 配置物件新增開啟無介面模式的命令
      • options.add_argument("--headless")
    • 配置物件新增禁用gpu的命令
      • options.add_argument("--disable-gpu")
    • 例項化帶有配置物件的driver物件
      • driver = webdriver.Chrome(chrome_options=options)
  • 注意:macos中chrome瀏覽器59+版本,Linux中57+版本才能使用無介面模式!
  • 參考程式碼如下:
from selenium import webdriver

options = webdriver.ChromeOptions() # 建立一個配置物件
options.add_argument("--headless") # 開啟無介面模式
options.add_argument("--disable-gpu") # 禁用gpu

# options.set_headles() # 無介面模式的另外一種開啟方式
driver = webdriver.Chrome(chrome_options=options) # 例項化帶有配置的driver物件

driver.get('http://www.itcast.cn')
print(driver.title)
driver.quit()

知識點:掌握 selenium開啟無介面模式

7. selenium使用代理ip

selenium控制瀏覽器也是可以使用代理ip的!

  • 使用代理ip的方法

    • 例項化配置物件
      • options = webdriver.ChromeOptions()
    • 配置物件新增使用代理ip的命令
      • options.add_argument('--proxy-server=http://202.20.16.82:9527')
    • 例項化帶有配置物件的driver物件
      • driver = webdriver.Chrome('./chromedriver', chrome_options=options)
  • 參考程式碼如下:

    from selenium import webdriver
    
    options = webdriver.ChromeOptions() # 建立一個配置物件
    options.add_argument('--proxy-server=http://202.20.16.82:9527') # 使用代理ip
    
    driver = webdriver.Chrome(chrome_options=options) # 例項化帶有配置的driver物件
    
    driver.get('http://www.itcast.cn')
    print(driver.title)
    driver.quit()
    

知識點:瞭解 selenium使用代理ip

8. selenium替換user-agent

selenium控制谷歌瀏覽器時,User-Agent預設是谷歌瀏覽器的,這一小節我們就來學習使用不同的User-Agent

  • 替換user-agent的方法

    • 例項化配置物件
      • options = webdriver.ChromeOptions()
    • 配置物件新增替換UA的命令
      • options.add_argument('--user-agent=Mozilla/5.0 HAHA')
    • 例項化帶有配置物件的driver物件
      • driver = webdriver.Chrome('./chromedriver', chrome_options=options)
  • 參考程式碼如下:

    from selenium import webdriver
    
    options = webdriver.ChromeOptions() # 建立一個配置物件
    options.add_argument('--user-agent=Mozilla/5.0 HAHA') # 替換User-Agent
    
    driver = webdriver.Chrome('./chromedriver', chrome_options=options)
    
    driver.get('http://www.itcast.cn')
    print(driver.title)
    driver.quit()
    

知識點:瞭解 selenium替換user-agent

相關文章