python网络爬虫系列(七)——selenium的介绍 selenium定位获取标签对象并提取数据 selenium的其它使用方法
一、selenium的介紹
知識點:
- 了解 selenium的工作原理
- 了解 selenium以及chromedriver的安裝
- 掌握 標簽對象click點擊以及send_keys輸入
1. selenium運行效果展示
Selenium是一個Web的自動化測試工具,最初是為網(wǎng)站自動化測試而開發(fā)的,Selenium 可以直接調(diào)用瀏覽器,它支持所有主流的瀏覽器(包括PhantomJS這些無界面的瀏覽器),可以接收指令,讓瀏覽器自動加載頁面,獲取需要的數(shù)據(jù),甚至頁面截屏等。我們可以使用selenium很容易完成之前編寫的爬蟲,接下來我們就來看一下selenium的運行效果
1.1 chrome瀏覽器的運行效果
在下載好chromedriver以及安裝好selenium模塊后,執(zhí)行下列代碼并觀察運行的過程
from selenium import webdriver # 如果driver沒有添加到了環(huán)境變量,則需要將driver的絕對路徑賦值給executable_path參數(shù) # driver = webdriver.Chrome(executable_path='/home/worker/Desktop/driver/chromedriver')# 如果driver添加了環(huán)境變量則不需要設(shè)置executable_path driver = webdriver.Chrome()# 向一個url發(fā)起請求 driver.get("http://www.itcast.cn/")# 把網(wǎng)頁保存為圖片,69版本以上的谷歌瀏覽器將無法使用截圖功能 # driver.save_screenshot("itcast.png")print(driver.title) # 打印頁面的標題# 退出模擬瀏覽器 driver.quit() # 一定要退出!不退出會有殘留進程!1.2 phantomjs無界面瀏覽器的運行效果
PhantomJS 是一個基于Webkit的“無界面”(headless)瀏覽器,它會把網(wǎng)站加載到內(nèi)存并執(zhí)行頁面上的 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發(fā)起請求 driver.get("http://www.itcast.cn/")# 把網(wǎng)頁保存為圖片 driver.save_screenshot("itcast.png")# 退出模擬瀏覽器 driver.quit() # 一定要退出!不退出會有殘留進程!1.3 觀察運行效果
- python代碼能夠自動的調(diào)用谷歌瀏覽或phantomjs無界面瀏覽器,控制其自動訪問網(wǎng)站
1.4 無頭瀏覽器與有頭瀏覽器的使用場景
- 通常在開發(fā)過程中我們需要查看運行過程中的各種情況所以通常使用有頭瀏覽器
- 在項目完成進行部署的時候,通常平臺采用的系統(tǒng)都是服務(wù)器版的操作系統(tǒng),服務(wù)器版的操作系統(tǒng)必須使用無頭瀏覽器才能正常運行
2. selenium的作用和工作原理
利用瀏覽器原生的API,封裝成一套更加面向?qū)ο蟮腟elenium WebDriver API,直接操作瀏覽器頁面里的元素,甚至操作瀏覽器本身(截屏,窗口大小,啟動,關(guān)閉,安裝插件,配置證書之類的)
- webdriver本質(zhì)是一個web-server,對外提供webapi,其中封裝了瀏覽器的各種功能
- 不同的瀏覽器使用各自不同的webdriver
知識點:了解 selenium的工作原理
3. selenium的安裝以及簡單使用
我們以谷歌瀏覽器的chromedriver為例
3.1 在python虛擬環(huán)境中安裝selenium模塊
pip/pip3 install selenium
3.2 下載版本符合的webdriver
以chrome谷歌瀏覽器為例
查看谷歌瀏覽器的版本
訪問https://npm.taobao.org/mirrors/chromedriver,點擊進入不同版本的chromedriver下載頁面
點擊notes.txt進入版本說明頁面
查看chrome和chromedriver匹配的版本
根據(jù)操作系統(tǒng)下載正確版本的chromedriver
解壓壓縮包后獲取python代碼可以調(diào)用的谷歌瀏覽器的webdriver可執(zhí)行文件
-
windows為chromedriver.exe
-
linux和macos為chromedriver
chromedriver環(huán)境的配置
- windows環(huán)境下需要將 chromedriver.exe 所在的目錄設(shè)置為path環(huán)境變量中的路徑
- linux/mac環(huán)境下,將 chromedriver 所在的目錄設(shè)置到系統(tǒng)的PATH環(huán)境值中
知識點:了解 selenium以及chromedriver的安裝
4. selenium的簡單使用
接下來我們就通過代碼來模擬百度搜索
import time from selenium import webdriver# 通過指定chromedriver的路徑來實例化driver對象,chromedriver放在當(dāng)前目錄。 # driver = webdriver.Chrome(executable_path='./chromedriver') # chromedriver已經(jīng)添加環(huán)境變量 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參數(shù)指定的是下載好的chromedriver文件的路徑
- driver.find_element_by_id('kw').send_keys('python')定位id屬性值是’kw’的標簽,并向其中輸入字符串’python’
- driver.find_element_by_id('su').click()定位id屬性值是su的標簽,并點擊
- click函數(shù)作用是:觸發(fā)標簽的js的click事件
知識點:掌握 標簽對象click點擊以及send_keys輸入
值是’kw’的標簽,并向其中輸入字符串’python’
- driver.find_element_by_id('su').click()定位id屬性值是su的標簽,并點擊
- click函數(shù)作用是:觸發(fā)標簽的js的click事件
知識點:掌握 標簽對象click點擊以及send_keys輸入
二、selenium提取數(shù)據(jù)
知識點:
- 了解 driver對象的常用屬性和方法
- 掌握 driver對象定位標簽元素獲取標簽對象的方法
- 掌握 標簽對象提取文本和屬性值的方法
1. driver對象的常用屬性和方法
在使用selenium過程中,實例化driver對象后,driver對象有一些常用的屬性和方法
知識點:了解 driver對象的常用屬性和方法
2. driver對象定位標簽元素獲取標簽對象的方法
在selenium中可以通過多種方式來定位標簽,返回標簽元素對象
find_element_by_id (返回一個元素) find_element(s)_by_class_name (根據(jù)類名獲取元素列表) find_element(s)_by_name (根據(jù)標簽的name屬性值返回包含標簽對象元素的列表) find_element(s)_by_xpath (返回一個包含元素的列表) find_element(s)_by_link_text (根據(jù)連接文本獲取元素列表) find_element(s)_by_partial_link_text (根據(jù)鏈接包含的文本獲取元素列表) find_element(s)_by_tag_name (根據(jù)標簽名獲取元素列表) find_element(s)_by_css_selector (根據(jù)css選擇器來獲取元素列表)- 注意:
- find_element和find_elements的區(qū)別:
- 多了個s就返回列表,沒有s就返回匹配到的第一個標簽對象
- find_element匹配不到就拋出異常,find_elements匹配不到就返回空列表
- by_link_text和by_partial_link_tex的區(qū)別:全部文本和包含某個文本
- 以上函數(shù)的使用方法
- driver.find_element_by_id('id_str')
- find_element和find_elements的區(qū)別:
代碼演示:
from selenium import webdriverurl = "http://www.baidu.com"driver = webdriver.Chrome()driver.get(url)# 通過xpath進行元素定位 # driver.find_element_by_xpath('//*[@id="kw"]').send_keys('python3')# 通過css選擇器進行元素定位 # driver.find_element_by_css_selector('#kw').send_keys('python3')# 通過name屬性值進行元素定位 # driver.find_element_by_name('wd').send_keys('python3')# 通過class屬性值進行元素定位 # driver.find_element_by_class_name('s_ipt').send_keys('python3')# 通過鏈接文本進行元素定位 # driver.find_element_by_link_text('貼吧').click() # driver.find_element_by_partial_link_text('貼').click()# 目標元素在當(dāng)前HTML中是唯一標簽的時候或者是眾多定位出來的標簽中的第一個的時候才能使用 print(driver.find_element_by_tag_name('title'))# driver.find_element_by_id('su').click()知識點:掌握 driver對象定位標簽元素獲取標簽對象的方法
3. 標簽對象提取文本內(nèi)容和屬性值
find_element僅僅能夠獲取元素,不能夠直接獲取其中的數(shù)據(jù),如果需要獲取數(shù)據(jù)需要使用以下方法
-
對元素執(zhí)行點擊操作element.click()
- 對定位到的標簽對象進行點擊操作
-
向輸入框輸入數(shù)據(jù)element.send_keys(data)
- 對定位到的標簽對象輸入數(shù)據(jù)
-
獲取文本element.text
- 通過定位獲取的標簽對象的text屬性,獲取文本內(nèi)容
-
獲取屬性值element.get_attribute("屬性名")
- 通過定位獲取的標簽對象的get_attribute函數(shù),傳入屬性名,來獲取屬性的值
?
-
代碼實現(xiàn),如下:
from selenium import webdriverdriver = 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的方法
- 掌握 手動實現(xiàn)頁面等待
- 掌握 selenium控制瀏覽器執(zhí)行js代碼的方法
- 掌握 selenium開啟無界面模式
- 了解 selenium使用代理ip
- 了解 selenium替換user-agent
1. selenium標簽頁的切換
當(dāng)selenium控制瀏覽器打開多個標簽頁時,如何控制瀏覽器在不同的標簽頁中進行切換呢?需要我們做以下兩步:
-
獲取所有標簽頁的窗口句柄
-
利用窗口句柄字切換到句柄指向的標簽頁
- 這里的窗口句柄是指:指向標簽頁對象的標識
- 關(guān)于句柄請課后了解更多,本小節(jié)不做展開
-
具體的方法
# 1. 獲取當(dāng)前所有的標簽頁的句柄構(gòu)成的列表 current_windows = driver.window_handles# 2. 根據(jù)標簽頁句柄列表索引下標進行切換 driver.switch_to.window(current_windows[0]) -
myCode
代碼演示:
-
參考代碼示例:
import time from selenium import webdriverdriver = 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)# 通過執(zhí)行js來新開一個標簽頁 js = 'window.open("https://www.sogou.com");' driver.execute_script(js) time.sleep(1)# 1. 獲取當(dāng)前所有的窗口 windows = driver.window_handlestime.sleep(2) # 2. 根據(jù)窗口索引進行切換 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中常用的一種技術(shù),即一個頁面中嵌套了另一個網(wǎng)頁,selenium默認是訪問不了frame中的內(nèi)容的,對應(yīng)的解決思路是driver.switch_to.frame(frame_element)。接下來我們通過qq郵箱模擬登陸來學(xué)習(xí)這個知識點
-
參考代碼:
import time from selenium import webdriverdriver = 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') # 根據(jù)id定位 frame元素 driver.switch_to.frame(login_frame) # 轉(zhuǎn)向到該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() -
myCode
-
總結(jié):
-
切換到定位的frame標簽嵌套的頁面中
- driver.switch_to.frame(通過find_element_by函數(shù)定位的frame、iframe標簽對象)
-
利用切換標簽頁的方式切出frame標簽
- windows = driver.window_handles driver.switch_to.window(windows[0])
-
知識點:掌握 selenium控制frame標簽的切換
3. selenium對cookie的處理
selenium能夠幫助我們處理頁面中的cookie,比如獲取、刪除,接下來我們就學(xué)習(xí)這部分知識
3.1 獲取cookie
driver.get_cookies()返回列表,其中包含的是完整的cookie信息!不光有name、value,還有domain等cookie其他維度的信息。所以如果想要把獲取的cookie信息和requests模塊配合使用的話,需要轉(zhuǎn)換為name、value作為鍵值對的cookie字典
# 獲取當(dāng)前標簽頁的全部cookie信息 print(driver.get_cookies()) # 把cookie轉(zhuǎn)化為字典 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()from selenium import webdriverurl = "http://www.baidu.com"driver = webdriver.Chrome()driver.get(url)print(driver.get_cookies()) print("——————————————————————————————————————") # cookies = {} # for data in driver.get_cookies(): # cookies[data['name']] = data['value']cookies = {data['name']:data['value']for data in driver.get_cookies()}print(cookies)
知識點:掌握 利用selenium獲取cookie的方法
4. selenium控制瀏覽器執(zhí)行js代碼
selenium可以讓瀏覽器執(zhí)行我們規(guī)定的js代碼,運行下列代碼查看運行效果
import time from selenium import webdriverdriver = webdriver.Chrome() driver.get("http://www.itcast.cn/") time.sleep(1)js = 'window.scrollTo(0,document.body.scrollHeight)' # js語句 driver.execute_script(js) # 執(zhí)行js的方法time.sleep(5) driver.quit()- 執(zhí)行js的方法:driver.execute_script(js)
知識點:掌握 selenium控制瀏覽器執(zhí)行js代碼的方法
5. 頁面等待
頁面在加載的過程中需要花費時間等待網(wǎng)站服務(wù)器的響應(yīng),在這個過程中標簽元素有可能還沒有加載出來,是不可見的,如何處理這種情況呢?
5.1 頁面等待的分類
首先我們就來了解以下selenium頁面等待的分類
5.2 強制等待(了解)
- 其實就是time.sleep()
- 缺點時不智能,設(shè)置的時間太短,元素還沒有加載出來;設(shè)置的時間太長,則會浪費時間
5.3 隱式等待
-
隱式等待針對的是元素定位,隱式等待設(shè)置了一個時間,在一段時間內(nèi)判斷元素是否定位成功,如果完成了,就進行下一步
-
在設(shè)置的時間內(nèi)沒有定位成功,則會報超時加載
-
示例代碼
from selenium import webdriverdriver = webdriver.Chrome() driver.implicitly_wait(10) # 隱式等待,最長等20秒 driver.get('https://www.baidu.com')driver.find_element_by_xpath()
5.4 顯式等待(了解)
-
每經(jīng)過多少秒就查看一次等待條件是否達成,如果達成就停止等待,繼續(xù)執(zhí)行后續(xù)代碼
-
如果沒有達成就繼續(xù)等待直到超過規(guī)定的時間后,報超時異常
-
示例代碼
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'))) # 參數(shù)20表示最長等待20秒 # 參數(shù)0.5表示0.5秒檢查一次規(guī)定的標簽是否存在 # EC.presence_of_element_located((By.LINK_TEXT, '好123')) 表示通過鏈接文本內(nèi)容定位標簽 # 每0.5秒一次檢查,通過鏈接文本內(nèi)容定位標簽是否存在,如果存在就向下繼續(xù)執(zhí)行;如果不存在,直到20秒上限就拋出異常print(driver.find_element_by_link_text('好123').get_attribute('href')) driver.quit()
5.5 手動實現(xiàn)頁面等待
在了解了隱式等待和顯式等待以及強制等待后,我們發(fā)現(xiàn)并沒有一種通用的方法來解決頁面等待的問題,比如“頁面需要滑動才能觸發(fā)ajax異步加載”的場景,那么接下來我們就以淘寶網(wǎng)首頁為例,手動實現(xiàn)頁面等待
- 原理:
- 利用強制等待和顯式等待的思路來手動實現(xiàn)
- 不停的判斷或有次數(shù)限制的判斷某一個標簽對象是否加載完畢(是否存在)
- 實現(xiàn)代碼如下:
知識點:掌握 手動實現(xiàn)頁面等待
6. selenium開啟無界面模式
絕大多數(shù)服務(wù)器是沒有界面的,selenium控制谷歌瀏覽器也是存在無界面模式的,這一小節(jié)我們就來學(xué)習(xí)如何開啟無界面模式(又稱之為無頭模式)
- 開啟無界面模式的方法
- 實例化配置對象
- 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+版本才能使用無界面模式!
- 參考代碼如下:
知識點:掌握 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 webdriveroptions = webdriver.ChromeOptions() # 創(chuàng)建一個配置對象 options.add_argument('--proxy-server=http://202.20.16.82:9527') # 使用代理ipdriver = 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默認是谷歌瀏覽器的,這一小節(jié)我們就來學(xué)習(xí)使用不同的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 webdriveroptions = webdriver.ChromeOptions() # 創(chuàng)建一個配置對象 options.add_argument('--user-agent=Mozilla/5.0 HAHA') # 替換User-Agentdriver = webdriver.Chrome('./chromedriver', chrome_options=options)driver.get('http://www.itcast.cn') print(driver.title) driver.quit()
知識點:了解 selenium替換user-agent
from selenium import webdriverurl = "http://www.baidu.com"# 創(chuàng)建配置對象 opt = webdriver.ChromeOptions()# 添加配置參數(shù) # 設(shè)置瀏覽器為無頭模式 # opt.add_argument('--headless') # opt.add_argument('--disable-gpu') # 更換IP代理必須重新啟動瀏覽器 opt.add_argument('--proxy-server=http://163.125.16.198:8888')# 更換User-agent opt.add_argument('--User-agent=Mozilla/5.0 python37')# 創(chuàng)建瀏覽器對象的時候添加配置對象 driver = webdriver.Chrome(options=opt)driver.get(url)# driver.save_screenshot('baidu_d.png')
綜合案例:爬取斗魚直播間數(shù)據(jù)
from selenium import webdriver import timeclass Douyu(object):def __init__(self):self.url = 'https://www.douyu.com/directory/all'self.driver = webdriver.Chrome()def parse_data(self):time.sleep(5)room_list = self.driver.find_elements_by_xpath('//*[@id="listAll"]/section[2]/div[2]/ul/li/div')print(len(room_list))data_list = []# 遍歷房間列表,從每一個房間節(jié)點中獲取數(shù)據(jù)for room in room_list:temp={}temp['title'] = room.find_element_by_xpath('./a[1]/div[2]/div[1]/h3').texttemp['type'] = room.find_element_by_xpath('./a[1]/div[2]/div[1]/span').texttemp['owner'] = room.find_element_by_xpath('./a[1]/div[2]/div[2]/h2').texttemp['num'] = room.find_element_by_xpath('./a[1]/div[2]/div[2]/span').texttemp['pic'] = room.find_element_by_xpath('./a[1]/div[1]/div[1]/img').get_attribute('src')# print(temp)data_list.append(temp)return data_listdef save_data(self,data_list):for data in data_list:print(data)def run(self):# url# driver# getself.driver.get(self.url)while True:# parsedata_list = self.parse_data()# saveself.save_data(data_list)# nexttry:el_next = self.driver.find_element_by_xpath("//*[contains(text(),'下一頁')]")self.driver.execute_script('scrollTo(0,10000)')el_next.click()except:breakif __name__ == '__main__':douyu = Douyu()douyu.run()總結(jié)
以上是生活随笔為你收集整理的python网络爬虫系列(七)——selenium的介绍 selenium定位获取标签对象并提取数据 selenium的其它使用方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python3语法糖_Python笔记3
- 下一篇: Uniapp学习笔记(数据展示、数据循环