建議以下帖子:
教你在Windows上搭建Python+Selenium環境:https://blog.csdn.net/huilan_same/article/details/52888262
python webdriver 的異常:https://blog.csdn.net/huilan_same/article/details/52815047
Selenium庫的使用:https://blog.csdn.net/weixin_36279318/article/details/79475388
以下是我滿懷信心學習卻被異常為所欲為的調戲但是堅持抵抗留下的充滿邏輯的筆記
一、用selenium模塊控制瀏覽器
安裝selenium 3.1410
selenium能讓用戶通過Python直接控制瀏覽器,實際點擊鏈接,填寫登錄信息,幾乎就像一個人類與瀏覽器交互。這能比使用 Request 和 Beautiful Soup 模塊完成更多的事情,能讓你以更高級的方式和瀏覽器交互,但是也有一個確定,比如當你只是想下載一個文件時,前者就有些復雜,並且難以在后台運行
安裝針對chrome的瀏覽器驅動(注意版本):http://selenium-release.storage.googleapis.com/index.html
1.1啟動selenium控制的瀏覽器
以 form selenium import webdriver 來導入webderiver模塊
>>> from selenium import webdriver >>> browser=webdriver.Chrome() >>> browser.get('http://www.baidu.com') >>> browser.quit()#退出
1.2在頁面中尋找元素
Webdriver對象有好幾種方法,用於在頁面中尋找元素。他們被分成 find_element_* 和 find_elements_* 方法。前者返回的WebElement對象,代表頁面中匹配查詢的第一個元素,而后者包含所有匹配元素的列表。
在Webdriver對象上調用的方法:
方法名 | 返回的WebElement對象/列表 |
browser.find_element_by_class_name(name) browser.find_elements_by_class_name(name) |
類名為name的元素 |
browser.find_element_by_css_selector(selector) browser.find_elements_by_css_selector(selector) |
selector為css選擇器,如同我們寫樣式時寫的內容如“#head” 返回匹配的元素 |
browser.find_element_by_id(id) browser.find_elements_by_id(id) |
id名為id的元素 |
browser.find_element_by_link_text(text) browser.find_elements_by_link_text(text) |
返回a元素中文本內容完全為text的a元素 |
browser.find_element_by_partial_link_text(text) browser.find_elements_by_partial_link_text(text) |
partial:局部 返回a元素中文本內容包含text的元素 |
browser.find_element_by_name(name) browser.find_elements_by_name(name) |
匹配name屬性值為name的元素 |
browser.find_element_by_tag_name(name) | 匹配標簽名為name的元素 (大小寫無關‘a’和'A'都會匹配便簽<a>) |
注意:
除了最后一個方法,其他的參數都是區分大小寫的。如果頁面上沒有元素被匹配,selenium模塊就會拋出 NoSuchElement 異常。即要配合 try....except 語句
使用類名和id來查找元素時,注意不要有空格,因為空格前后的內容會被HTML解釋成兩個
當界面跳轉后,如果原來的查找結果還能有匹配,那么就不用重新匹配
上述方法假如匹配成功,會返回一個 WebElement 對象,對於這個對象可以使用下面的屬性或方法:
方法或者屬性 | 描述 |
tag_name | 標簽名,例如‘a’(這個是返回的值)代表<a>元素 |
get_attribute(name) | 該元素 name屬性 的值 |
text | 該元素內的文本,例如<span>hello</span>中的‘hello’ |
clear() | 對於文本字段或文本區域元素,清除其中輸入的文本 不能清除<a>里面的,估計<span>里的也不能 |
is_displayed() | 如果該元素可見,返回True,可以用於先判斷元素是否可見 |
is_enabled() | 對於輸入元素,如果該元素啟用,返回True |
is_selected() | 對於復選框或者單選元素,如果該元素被選中,返回True |
location | 一個字典,包含鍵‘x’和'y',表示該元素在頁面上的位置 |
示例:
from selenium import webdriver browser=webdriver.Chrome() browser.get('http://www.baidu.com') try: elem=browser.find_element_by_class_name('head_wrapper')#尋找第一個類名為head_wrapper的元素 print('找到了相應類名的元素:<%s>'%(elem.location)) except: print('沒有找到這個元素。') browser.quit()
1.3點擊頁面
利用 WebElement 對象的click()方法,我們可以模擬鼠標在該元素上單擊。效果與我們手動單擊的效果一樣
示例:
from selenium import webdriver browser=webdriver.Chrome() browser.get('http://www.baidu.com') try: elem=browser.find_element_by_class_name('mnav')#會匹配到“新聞” print('找到了相應類名的元素:<%s>'%(elem.location)) elem.click() except: print('沒有找到這個元素。') browser.quit()
1.4輸入內容send_key()
是webElement對象的方法
1.5填寫並提交表單
webElement對象方法 submit() ,在任何元素上使用 submit() 方法,都相當於點擊該元素所在表單的submit按鈕
示例:
import logging #此行以及下兩行行是使用日志內容 logging.basicConfig(level=logging.CRITICAL,format=' %(asctime)s - %(levelname)s -%(message)s') from selenium import webdriver logging.disable(logging.ERROR) browser=webdriver.Chrome() browser.get('http://www.baidu.com') try: elem=browser.find_element_by_id('kw') logging.critical('輸入框已經找到') elem.send_keys('長澤雅美') #是keys logging.critical('內容已輸入') searchElem=browser.find_element_by_id('su') logging.critical('按鈕已經找到') searchElem.submit() logging.critical('已提交') except: print('沒有找到這個元素。') browser.quit()
注意,不用在尋找提交按鈕上花費太長時間,因為在任何元素上使用 submit() 方法,都等同於你點擊了這個元素所屬表單的提交按鈕,你甚至可以這樣(我不確定,你可以打開百度首頁,輸入內容演示一下,就能知道我的意思了你可能發現你不需要點擊搜索按鈕,就會出現搜索結果)
---snip---- elem.submit() #改動在這里 logging.critical('已提交') ---snip---
1.6發送特殊鍵
當我們需要向瀏覽器擊鍵行為,如按下‘F12’,這時僅通過字符串值輸入時不可能完成的,selenium為我們這種需要提供了一個解決辦法:這些值保存在selenium.webdriver.common.keys模塊的屬性中。由於這個模塊的名字非常長,我們可以通過from selenium.webdriver.common.keys import Keys,讓from selenium.webdriver.common.keys.Keys.F12簡寫為:Keys.F12
下表展示了一些selenium.webdriver.common.keys模塊中常用的變量:
屬性 | 含義 |
Keys.DOWN,Keys.UP,Keys.LEFT,Keys.RIGHT | 鍵盤方向鍵 |
Keys.ENTER,Keys.RETURN | 回車鍵和換行鍵 |
Keys.HOME,Keys.END,Keys.PAGE_DOWN,Keys.PAGE_UP | |
Keys.ESCAPE,Keys.BACK_SPACE,Keys.DELETE | Esc,backspace和消除鍵 |
Keys.F1,Keys.F2........Keys.F12 | |
Keys.TAB |
示例:使頁面向下滾動一次
import time import logging #此行以及下兩行行是使用日志內容 logging.basicConfig(level=logging.CRITICAL,format=' %(asctime)s - %(levelname)s -%(message)s') from selenium import webdriver logging.disable(logging.ERROR) from selenium.webdriver.common.keys import Keys browser=webdriver.Chrome() browser.get('http://www.baidu.com') try: elem=browser.find_element_by_id('kw') logging.critical('輸入框已經找到') elem.send_keys('長澤雅美') #是keys logging.critical('內容已輸入') searchElem=browser.find_element_by_id('su') logging.critical('按鈕已經找到') elem.submit() logging.critical('已提交') htmlElem=browser.find_element_by_tag_name('html') htmlElem.send_keys(Keys.PAGE_DOWN) except: print('沒有找到這個元素。') time.sleep(3) #不加這個暫停看不出來效果 browser.quit()
注意:
(未證明)要對合適的元素對象使用相應的按鍵,如果上面你對'elem'使用這不會有效果
是keys要加s
問題:
使用Keys.PAGE_DOWN,時必須在前面加sleep()才能實現
import time import logging #此行以及下兩行行是使用日志內容 logging.basicConfig(level=logging.CRITICAL,format=' %(asctime)s - %(levelname)s -%(message)s') from selenium import webdriver logging.disable(logging.ERROR) from selenium.webdriver.common.keys import Keys browser=webdriver.Chrome() browser.maximize_window() browser.get('http://www.baidu.com') try: elem=browser.find_element_by_id('kw') logging.critical('輸入框已經找到') elem.send_keys('長澤雅美') #是keys logging.critical('內容已輸入') searchElem=browser.find_element_by_id('su') logging.critical('按鈕已經找到') elem.submit() logging.critical('已提交') htmlElem=browser.find_element_by_tag_name('html') logging.critical('html標簽已找到') time.sleep(2) elem.send_keys(Keys.PAGE_DOWN)#必須前面使用sleep()暫停才有用 logging.critical('按鍵已激發') except: print('沒有找到這個元素。') time.sleep(10) browser.quit()
不能發送F5按鍵使瀏覽器窗口刷新(可以使用browser.refresh()),無論是對html標簽元素還是其他元素使用均無效
import time import logging #此行以及下兩行行是使用日志內容 logging.basicConfig(level=logging.CRITICAL,format=' %(asctime)s - %(levelname)s -%(message)s') from selenium import webdriver logging.disable(logging.ERROR) from selenium.webdriver.common.keys import Keys browser=webdriver.Chrome() browser.maximize_window() browser.get('http://www.baidu.com') try: elem=browser.find_element_by_id('kw') logging.critical('輸入框已經找到') elem.send_keys('長澤雅美') #是keys logging.critical('內容已輸入') searchElem=browser.find_element_by_id('su') logging.critical('按鈕已經找到') elem.submit() logging.critical('已提交') htmlElem=browser.find_element_by_tag_name('html') logging.critical('html標簽已找到') time.sleep(2) elem.send_keys(Keys.F5)#必須前面使用sleep()暫停才有用 logging.critical('按鍵已激發') except: print('沒有找到這個元素。') time.sleep(10) browser.quit()
1.6點擊瀏覽器按鈕
這里的瀏覽器按鈕指的是瀏覽器應用里的按鈕,
browser.back() 點擊返回按鈕
browser.froward() 點擊前進按鈕
browser.refresh() 點擊刷新按鈕
browser.quit() 點擊關閉窗口按鈕
二、selenium的更多信息
browser.maximize_windows():設置瀏覽器大小為全屏
browser.set_window_size(500,500):設置瀏覽器窗口大小為500*500
組合鍵操作:https://www.cnblogs.com/mengyu/p/6942584.html
更詳細的信息包括 拖放:https://www.cnblogs.com/zhongyehai/p/9163740.html
說send_keys()不能輸入中文的解決辦法是send_keys(u' ')
三、遇到的問題:
1)selenium.common.exceptions.WebDriverException:Message: 'geckodriver' executable needs to be in PATH.
問題是有你沒有瀏覽器驅動,或者瀏覽器驅動所在的文件夾沒有在環境變量PATH里面
在執行以下代碼時出現了上個異常
>>> from selenium import webdriver >>> browser=webdriver.Firefox() Traceback (most recent call last): File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\common\service.py", line 76, in start stdin=PIPE) File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\subprocess.py", line 775, in __init__ restore_signals, start_new_session) File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\subprocess.py", line 1178, in _execute_child startupinfo) FileNotFoundError: [WinError 2] 系統找不到指定的文件。 During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<pyshell#1>", line 1, in <module> browser=webdriver.Firefox() File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\firefox\webdriver.py", line 164, in __init__ self.service.start() File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\common\service.py", line 83, in start os.path.basename(self.path), self.start_error_message) selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executable needs to be in PATH.
解決辦法:(錯誤雖然沒有別我解決,但基於相似問題有龐大的搜索結果。相信仍然有一定的借鑒意義)
錯誤是英文的,我先把他翻譯過來之后,這個錯誤的意思是“geckodriver”需要在環境變量訪問到才能執行。 由於是第一次使用selenium模塊,我搜索了模塊的使用方法,然后發現需要針對Firefox瀏覽器的webdriver驅動文件,然后就下載了。發現下載太慢,然后又按照另外一個方法解決辦法:“出現這樣的錯誤是瀏覽器沒有安裝到默認位置,需要修改selenium模塊里的兩個參數”(這個辦法沒有用,你只需要將瀏覽器的安裝文件夾添加到PATH里面)
D:\Programs\Python\Python35-32\Lib\site-packages\selenium-3.0.1-py3.5.egg\selenium\webdriver\firefox的 webdriver.py文件中修改為 def_init_(self,firefox_profile=None,firefox_binary=FirefoxBinary("D:/Program Files (x86)/Mozilla Firefox/firefox.exe")#其中的是瀏覽器的安裝位置 Firefox_binary.py文件中修改為 def_init_(self,firefox_path="D:/Program Files (x86)/Mozilla Firefox/firefox.exe",log_file=None);
然后發現還是報同樣的錯誤,這是下載驅動文件也好了,網上說要需要配置Path變量的,我直接把它放在Python的根目錄下了,因為這里已經配置過了
geckodriver的網盤鏈接: https://pan.baidu.com/s/1fWLiTd_1p3vn9CzBTJcfpg 提取碼: uki4
GitHub鏈接:https://github.com/mozilla/geckodriver/releases
然后程序能運行了,能打開一個火狐瀏覽器窗口
>>> from selenium import webdriver >>> browser=webdriver.firefox()
我沒高興太長時間,准確來說,上述成功只運行了一次,就不行了。我試了很多辦法,然后放棄了,選擇了chrome
我試了下載高版本的selenium,但pip中自動安裝的最新版本是3.141,我上網找了selenium的版本:版本在這里,不知道那個才是python要的,放棄
以上辦法來源於參考經驗:
https://www.cnblogs.com/fangfangs/p/f0000000f.html
問題 selenium.common.exceptions.SessionNotCreatedException: Message: Unable to find a matching set of capabilities
這個問題是由於你的瀏覽器驅動文件(geckodriver、chromedriver)版本和selenium版本不兼容導致的
>>> from selenium import webdriver
>>> browser=webdriver.firefox()
Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> browser=webdriver.Firefox() File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\firefox\webdriver.py", line 174, in __init__ keep_alive=True) File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 157, in __init__ self.start_session(capabilities, browser_profile) File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 252, in start_session response = self.execute(Command.NEW_SESSION, parameters) File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute self.error_handler.check_response(response) File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\site-packages\selenium\webdriver\remote\errorhandler.py", line 242, in check_response raise exception_class(message, screen, stacktrace) selenium.common.exceptions.SessionNotCreatedException: Message: Unable to find a matching set of capabilities
上網搜索發現是瀏覽器版本問題,決定更新瀏覽器版本再說,之后發現這個方法沒用
首先應該讓瀏覽器、瀏覽器驅動、selenium、三個的版本互相兼容:他們之間版本關系我在網上沒有找到整理的好的。我就在geckodriver(針對火狐的瀏覽器驅動)的主頁上看介紹,發現我下的v24,竟然要求Firefox是66版本的,而瀏覽器提示我65已經是最新,沒有辦法我只能繼續看下去,然后找到了一個
通過查看C:\Users\Administrator.SC-2016\AppData\Local\Programs\Python\Python37\Lib\site-packages\selenium\webdriver\firefox\webdriver.xpi\install.rdf文件來查看你安裝的selenium支持的瀏覽器版本(通過winrar查看這個文件),發現我的支持Firefox版本是3.0到52的:
然后發現Firefox版本還是太高,我下了一個51.***的。
啟發:
不要想着征服錯誤,特別是在還有別的替代方法的情況下。
不要被搜索出來的解決辦法的困難度嚇到,要盡量找到高質量的解決辦法,像有些錯誤,壓根就是沒按照正常流程去做而出錯的。如果你找到的解決辦法沒有把這個講明白,會很浪費時間