有人說Selenium庫和PhantomJ,說他們結合使用是萬能的利器。那麼,他們真的那麼厲害嗎,我們就一起來看看Selenium庫的用法吧。透過這篇文章讓我們來看看Selenium庫結合PhantomJs,Chrome等一些瀏覽器的操作吧。
什麼是Selenium
Selenium是一個自動化測試工具,支援包括Chrome,Firefox,Safari,PhantomJs等一些瀏覽器。如果用於爬蟲中,我們主要用來解決一些JavaScript渲染的問題。
我們在使用Requests函式庫去請求一些網頁的時候,例如 163music,我們獲得的回應資料呢,並不全是我們在瀏覽器中看到的資訊。他可能是透過js渲染出來的。那麼,我們如果使用Selenium庫,就不會再去關心如何解決這種問題了。
因為我們的瀏覽器,例如PhantomJs,他就是一個無介面的瀏覽器,他用來渲染解析js,而Selenium庫就負責給瀏覽器發送一些命令,模擬一些比如下拉,拖拽,翻頁,輸入表單等動作。這樣他們兩個結合,對於那些 JS 的渲染問題是不是完美解決了。
注意
雖然Selenium庫加上PhantomJs很好用,但他畢竟是驅動一個瀏覽器,然後取得資料。所以在我們使用中,會發現他並沒有我們使用一些解析函式庫速度快。這其實就是他的弊端,所以我還是建議大家,不到我找不到解決方法的時候,不去使用他們。
安裝準備
pip直接安裝Selenium庫:
pip install selenium
瀏覽器驅動程式的安裝:
Chrome瀏覽器驅動
PhantomJs瀏覽器驅動程式
我們需要把安裝好的瀏覽器驅動程式配置到我們的環境變數。對於Windows用戶,配置環境變數比較麻煩。我們需要找到下載好的驅動位置,然後複製他的檔案位置,請參閱他貼上到環境變數。
設定完成,命令列輸入:
phantomjs -v
查看是否成功。
使用範例
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait browser = webdriver.Chrome() try: browser.get('http://www.yukunweb.com') input = browser.find_element_by_id('s') input.send_keys('Python') input.send_keys(Keys.ENTER) wait = WebDriverWait(browser, 10) wait.until(EC.presence_of_element_located((By.ID, 'main'))) print(browser.current_url) print(browser.page_source) finally: browser.close()
如果我們執行上面的程式碼,我們會看到本機開啟了一個Chrome瀏覽器,然後在瀏覽器網址列輸入了我的部落格網址,然後他會自動的在搜尋欄輸入'Python',並且點擊了回車搜尋。並且將結果頁的url和原始碼列印出來。
我們的範例都是使用Chrome瀏覽器來操作,因為PhantomJs是無介面的,不方便查看到效果。如果大家執行錯誤的話,一般情況是瀏覽器並沒有打開,那麼應該是大家沒有安裝好Chrome瀏覽器,或是沒有將驅動設定環境變數。
那麼這幾行程式碼究竟是什麼意思呢,我們究竟賦予了什麼指令呢?
宣告瀏覽器物件
from selenium import webdriver browser = webdriver.Chrome() # 声明其他浏览器 browser = webdriver.PhantomJs() browser = webdriver.Firefox()
這就相當於我們呼叫了Selenium函式庫的webdriver方法,實例化一個Chrome瀏覽器給我們調用。
造訪頁面
from selenium import webdriver browser = webdriver.Chrome() browser.get('http://www.yukunweb.com')
我們將要存取的url傳給get方法。調用瀏覽器訪問url。
找出元素
input = browser.find_element_by_id('s')
這句程式碼呼叫find_element_by_id方法,顧名思義,就是找出id為's'的標籤,那麼如果是操作class為's'的話,就是find_element_by_class('s')。
當然,我們也可以使用 CSS選擇器和xpath選擇器來尋找元素:
input = browser.find_element_by_css_selector("#s") print(input) input = browser.find_element_by_xpath('//*[@id="s"]') print(input)
透過列印結果,可以看到不管使用什麼選擇器,尋找結果都是一樣的。以下是一些查找api:
find_element_by_namefind_element_by_xpathfind_element_by_link_textfind_element_by_partial_link_textfind_element_by_tag_namefind_element_by_class_namefind_element_by_css_selector
尋找多個元素
如果我們尋找的元素是網頁中的li標籤,是很多的元素。那麼我們的查找方式和單一元素是相同的,只是對於查找的api我們需要在element後面加個複數形式 s。即:
find_elements_by_namefind_elements_by_xpathfind_elements_by_link_textfind_elements_by_partial_link_textfind_elements_by_tag_namefind_elements_by_class_namefind_elements_by_css_selector
元素交互操作
即是對於我們所取得的元素下達指令,呼叫互動的方法。
browser.get('http://www.yukunweb.com') input = browser.find_element_by_id('s') input.send_keys('Python') input.send_keys(Keys.ENTER)
這段程式碼中,我們先查找到了id為's'的元素,然後傳給他'Python'值,然後呼叫互動方法,敲了回車。
當然,在大多是情況下,我們不能直接使用敲擊回車的方法,因為我們不確定是不是敲了回車,表單就提交了。我們需要使用查找器查找到提交按鈕元素,然後模擬點擊:
button = browser.find_element_by_class_name('xxxx') button.click() # 清除表单信息 button.clear()
那麼,我們可以看到在模擬登陸時候,直接讓我們手動的輸入帳號,密碼,如果有驗證碼的話直接給一個input方法,我們手動輸入驗證碼傳給表單,是不是很簡單的就模擬登入了。
互動動作
#元素交互动作与上面的操作是不同的。上面的操作需要获得一个特定的元素。然后对这个特定的元素调用一些指令,才可以完成交互。而这个交互是将这些动作附加到动作链中串行执行。
我们以拖拽元素为例(我们需要导入ACtionChains方法):
from selenium import webdriver from selenium.webdriver import ActionChains browser = webdriver.Chrome() browser.get(url) source = browser.find_element_by_name("source") target = browser.find_element_by_name("target") actions = ActionChains(browser) actions.drag_and_drop(source, target).perform()
这里的sourcs是我们要拖拽的元素,我们使用查找器找到他,target就是我们要拖拽到的位置元素。然后调用ActionChains方法,实现拖拽操作。
执行JavaScript
有些动作呢,Selenium库并没有为我们提供特定的api,比如说将浏览器进度条下拉,这个实现起来是很难的。那么我们就可以通过让Selenium执行JS来实现进度条的下拉,这个得需要一些js的知识,不过还是很简单的。
from selenium import webdriver browser = webdriver.Chrome() browser.get('http://www.yukunweb.com') browser.execute_script('window.scrollTo(0, document.body.scrollHeight)') browser.execute_script('alert("到达底部")')
这就相当于我们将一些JS命令传给Selenium的execute_script这个api,我们运行就可以看到浏览器下拉到底部,然后弹出会话框。
获取元素文本值
如果我们查找得到一个元素,我们要怎样获得元素的一些属性和文本信息呢?
from selenium import webdriver browser = webdriver.Chrome() browser.get('http://www.yukunweb.com') name = browser.find_element_by_css_selector('#kratos-logo > a') print(name.text) print(name.get_attribute('href'))
运行结果可以看到,他打印出了‘意外’和他的url。
Frame框架
有些网页在我们直接使用Selenium驱动浏览器打印源码的时候,并没有如期获得想要的数据,那在我们查看网页源码的时候,可以看到网页的iframe标签包裹的一个一个的框架。那么这就需要我们请求对应框架,拿到源码了。
我们以网易云音乐的歌手栏为例。
from selenium import webdriver browser = webdriver.Chrome() browser.get('https://music.163.com/#/discover/artist/signed/') print(browser.page_source)
可以查看结果,并没有我们想要的信息。
from selenium import webdriver browser = webdriver.Chrome() browser.get('https://music.163.com/#/discover/artist/signed/') browser.switch_to.frame('contentFrame') print(browser.page_source)
这次打印,我们就可以看到我们需要的信息了,是不是很简单。
显示等待
在文章开始的时候,我们运行的那段代码中有一段代码是不是还没有说。那就是我们命令浏览器等待的操作。
等待有两种方式,一种是隐士等待,一种是显示等待。当使用了隐士等待执行时,如果浏览器没有找到指定元素,将继续等待,如果超出设定时间就会抛出找不到元素的异常。而大多数情况我们建议使用显示等待。
显示等待是你指定一个等待的条件,还指定一个最长等待时间。那么程序会在最长等待时间内,判断条件是否成立,如果成立,立即返回。如果不成立,他会一直等待,直到最长等待时间结束,如果条件仍然不满足,就返回异常。
wait = WebDriverWait(browser, 10) wait.until(EC.presence_of_element_located((By.ID, 'main')))
这里的By.ID方法实际上就是一个查找的万能方法,而我们直接查找或者使用CSS、xpath查找足够满足,我也不过多介绍,想要了解可以查看官方文档。
这里是知道查找到id为‘main’就返回。
显示等待的一些条件还有:
title_is 标题是某内容
title_contains 标题包含某内容
presence_of_element_located 元素加载出,传入定位元组,如(By.ID, ‘p’)
visibility_of_element_located 元素可见,传入定位元组
visibility_of_element_located 元素可见,传入定位元组
visibility_of_element_located 元素可见,传入定位元组
visibility_of 可见,传入元素对象
presence_of_all_elements_located 所有元素加载出
text_to_be_present_in_element 某个元素文本包含某文字
text_to_be_present_in_element_value 某个元素值包含某文字
frame_to_be_available_and_switch_to_it frame加载并切换
invisibility_of_element_located 元素不可见
element_to_be_clickable 元素可点击
staleness_of 判断一个元素是否仍在DOM,可判断页面是否已经刷新
element_to_be_selected 元素可选择,传元素对象
element_located_to_be_selected 元素可选择,传入定位元组
element_selection_state_to_be 传入元素对象以及状态,相等返回True,否则返回False
element_located_selection_state_to_be 传入定位元组以及状态,相等返回True,否则返回False
alert_is_present 是否出现Alert
窗口选择
如果我们在表单输入关键词,提交表单后浏览器新打开了一个窗口,那么我们要怎么去操作新的窗口呢?索性Selenium为我们提供了对应的api.
import time from selenium import webdriver from selenium.webdriver.common.keys import Keys browser = webdriver.Chrome() browser.get('http://www.23us.cc/') input = browser.find_element_by_id('bdcs-search-form-input') input.send_keys('斗破苍穹') input.send_keys(Keys.ENTER) browser.switch_to_window(browser.window_handles[1]) print(browser.current_url) time.sleep(1) browser.switch_to_window(browser.window_handles[0]) print(browser.current_url)
通过打印结果,不难看出先打印了搜索结果窗口url,然后打印了索引页url。要注意窗口的索引是从 0 开始的哦,这个大家都明白。
异常处理
异常处理和普通的异常处理一样,没有什么要说的,大家自己查看官方异常 api.地址
最后
好了,透過這篇文章希望大家可以基本上了解Selenium庫結合瀏覽器驅動的一些使用方法。我們例子裡使用的是Chrome,但大家在實際的程式碼裡最好是使用PhantomJs,因為他是無介面的,運作起來相對好一點。
文章開始說過一般情況下不建議大家使用Selenium,因為他很慢。但是即使是慢,也很爽啊,是不是。
以上是Selenium+PhantomJs解析渲染Js的基本操作的詳細內容。更多資訊請關注PHP中文網其他相關文章!