是一个测试自动化的浏览器工具。爬虫主要用到Selenium的WebDriver,可以模拟真实用户操作浏览器。
1. 基本应用
安装
$ pip install selenium
导入库
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
加载浏览器
支持的浏览器有
Browser | Maintainer | Versions Supported |
---|---|---|
Chrome | Chromium | All versions |
Firefox | Mozilla | 54 and newer |
Edge | Microsoft | 84 and newer |
Internet Explorer | Selenium | 6 and newer |
Opera | Opera Chromium / Presto | 10.5 and newer |
Safari | Apple | 10 and newer |
这里使用了Chrome,可以自定义chrome浏览器的配置,然后加载到浏览器参数中
chrome_options = Options()
chrome_options.add_argument('--headless') ##无界面执行
chrome_options.add_argument('user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"')
driver = webdriver.Chrome(chrome_options=chrome_options)
driver.get(<url>)
2. 保存与读取cookies
前提条件是浏览器窗口要在该域名中,所以一般都会先执行
driver.get("http://www.example.com")
再进行cookies的操作
添加cookies至浏览器:
# Adds the cookie into current browser context
driver.add_cookie({"name": "key", "value": "value"})
从浏览器获取cookies:
获取指定名称
driver.get_cookie("foo")
获取所有
driver.get_cookies()
删除在浏览器中的cookies:
删除指定
# Delete a cookie with name 'test1'
driver.delete_cookie("test1")
删除所有
# Deletes all cookies
driver.delete_all_cookies()
除此之外,还能利用json文件读取和写入cookies文件
-
保存cookies到json文件
cookies = driver.get_cookies() jsonCookies = json.dumps(cookies) # 通过json将cookies写入文件 with open('topcashbacktest.json', 'w') as f: f.write(jsonCookies)
-
读取cookies文件
f = open("topcashbacktest.json", "r+", encoding='utf-8') cookie = f.read() cookie = json.loads(cookie) for c in cookie: if 'expiry' in c: del c['expiry'] driver.add_cookie(c)
- 如果出现
expiry
错误则删除expiry
键值
- 如果出现
3. 如何定位元素
有两种写法:
-
不同的查找方式有不同的函数名
to locate single element in a page:
- findelementby_id
- findelementby_name
- findelementby_xpath
- findelementbylinktext
- findelementbypartiallink_text
- findelementbytagname
- findelementbyclassname
- findelementbycssselector
To find multiple elements (these methods will return a list):
- findelementsby_name
- findelementsby_xpath
- findelementsbylinktext
- findelementsbypartiallink_text
- findelementsbytagname
- findelementsbyclassname
- findelementsbycssselector
-
不同的查找方式相同函数名,只是改变其参数
find_element
find_elements
使用例子:
from selenium.webdriver.common.by import By driver.find_element(By.XPATH, '//button[text()="Some text"]') driver.find_elements(By.XPATH, '//button')
解析:
导入By类;
在函数中根据想查找的方式使用不同的By类,其中类的各个方法名称定义为:
- ID = "id"
- XPATH = "xpath"
- LINK_TEXT = "link text"
- PARTIALLINKTEXT = "partial link text"
- NAME = "name"
- TAG_NAME = "tag name"
- CLASS_NAME = "class name"
- CSS_SELECTOR = "css selector"
各定位方式说明:
Locator | Description |
---|---|
class name | Locates elements whose class name contains the search value (compound class names are not permitted) |
css selector | Locates elements matching a CSS selector |
id | Locates elements whose ID attribute matches the search value |
name | Locates elements whose NAME attribute matches the search value |
link text | Locates anchor elements whose visible text matches the search value |
partial link text | Locates anchor elements whose visible text contains the search value. If multiple elements are matching, only the first one will be selected. |
tag name | Locates elements whose tag name matches the search value |
xpath | Locates elements matching an XPath expression |
可以在上一个搜索情况下再收窄元素
cheese = driver.find_element_by_id("cheese") ##根据id定位
cheddar = cheese.find_elements_by_id("cheddar") ##在原来的搜索结果上收窄搜索
4. 如何填表单
填充输入框:
username = driver.find_element(By.XPATH, '//input[@id="txtEmail"]')
username.clear()
username.send_keys(u'<yourEmail>')
pas = driver.find_element(By.XPATH,'//input[@id="ctl00_GeckoOneColPrimary_Login_txtPassword"]')
pas.clear()
pas.send_keys(u'<yourPassword>')
针对表单其他标签有其他方法,
-
select标签。使用
Select
类更加高效,方法如下:from selenium.webdriver.support.ui import Select select = Select(driver.find_element_by_name('name')) select.select_by_index(index) select.select_by_visible_text("text") select.select_by_value(value)
-
提交submit。有两种方法:
-
找到提交的button,使用
click()
# Assume the button has the ID "submit" :) driver.find_element_by_id("submit").click()
-
直接定位在该表单,使用
submit()
element.submit()
-
5. 如何切换句柄
首先,需要先获取句柄
获取当前window句柄:
this_window = driver.current_window_handle
获取当前浏览器的所有句柄:
all_windows = driver.window_handles
在切换句柄时,可以使用以下两种方式提供参数:
- 想跳转到的window的handle值
- 想跳转到的windows在windows_handles中的索引号
在selenium中通过driver.switch_to.window()
方式切换句柄。
所以,根据上述的参数方式可分为:
driver.switch_to.window(desired_window_handle)
driver.switch_to.window(driver.window_handles[desired_window_handle_index])
常见问题:
-
网页元素无法定位selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element:...
出错原因1:元素未加载完成
解决方法:
使用
WebDriverWait(driver,x)
函数实现等待X秒的功能,在X秒期间,每隔500毫秒扫描一次变化。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.Firefox() driver.get("http://somedomain/url_that_delays_loading") try: element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "myDynamicElement")) ) finally: ...
出错原因2:xpath或cssSelector定位错误
解决方法:
利用chrome的开发者工具,然后在
console
输入命令验证能否定位。xpath验证:
$x("the xpath you got from chrome")
cssSelector验证:
$$("the selector you got from chrome")
出错原因3:需要定位的元素在iframe框架中
解决方法:
先定位该iframe元素
iframe = driver.find_element_by_xpath("//iframe[@name='...']")
然后切换框架
driver.switch_to.frame(iframe)
然后在框架下定位想要的元素
desired_element = driver.find_element_by_xpath("//....")
-
所有的操作完成后,记得切换回到主框架
driver.switch_to.default_content()
-
-
在同一个浏览器新建tab(window)
打开的方式一般有两种,一种是使用浏览器(系统和浏览器的不同可能会有差异)的键盘快捷键打开,另一种是使用JavaScript打开。
这里使用JavaScript方式打开。
driver.execute_script("window.open('')")
-
注意点:
新建了tab后,selenium需要切换句柄才能真正在该新建的窗口中进行操作。虽然浏览器已经切换到新的窗口,但实际selenium还停留在原来的句柄那。
-
-
如何切换到想到的window窗口
可通过for loop的方式遍历。前提条件是要知道该window窗口的句柄值。
for window_handle in driver.window_handles: if window_handle != original_window: driver.switch_to.window(window_handle) break
-
如何bypass Google recaptcha
根据StackOverflow的解答,给chromeDriver增加属性
--disable-blink-features=AutomationControlled
。python代码:
from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument("--disable-blink-features=AutomationControlled") driver = webdriver.Chrome(chrome_options=chrome_options)
-
如何缓存cookies
给chromeDriver增加属性
--user-data-dir= the_detionary_path_you_want_to_save
python代码:
from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument("--user-data-dir= chrome_data") driver = webdriver.Chrome(chrome_options=chrome_options)
- 缓存的数据存在该项目根目录(或者执行工具目录)中,文件名为
chrome_data
。
- 缓存的数据存在该项目根目录(或者执行工具目录)中,文件名为
There are 0 comments