新聞中心
我們知道很多時(shí)候爬蟲也不是萬能的,這個(gè)時(shí)候就需要我們的自動(dòng)化測(cè)試框架了。

為迪慶州等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及迪慶州網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、迪慶州網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!
于是Selenium就應(yīng)運(yùn)而生了,它可以算的上是自動(dòng)化測(cè)試框架中的佼佼者,因?yàn)樗鉀Q了大多數(shù)用來爬取頁面的模塊的一個(gè)永遠(yuǎn)的痛,那就是Ajax異步加載 。今天將給大家詳解如何用Selenium爬取數(shù)據(jù),并最后附上一個(gè)真實(shí)的案例。
一 、Selenium介紹
Selenium是一個(gè)web的自動(dòng)化測(cè)試工具,最初是為網(wǎng)站自動(dòng)化測(cè)試而開發(fā)的,Selenium可以直接運(yùn)行在瀏覽器上,它支持所有主流的瀏覽器,可以接收指令,讓瀏覽器自動(dòng)加載頁面,獲取需要的數(shù)據(jù),甚至頁面截屏 。
chromedriver是一個(gè)驅(qū)動(dòng)Chrome瀏覽器的驅(qū)動(dòng)程序,使用他才可以驅(qū)動(dòng)瀏覽器。當(dāng)然針對(duì)不同的瀏覽器有不同的driver。以下列出了不同瀏覽器及其對(duì)應(yīng)的driver:
- Chrome:https://sites.google.com/a/chromium.org/chromedriver/downloads
- Firefox:https://github.com/mozilla/geckodriver/releases
- Edge:https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
- Safari:https://webkit.org/blog/6900/webdriver-support-in-safari-10/
安裝配置chromedriver:https://blog.csdn.net/weixin_43901998/article/details/88087832
安裝Selenium:
pip install selenium
安裝好瀏覽器后,將瀏覽器驅(qū)動(dòng)放在瀏覽器同級(jí)目錄下,這樣前期工作就算都預(yù)備好了。
- 注:不要隨便亂下瀏覽器和驅(qū)動(dòng),每個(gè)瀏覽器和驅(qū)動(dòng)器的版本都必須是一一對(duì)應(yīng)的,不是通用的。
二、快速入門
1、與瀏覽器建立連接
# 1.加載網(wǎng)頁
from selenium import webdriver
driver = webdriver.PhantomJS(executable_path=r'"安裝目錄") # 也可以把chrome添加到python文件路徑下,就不用寫executable_path=r'"安裝目錄"
driver.get("https://www.baidu.com") # 請(qǐng)求
driver.save_screenshot("baidu.png") # 截圖
# 退出
driver.quit()
2、selenium快速入門
from selenium import webdriver
# 實(shí)例化瀏覽器
driver = webdriver.Chrome()
# 發(fā)送請(qǐng)求
driver.get('https://www.baidu.com')
# 截圖
driver.save_screenshot("baidu.png")
# 最大化窗口
driver.maximize_window()
# 退出瀏覽器
driver.quit()
三、定位元素
- find_element_by_id:根據(jù)id來查找某個(gè)元素。
submitTag = driver.find_element_by_id('su')
submitTag1 = driver.find_element(By.ID,'su')- find_element_by_class_name:根據(jù)類名查找元素。
submitTag = driver.find_element_by_class_name('su')
submitTag1 = driver.find_element(By.CLASS_NAME,'su')- find_element_by_name:根據(jù)name屬性的值來查找元素。
submitTag = driver.find_element_by_name('email')
submitTag1 = driver.find_element(By.NAME,'email')- find_element_by_tag_name:根據(jù)標(biāo)簽名來查找元素。
submitTag = driver.find_element_by_tag_name('div')
submitTag1 = driver.find_element(By.TAG_NAME,'div')- find_element_by_xpath:根據(jù)xpath語法來獲取元素。
submitTag = driver.find_element_by_xpath('//div')
submitTag1 = driver.find_element(By.XPATH,'//div')要注意,find_element是獲取第一個(gè)滿足條件的元素。find_elements是獲取所有滿足條件的元素。
四、瀏覽器操作
from selenium import webdriver
# 實(shí)例化瀏覽器
c = webdriver.Chrome()
# 發(fā)送請(qǐng)求
c.get('https://www.baidu.com')
1、獲取本頁面URL
c.current_url
2、獲取日志
c.log_types #獲取當(dāng)前日志類型
c.get_log('browser')#瀏覽器操作日志
c.get_log('driver') #設(shè)備日志
c.get_log('client') #客戶端日志
c.get_log('server') #服務(wù)端日志
##3.窗口操作
c.maximize_window()#最大化
c.fullscreen_window() #全屏
c.minimize_window() #最小化
c.get_window_position() #獲取窗口的坐標(biāo)
c.get_window_rect()#獲取窗口的大小和坐標(biāo)
c.get_window_size()#獲取窗口的大小
c.set_window_position(100,200)#設(shè)置窗口的坐標(biāo)
c.set_window_rect(100,200,32,50) #設(shè)置窗口的大小和坐標(biāo)
c.set_window_size(400,600)#設(shè)置窗口的大小
c.current_window_handle #返回當(dāng)前窗口的句柄
c.window_handles #返回當(dāng)前會(huì)話中的所有窗口的句柄
3、設(shè)置延時(shí)
c.set_script_timeout(5) #設(shè)置腳本延時(shí)五秒后執(zhí)行
c.set_page_load_timeout(5)#設(shè)置頁面讀取時(shí)間延時(shí)五秒
4、關(guān)閉
c.close() #關(guān)閉當(dāng)前標(biāo)簽頁
c.quit() #關(guān)閉瀏覽器并關(guān)閉驅(qū)動(dòng)
5、打印網(wǎng)頁源代碼
c.page_source
6、屏幕截圖操作
c.save_screenshot('1.png')#截圖,只支持PNG格式
c.get_screenshot_as_png() #獲取當(dāng)前窗口的截圖作為二進(jìn)制數(shù)據(jù)
c.get_screenshot_as_base64() #獲取當(dāng)前窗口的截圖作為base64編碼的字符串
8.前進(jìn)后退刷新
c.forward() #前進(jìn)
c.back() #后退
c.refresh()#刷新7、Cookies操作
c.get_cookie('BAIDUID') #獲取指定鍵的Cookies
c.get_cookies() #獲取所有的Cookies
for y in c.get_cookies():
x=y
if x.get('expiry'):
x.pop('expiry')
c.add_cookie(x) #添加Cookies
c.delete_cookie('BAIDUID') #刪除指定鍵的Cookies內(nèi)容
c.delete_all_cookies() #刪除所有cookies五、操作表單元素
操作輸入框:分為兩步。
第一步:找到這個(gè)元素。
第二步:使用send_keys(value),將數(shù)據(jù)填充進(jìn)去
使用clear方法可以清除輸入框中的內(nèi)容
inputTag.clear()
操作checkbox
因?yàn)橐x中checkbox標(biāo)簽,在網(wǎng)頁中是通過鼠標(biāo)點(diǎn)擊的。因此想要選中checkbox標(biāo)簽,那么先選中這個(gè)標(biāo)簽,然后執(zhí)行click事件。
rememberTag = driver.find_element_by_name("rememberMe")
rememberTag.click()操作按鈕
操作按鈕有很多種方式。比如單擊、右擊、雙擊等。這里講一個(gè)最常用的。就是點(diǎn)擊。直接調(diào)用click函數(shù)就可以了。?
inputTag = driver.find_element_by_id('su')
inputTag.click()選擇select
select元素不能直接點(diǎn)擊。因?yàn)辄c(diǎn)擊后還需要選中元素。這時(shí)候selenium就專門為select標(biāo)簽提供了一個(gè)類selenium.webdriver.support.ui.Select。將獲取到的元素當(dāng)成參數(shù)傳到這個(gè)類中,創(chuàng)建這個(gè)對(duì)象。以后就可以使用這個(gè)對(duì)象進(jìn)行選擇了[1]。
切換iframe
我們知道網(wǎng)頁中有一種節(jié)點(diǎn)叫作 iframe,也就是子 Frame,相當(dāng)于頁面的子頁面,它的結(jié)構(gòu)和外部網(wǎng)頁的結(jié)構(gòu)完全一致。Selenium打開頁面后,默認(rèn)是在父級(jí) Frame 里面操作,而此時(shí)如果頁面中還有子 Frame,Selenium是不能獲取到子 Frame 里面的節(jié)點(diǎn)的。這時(shí)就需要使用 switch_to.frame 方法來切換 Frame。
接下來通過豆瓣模擬登錄來切換iframe,示例如下:
from selenium import webdriver
import time
url = 'https:www.douban.com'
driver = webdriver.Chrome()
driver.get(self.url)
time.sleep(3)
# 定位iframe標(biāo)簽
login_iframe = self.driver.find_element_by_xpath('//*[@id="anony-reg-new"]/div/div[1]/iframe')
# 切換iframe標(biāo)簽
driver.switch_to.frame(login_iframe)
六、行為鏈
有時(shí)候在頁面中的操作可能要有很多步,那么這時(shí)候可以使用鼠標(biāo)行為鏈類ActionChains來完成。比如現(xiàn)在要將鼠標(biāo)移動(dòng)到某個(gè)元素上并執(zhí)行點(diǎn)擊事件。
actions = ActionChains(driver)
actions.move_to_element(inputTag)
actions.send_keys_to_element(inputTag,'python')
actions.move_to_element(submitTag)
actions.context_click()
actions.click(submitTag)
actions.perform()
還有更多的鼠標(biāo)相關(guān)的操作。
- click_and_hold(element):點(diǎn)擊但不松開鼠標(biāo)。
- context_click(element):右鍵點(diǎn)擊。
- double_click(element):雙擊。
- 更多方法請(qǐng)參考:http://selenium-python.readthedocs.io/api.html
豆瓣模擬登錄(定位元素,切換iframe,以及行為鏈操作)。
from selenium import webdriver
import time
class Douban():
def __init__(self):
self.url = 'https:www.douban.com'
self.driver = webdriver.Chrome()
def login(self):
self.driver.get(self.url)
time.sleep(3)
# 定位iframe標(biāo)簽
login_iframe = self.driver.find_element_by_xpath('//*[@id="anony-reg-new"]/div/div[1]/iframe')
# 切換iframe標(biāo)簽
self.driver.switch_to.frame(login_iframe)
# 第一張截圖(登錄前)
self.driver.save_screenshot('db1.png')
# 定位密碼輸入框
self.driver.find_element_by_class_name('account-tab-account').click()
# 輸入手機(jī)號(hào)
self.driver.find_element_by_id('username').send_keys('156xxxxxx26')
# 輸入密碼
self.driver.find_element_by_id('password').send_keys('.......')
# 點(diǎn)擊登錄按鈕
self.driver.find_element_by_class_name('btn-account').click()
time.sleep(3)
# 第二張截圖(登陸后)
self.driver.save_screenshot('db2.png')
def out(self):
'''調(diào)用內(nèi)建的稀構(gòu)方法,在程序退出的時(shí)候自動(dòng)調(diào)用
類似的還可以在文件打開的時(shí)候調(diào)用close,數(shù)據(jù)庫(kù)鏈接的斷開
'''
self.driver.quit()
if __name__ == '__main__':
db = Douban() # 實(shí)例化
db.login() # 之后調(diào)用登陸方法
七、Selenium頁面等待
Cookie操作
獲取所有的cookie
cookies = driver.get_cookies()
根據(jù)cookie的name獲取cookie
value = driver.get_cookie(key)
刪除某個(gè)cookie
driver.delete_cookie('key')頁面等待
現(xiàn)在的網(wǎng)頁越來越多采用了 Ajax 技術(shù),這樣程序便不能確定何時(shí)某個(gè)元素完全加載出來了。如果實(shí)際頁面等待時(shí)間過長(zhǎng)導(dǎo)致某個(gè)dom元素還沒出來,但是你的代碼直接使用了這個(gè)WebElement,那么就會(huì)拋出NullPointer的異常。為了解決這個(gè)問題。所以 Selenium 提供了兩種等待方式:一種是隱式等待、一種是顯式等待。
- 隱式等待:調(diào)用driver.implicitly_wait。那么在獲取不可用的元素之前,會(huì)先等待10秒中的時(shí)間。
driver.implicitly_wait(10)
- 顯示等待:顯示等待是表明某個(gè)條件成立后才執(zhí)行獲取元素的操作。也可以在等待的時(shí)候指定一個(gè)最大的時(shí)間,如果超過這個(gè)時(shí)間那么就拋出一個(gè)異常。顯示等待應(yīng)該使用selenium.webdriver.support.excepted_conditions期望的條件和selenium.webdriver.support.ui.WebDriverWait來配合完成。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("https://www.baidu.com/")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
一些其他的等待條件
- presence_of_element_located:某個(gè)元素已經(jīng)加載完畢了。
- presence_of_all_elements_located:網(wǎng)頁中所有滿足條件的元素都加載完畢了。
- element_to_be_clickable:某個(gè)元素是可以點(diǎn)擊了。
更多條件請(qǐng)參考:http://selenium-python.readthedocs.io/waits.html
八、打開多窗口和切換頁面
有時(shí)候窗口中有很多子tab頁面。這時(shí)候肯定是需要進(jìn)行切換的。selenium提供了一個(gè)叫做switch_to_window來進(jìn)行切換,具體切換到哪個(gè)頁面,可以從driver.window_handles中找到。?
# 打開一個(gè)新的頁面
driver.execute_script("window.open('url')")
print(driver.current_url)
# 切換到這個(gè)新的頁面中
driver.switch_to_window(self.driver.window_handles[1])
九、企鵝電競(jìng)案例
下面我們用企鵝電競(jìng)為案例,演示一下如何使用Selenium爬取數(shù)據(jù)。
1、打開官網(wǎng)首頁:通過分析頁面知道全部直播的信息儲(chǔ)存在ul(class='livelist-mod resize-list-container-280-livelist-live)下面的li里面。
但是通過測(cè)試可以發(fā)現(xiàn)這個(gè)頁面瀑布流布局,他不需要翻頁,需要滾到頁面底部加載更多數(shù)據(jù)。所以:
dataNum = int(input('請(qǐng)輸入目標(biāo)直播間數(shù)量:')) # 用戶決定爬取多少個(gè)直播間信息
_single = True
# 做一個(gè)死循環(huán)
while _single:
items = driver.find_elements_by_xpath("http://ul[@class='livelist-mod resize-list-container-280-livelist-live']/li") # 頁面的li標(biāo)簽(也就是一個(gè)直播間數(shù)據(jù))
print(len(items))
if len(items) < dataNum:
# 拖動(dòng)滾動(dòng)條至底部
js1 = "document.documentElement.scrollTop=100000"
driver.execute_script(js1)
time.sleep(3) # 因?yàn)闈L動(dòng)到頁面底部只需要一瞬間,休息3s是為了數(shù)據(jù)加載完全
else:
_single = False2、我們要獲取的是主題(title),界面圖片鏈接(pic),主播名(name),人氣(popu),類型(types)。
- 這里我們只爬取了600條數(shù)據(jù),但是讓頁面加載800條數(shù)據(jù),因?yàn)檫@個(gè)頁面加載不完全,也就是他最后面展示的數(shù)據(jù)不會(huì)顯示出來(只要使用滾輪滾到底部,由于數(shù)據(jù)加載,滾輪就會(huì)往上一點(diǎn),這樣頁面顯示的數(shù)據(jù)是沒有完全加載出來)。
items = driver.find_elements_by_xpath("http://ul[@class='livelist-mod resize-list-container-280-livelist-live']/li")
print(len(items))
info_list = []
for item in items[:600]:
dic = {}
name = item.find_element_by_xpath("./a/div[2]/p").text # 主播名字
popularity = item.find_element_by_xpath("./a/div[2]/span").text # 人氣
title = item.find_element_by_xpath('./a/h4/span[1]').text # 主題
types = item.find_element_by_xpath('./a/h4/span[2]').text # 類型
pic = item.find_element_by_xpath('./a/div[1]/img').get_attribute('src') # 圖片鏈接
picLink = 'https:' + pic
dic['name'] = name
dic['popu'] = popularity
dic['title'] = title
dic['type'] = types
dic['pic'] = picLink
print(dic)
info_list.append(dic)3、數(shù)據(jù)提取
這里我們把數(shù)據(jù)保存到一個(gè)csv文件中。
head = ['name','popu','title','type','pic']
with open('qiee.csv', 'w', encoding='utf-8', newline='') as f:
writer = csv.DictWriter(f, head)
writer.writeheader()
writer.writerows(info_list)
print('寫入成功')
4、運(yùn)行程序
開始:
結(jié)尾:
然后我們看下csv文件:
成功爬取到了想要的數(shù)據(jù)。
網(wǎng)站標(biāo)題:用Selenium來爬取數(shù)據(jù)?真挺簡(jiǎn)單的!
瀏覽地址:http://www.dlmjj.cn/article/dhppcec.html


咨詢
建站咨詢
