自動化爬蟲selenium
文章目錄
- 自動化爬蟲selenium
- 一:Selenium簡介
- 1:什么是selenium
- 2:安裝準備
- 二:元素定位
- 1:id 定位
- 2:name 定位
- 3:class 定位
- 4:tag 定位
- 5:xpath 定位(最常用)
- 6:css 定位
- 7:link 定位
- 8:partial_link 定位
- 三:瀏覽器控制
- 1:窗口大小
- 2:瀏覽器前進 & 后退
- 3:瀏覽器的刷新
- 4:瀏覽器窗口之間切換
- 5:常用方法
- 四:鼠標操作
- 1:單擊左鍵
- 2:單擊右鍵
- 3:雙擊
- 4:拖動
- 5:鼠標懸停
- 五:鍵盤控制
- 六:設置元素等待
- 1:顯示等待
- 2:隱式等待
- 七:定位一組元素
- 八:切換操作
- 1:窗口切換
- 2:表單切換
- 九:彈窗處理
- 十:百度自動化實例
- 十一:Chrome handless
一:Selenium簡介
1:什么是selenium
Selenium是一個用于Web應用程序測試的工具
Selenium測試直接運行在瀏覽器之中,就像真正的用戶在操作一樣
支持各種的driver(火狐,谷歌,IE,Opera),驅動真實的瀏覽器完成測試
支持無界面瀏覽器操作
可以模擬瀏覽器的功能,自動執行網頁中的JS代碼,實現動態的加載
2:安裝準備
1:安裝selenium
pip install selenium
2:針對不同的瀏覽器,需要安裝不同的驅動,常見的有谷歌和_Edge_
- Google:(https://chromedriver.storage.googleapis.com/index.html)
- Edge:(https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/)
3:查看瀏覽器對應的版本,決定下哪個版本的驅動(設置 -> 關于 -> 得到版本)
- google查看方法
- edge查看方法
4:復制對應的解壓文件到python的文件夾和瀏覽器的文件夾中
5:編寫測試代碼
from selenium import webdriverif __name__ == '__main__':driver = webdriver.Chrome(r'E:\centbrowser\chromedriver.exe')driver.get('https://www.csdn.net/')
?? 如果打開主頁后自動關閉,可以設置為不立刻關閉
from selenium import webdriverif __name__ == '__main__':# 不自動關閉瀏覽器option = webdriver.ChromeOptions()option.add_experimental_option("detach", True)driver = webdriver.Chrome(r'E:\centbrowser\chromedriver.exe', chrome_options=option)driver.get('https://www.csdn.net/')
二:元素定位
1:id 定位
- 標簽的
id
具有唯一性,就像人的身份證 - 可以通過
id
定位到它,由于id
的唯一性,我們可以不用管其他的標簽的內容。
driver.find_element_by_id("2cc5a005-9926-46fb-811d-ef323d660402")
2:name 定位
<meta name="keywords" content="CSDN博客,CSDN學院,CSDN論壇,CSDN直播">
name
指定標簽的名稱,在頁面中可以不唯一- 可以使用
find_element_by_name
定位到meta
標簽。
driver.find_element_by_name("keywords")
3:class 定位
<div class="toolbar-search-container">
class
指定標簽的類名,在頁面中可以不唯一- 可以使用
find_element_by_class_name
定位到上面_html_片段的div
標簽
driver.find_element_by_class_name("toolbar-search-container")
4:tag 定位
<div class="toolbar-search-container">
- 每個
tag
往往用來定義一類功能,通過tag
來識別某個元素的成功率很低,每個頁面一般都用很多相同的tag
- 我們可以使用
find_element_by_class_name
定位
driver.find_element_by_tag_name("div")
5:xpath 定位(最常用)
# 絕對路徑(層級關系)定位
driver.find_element_by_xpath("/html/body/div/div/div/div[2]/div/div/input[1]")
# 利用元素屬性定位
driver.find_element_by_xpath("//*[@id='toolbar-search-input']"))
# 層級+元素屬性定位
driver.find_element_by_xpath("//div[@id='csdn-toolbar']/div/div/div[2]/div/div/input[1]")
# 邏輯運算符定位
driver.find_element_by_xpath("//*[@id='toolbar-search-input' and @autocomplete='off']")
F12 -> 右鍵html元素內容 -> copy -> copy full xpath
6:css 定位
CSS
使用選擇器來為頁面元素綁定屬性,它可以較為靈活的選擇控件的任意屬性- 一般定位速度比
xpath
要快,但使用起來略有難度
driver.find_element_by_css_selector('#toolbar-search-input')
driver.find_element_by_css_selector('html>body>div>div>div>div>div>div>input')
7:link 定位
<div class="practice-box" data-v-04f46969="">加入!每日一練</div>
link
專門用來定位文本鏈接- 使用
find_element_by_link_text
并指明標簽內全部文本即可定位
driver.find_element_by_link_text("加入!每日一練")
8:partial_link 定位
- 就是“部分鏈接”,對于有些文本很長,這時候就可以只指定部分文本即可定位,同樣使用剛才的例子
# 上面的例子使用部分鏈接匹配
driver.find_element_by_partial_link_text("加入")
三:瀏覽器控制
1:窗口大小
webdriver
提供 set_window_size()
方法來修改瀏覽器窗口的大小。
from selenium import webdriver# Chrome瀏覽器
driver = webdriver.Chrome()
driver.get('https://www.csdn.net/')# 設置瀏覽器瀏覽器的寬高為:600x800
driver.set_window_size(600, 800)
也可以使用 maximize_window()
方法可以實現瀏覽器全屏顯示
from selenium import webdriver# Chrome瀏覽器
driver = webdriver.Chrome()
driver.get('https://www.csdn.net/')# 設置瀏覽器瀏覽器的寬高為:600x800
driver.maximize_window()
2:瀏覽器前進 & 后退
webdriver
提供 back
和 forward
方法來實現頁面的后退與前進
from selenium import webdriver
from time import sleepdriver = webdriver.Chrome()# 訪問CSDN首頁
driver.get('https://www.csdn.net/')sleep(2)#訪問CSDN個人主頁
driver.get('https://blog.csdn.net/qq_43965708')sleep(2)#返回(后退)到CSDN首頁
driver.back()sleep(2)#前進到個人主頁
driver.forward()
第二次 get()
打開新頁面時,會在原來的頁面打開,而不是在新標簽中打開。
如果想的話也可以在新的標簽頁中打開新的鏈接,但需要更改一下代碼,執行 js
語句來打開新的標簽
# 在原頁面打開
driver.get('https://blog.csdn.net/qq_43965708')# 新標簽中打開
js = "window.open('https://blog.csdn.net/qq_43965708')"
driver.execute_script(js)
3:瀏覽器的刷新
# 刷新頁面
driver.refresh()
4:瀏覽器窗口之間切換
我們先獲取當前各個窗口的句柄,這些信息的保存順序是按照時間來的
最新打開的窗口放在數組的末尾,這時我們就可以定位到最新打開的那個窗口了
# 獲取打開的多個窗口句柄
windows = driver.window_handles
# 切換到當前最新打開的窗口(獲取句柄數組中的最后一個)
driver.switch_to.window(windows[-1])
5:常用方法
模擬操作
if __name__ == '__main__':driver = webdriver.Chrome(r'E:\centbrowser\chromedriver.exe')driver.get('https://www.csdn.net/')sleep(2)# 定位搜索輸入框text_label = driver.find_element_by_xpath('//*[@id="toolbar-search-input"]')# 在搜索框中輸入 text_label.send_keys('是小崔啊')sleep(2)button = driver.find_element_by_xpath('//*[@id="toolbar-search-button"]/span')button.click()
四:鼠標操作
1:單擊左鍵
模擬完成單擊鼠標左鍵的操作,一般點擊進入子頁面等會用到,左鍵不需要用到 ActionChains
。
# 定位搜索按鈕
button = driver.find_element_by_xpath('//*[@id="toolbar-search-button"]/span')
# 執行單擊操作
button.click()
2:單擊右鍵
單擊右鍵需要使用 ActionChains
from selenium.webdriver.common.action_chains import ActionChains# 定位搜索按鈕
button = driver.find_element_by_xpath('//*[@id="toolbar-search-button"]/span')
# 右鍵搜索按鈕
ActionChains(driver).context_click(button).perform()
3:雙擊
需要使用 ActionChains
# 定位搜索按鈕
button = driver.find_element_by_xpath('//*[@id="toolbar-search-button"]/span')
# 執行雙擊動作
ActionChains(driver).double_click(button).perform()
4:拖動
模擬鼠標拖動操作,該操作有兩個必要參數,
- source:鼠標拖動的元素
- target:鼠標拖至并釋放的目標元素
# 定位要拖動的元素
source = driver.find_element_by_xpath('xxx')
# 定位目標元素
target = driver.find_element_by_xpath('xxx')
# 執行拖動動作
ActionChains(driver).drag_and_drop(source, target).perform()
5:鼠標懸停
模擬懸停的作用一般是為了顯示隱藏的下拉框
# 定位收藏欄
collect = driver.find_element_by_xpath('xxx')# 懸停至收藏標簽處
ActionChains(driver).move_to_element(collect).perform()
五:鍵盤控制
webdriver
中 Keys
類幾乎提供了鍵盤上的所有按鍵方法,我們可以使用 send_keys + Keys
實現輸出鍵盤上的組合按鍵
from selenium.webdriver.common.keys import Keys# 定位輸入框并輸入文本
driver.find_element_by_id('xxx').send_keys('是小崔啊')# 模擬回車鍵進行跳轉(輸入內容后)
driver.find_element_by_id('xxx').send_keys(Keys.ENTER)# 使用 Backspace 來刪除一個字符
driver.find_element_by_id('xxx').send_keys(Keys.BACK_SPACE)# Ctrl + A 全選輸入框中內容
driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'a')# Ctrl + C 復制輸入框中內容
driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'c')# Ctrl + V 粘貼輸入框中內容
driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'v')
六:設置元素等待
很多頁面都使用 ajax
技術,頁面的元素不是同時被加載出來的,為了防止定位這些尚在加載的元素報錯。
可以設置元素等來增加腳本的穩定性。webdriver
中的等待分為 顯式等待 和 隱式等待。
1:顯示等待
顯式等待:設置一個超時時間,每個一段時間就去檢測一次該元素是否存在:
- 如果存在則執行后續內容
- 如果超過最大時間(超時時間)則拋出超時異常(
TimeoutException
)。 - 顯示等待需要使用
WebDriverWait
,同時配合until
或not until
。
'''
driver:瀏覽器驅動
timeout:超時時間,單位秒
poll_frequency:每次檢測的間隔時間,默認為0.5秒
ignored_exceptions:指定忽略的異常如果在調用 until 或 until_not 的過程中拋出指定忽略的異常,則不中斷代碼默認忽略的只有 NoSuchElementException
'''
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
'''
method:指定預期條件的判斷方法,在等待期間,每隔一段時間調用該方法,判斷元素是否存在,直到元素出現。
until_not 正好相反,當元素消失或指定條件不成立,則繼續執行后續代碼
message: 如果超時,拋出 TimeoutException ,并顯示 message 中的內容
method 中的預期條件判斷方法是由 expected_conditions 提供,下面列舉常用方法。
'''
until(method, message='xxx')
until_not(method, message='xxx')
from selenium.webdriver.common.by import By
from selenium import webdriverdriver = webdriver.Chrome()
locator = (By.ID, 'kw')
element = driver.find_element_by_id('kw')
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import Bydriver = webdriver.Chrome()
element = WebDriverWait(driver, 5, 0.5).until(EC.presence_of_element_located((By.ID, 'kw')),message='超時啦!')
2:隱式等待
用 implicitly_wait()
來實現隱式等待,使用難度相對于顯式等待要簡單很多。
示例:打開個人主頁,設置一個隱式等待時間 5s,通過 id
定位一個不存在的元素,最后打印 拋出的異常 與 運行時間。
from selenium import webdriver
from time import timedriver = webdriver.Chrome()
driver.get('https://blog.csdn.net/qq_43965708')start = time()
driver.implicitly_wait(5)
try:# 觸發隱式等待,在輪詢檢查 5s 后仍然沒有定位到元素,拋出異常driver.find_element_by_id('kw')
except Exception as e:print(e)print(f'耗時:{time()-start}')
七:定位一組元素
將元素定位中的element -> elements
find_elements_by_id()
find_elements_by_name()
find_elements_by_class_name()
find_elements_by_tag_name()
find_elements_by_xpath()
find_elements_by_css_selector()
find_elements_by_link_text()
find_elements_by_partial_link_text()
from selenium import webdriver# 設置無頭瀏覽器
option = webdriver.ChromeOptions()
option.add_argument('--headless')driver = webdriver.Chrome(options=option)
driver.get('https://blog.csdn.net/')p_list = driver.find_elements_by_xpath("//p[@class='name']")
name = [p.text for p in p_list]
八:切換操作
1:窗口切換
窗口切換需要使用頁面句柄和 switch_to.windows()
方法。
from selenium import webdriverhandles = []
driver = webdriver.Chrome()
driver.get('https://blog.csdn.net/')
# 設置隱式等待
driver.implicitly_wait(3)
# 獲取當前窗口的句柄
handles.append(driver.current_window_handle)
# 點擊 python,進入分類頁面
driver.find_element_by_xpath('//*[@id="mainContent"]/aside/div[1]/div').click()
# 獲取當前窗口的句柄
handles.append(driver.current_window_handle)print(handles)
# 獲取當前所有窗口的句柄
print(driver.window_handles)
可以看到第一個列表 handle
是相同的,說明 selenium
實際操作的還是 _CSDN_首頁 ,并未切換到新頁面。
下面使用 switch_to.windows()
進行切換。
from selenium import webdriverhandles = []
driver = webdriver.Chrome()
driver.get('https://blog.csdn.net/')
# 設置隱式等待
driver.implicitly_wait(3)
# 獲取當前窗口的句柄
handles.append(driver.current_window_handle)# 點擊 python,進入分類頁面
driver.find_element_by_xpath('//*[@id="mainContent"]/aside/div[1]/div').click()
# 切換窗口
driver.switch_to.window(driver.window_handles[-1])
# 獲取當前窗口的句柄
handles.append(driver.current_window_handle)print(handles)
print(driver.window_handles)
2:表單切換
- 很多頁面也會用帶 frame or iframe 表單嵌套,對于這種內嵌的頁面 selenium 是無法直接定位的,需要使用
switch_to.frame()
方法將當前操作的對象切換成 frame or iframe 內嵌的頁面。 switch_to.frame()
默認可以用的 id 或 name 屬性直接定位,但如果 iframe 沒有 id 或 name ,這時就需要使用 xpath 進行定位。下面先寫一個包含 iframe 的頁面做測試用
舉個例子
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>div p {color: red;animation: change 2s infinite;}@keyframes change {from {color: red;}to {color: blue;}}</style>
</head><body>
<div><p>CSDN:是小崔啊</p>
</div>
<!-- 注意這里 -->
<iframe src="https://blog.csdn.net/qq_43350524" width="400" height="200"></iframe>
</body>
</html>
現在我們定位紅框中的 CSDN 按鈕,可以跳轉到 CSDN 首頁
from selenium import webdriver
from pathlib import Pathdriver = webdriver.Chrome()
# 讀取本地html文件
driver.get('file:///' + str(Path(Path.cwd(), 'iframe測試.html')))# 1.通過id定位
driver.switch_to.frame('CSDN_info')
# 2.通過name定位
# driver.switch_to.frame('是小崔啊')
# 通過xpath定位
# 3.iframe_label = driver.find_element_by_xpath('/html/body/iframe')
# driver.switch_to.frame(iframe_label)driver.find_element_by_xpath('//*[@id="csdn-toolbar"]/div/div/div[1]/div/a/img').click()
九:彈窗處理
JavaScript
有三種彈窗 alert
(確認)、confirm
(確認、取消)、prompt
(文本框、確認、取消)。
處理方式:
- 先定位(
switch_to.alert
自動獲取當前彈窗) - 再使用
text
、accept
、dismiss
、send_keys
等方法進行操作
<!DOCTYPE html>
<html lang="en"><head>
</head><body><button id="alert">alert</button><button id="confirm">confirm</button><button id="prompt">prompt</button><script type="text/javascript">const dom1 = document.getElementById("alert");dom1.addEventListener('click', function(){alert("alert hello")});const dom2 = document.getElementById("confirm");dom2.addEventListener('click', function(){confirm("confirm hello")});const dom3 = document.getElementById("prompt");dom3.addEventListener('click', function(){prompt("prompt hello")});</script>
</body>
</html>
from selenium import webdriver
from pathlib import Path
from time import sleepdriver = webdriver.Firefox()
driver.get('file:///' + str(Path(Path.cwd(), '彈窗.html')))sleep(2)# 點擊alert按鈕
driver.find_element_by_xpath('//*[@id="alert"]').click()
sleep(1)
alert = driver.switch_to.alert
# 打印alert彈窗的文本
print(alert.text)
# 確認
alert.accept()sleep(2)# 點擊confirm按鈕
driver.find_element_by_xpath('//*[@id="confirm"]').click()
sleep(1)
confirm = driver.switch_to.alert
print(confirm.text)
# 取消
confirm.dismiss()sleep(2)# 點擊confirm按鈕
driver.find_element_by_xpath('//*[@id="prompt"]').click()
sleep(1)
prompt = driver.switch_to.alert
print(prompt.text)
# 向prompt的輸入框中傳入文本
prompt.send_keys("Dream丶Killer")
sleep(2)
prompt.accept()'''輸出
alert hello
confirm hello
prompt hello
'''
十:百度自動化實例
import time
from selenium import webdriverpath = r"E:\centbrowser\chromedriver.exe"
browser = webdriver.Chrome(path)url = "https://www.baidu.com"
browser.get(url)
time.sleep(2)# 獲取文本框對象
input_object = browser.find_element_by_id("kw")
input_object.send_keys("周杰倫")
time.sleep(2)# 獲取按鈕并點擊
button_object = browser.find_element_by_id("su")
button_object.click()
time.sleep(2)# 滑到底部
js_bottom = "document.documentElement.scrollTop=100000"
browser.execute_script(js_bottom)
time.sleep(2)# 跳轉到下一頁
next_object = browser.find_element_by_xpath("//a[@class='n']")
next_object.click()
time.sleep(2)# 回退
browser.back()
time.sleep(3)# 退出
browser.quit()
十一:Chrome handless
Headless 模式是指瀏覽器在沒有圖形用戶界面(GUI)的情況下運行,Selenium 支持 Chrome 和 Firefox 等主流瀏覽器的 Headless 模式,非常適合服務器環境和自動化測試/爬蟲場景。
from selenium import webdriver
from selenium.webdriver.chrome.options import Optionschrome_options = Options()
chrome_options.add_argument('--headless') # 啟用無頭模式
chrome_options.add_argument('--disable-gpu') # 禁用GPU加速(舊版可能需要)driver = webdriver.Chrome(options=chrome_options)
driver.get("https://example.com")
print(driver.title)
driver.quit()
高級配置選項
chrome_options.add_argument('--no-sandbox') # 禁用沙盒
chrome_options.add_argument('--disable-dev-shm-usage') # 解決/dev/shm內存不足問題
chrome_options.add_argument('--window-size=1920,1080') # 設置窗口大小
chrome_options.add_argument('--blink-settings=imagesEnabled=false') # 禁用圖片加載
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Optionsdef share_browser():chrome_options = Options()chrome_options.add_argument("--headless")chrome_options.add_argument("--disable-gpu")# chrome瀏覽器的文件路徑path = r'E:\centbrowser\chrome.exe'chrome_options.binary_location = pathreturn webdriver.Chrome(chrome_options=chrome_options)if __name__ == '__main__':browser = share_browser()# 剩下的部分就一樣了url = "https://www.baidu.com"browser.get(url)browser.save_screenshot("baidu.png")time.sleep(2)browser.quit()