Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,可以按指定的命令自动操作,但是他需要与第三方浏览器结合在一起才能使用。如果我们把 Selenium和第三方浏览器(比如Chrome)结合在一起,就可以运行一个非常强大的网络爬虫了,这个爬虫可以处理 JavaScrip、Cookie、headers,以及任何我们真实用户需要做的事情。
一、安装
sudo pip3 install selenium
二、快速入门
from selenium import webdriver # 导入webdriver from selenium.webdriver.common.keys import Keys #Keys`类提供键盘按键的支持,比如:RETURN, F1, ALT等 from selenium.webdriver.chrome.options import Options #导入Chrome浏览器配置选项类
options = Options() options.add_argument('--headless')#无界面浏览器 options.add_argument('--disable-gpu')# 禁用gpu加速,规避bug driver = webdriver.Chrome(options=options) #创建浏览器对象 driver.get("https://www.baidu.com/") # get方法会打开一个页面 driver.implicitly_wait(10) # 通常打开页面后会等待一会,让页面加载 print (driver.title) # 打印页面标题 "百度一下,你就知道" driver.save_screenshot("baidu.png") # 生成当前页面快照并保存 elem = driver.find_element_by_id('kw') #根据id查找元素 elem.clear() #清空搜索框 elem.send_keys('中国') #搜索中国 elem.send_keys(Keys.RETURN) #按回车键 print(driver.page_source) # 打印网页渲染后的源代码 print(driver.get_cookies()) # 获取当前页面Cookie print(driver.current_url) # 获取当前url # driver.close() 关闭当前页面,如果只有一个页面,会关闭浏览器 driver.quit() # 关闭浏览器
三、查找元素
查找单个元素(如果有多个匹配的元素,则返回第一个匹配到的元素)
find_element_by_id 通过id查找
login_form = driver.find_element_by_id('loginForm')
find_element_by_name 通过name查找
username = driver.find_element_by_name('username') password = driver.find_element_by_name('password')
find_element_by_xpath 通过xpath查找
login_form = driver.find_element_by_xpath("//form[@id='loginForm']")
find_element_by_link_text 通过链接文本获取超链接元素
continue_link = driver.find_element_by_link_text('Continue')
find_element_by_partial_link_text 通过部分链接文本获取超链接元素
continue_link = driver.find_element_by_partial_link_text('Conti')
find_element_by_tag_name 通过标签名查找
heading1 = driver.find_element_by_tag_name('h1')
find_element_by_class_name 通过类名查找
content = driver.find_element_by_class_name('content')
find_element_by_css_selector 通过css选择器查找
content = driver.find_element_by_css_selector('p.content')
一次查找多个元素(返回的是元素列表)
find_elements_by_name
find_elements_by_xpath
find_elements_by_link_text
find_elements_by_partial_link_text
find_elements_by_tag_name
find_elements_by_class_name
find_elements_by_css_selector
此外还有两个私有方法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类的其他属性还包括:
ID = "id" XPATH = "xpath" LINK_TEXT = "link text" PARTIAL_LINK_TEXT = "partial link text" NAME = "name" TAG_NAME = "tag name" CLASS_NAME = "class name" CSS_SELECTOR = "css selector"
四、鼠标动作链
有些时候,我们需要再页面上模拟一些鼠标操作,比如双击、右击、拖拽甚至按住不动等,我们可以通过导入ActionChains 类来做到。
导入ActionChains类
from selenium.webdriver import ActionChains
一般样式
ActionChains(driver).操作方法1.操作方法2.....perform()
ActionChains对象上的操作方法存储在对象的队列中,在调用perform()方法时,才会按照队列中的顺序去触发操作
常见方法
click(on_element=None)
- 单击元素。如果没有传入参数,则在当前鼠标位置进行操作
click_and_hold(on_element=None)
- 在元素上单击鼠标左键并按住不放。如果没有传入参数,则在当前鼠标位置进行操作
context_click(on_element=None)
- 在元素上进行右击。如果没有传入参数,则在当前鼠标位置进行操作
double_click(on_element=None)
- 在元素上进行双击。如果没有传入参数,则在当前鼠标位置进行操作
drag_and_drop(source,target)
- 在起始元素上按住鼠标左键,并拖动到目标元素上进行释放
drag_and_drop_by_offset(source,xoffset,yoffset)
- 鼠标点击元素,并按住偏移量进行拖放
move_by_offset(xoffset,yoffset)
- 鼠标从当前位置按照偏移量进行移动
move_to_element(to_element)
- 鼠标移动到元素中间位置
五、页面下拉框处理
我们已经知道了怎样向文本框中输入文字,但是有时候我们会碰到<select> </select>
标签的下拉框。直接点击下拉框中的选项不一定可行。
WebDriver的支持类包括一个叫做 Select的类,他提供有用的方法处理这些内容:
from selenium.webdriver.support.ui import Select select = Select(driver.find_element_by_name('name')) select.select_by_index(index) #index索引从0开始 select.select_by_visible_text("text") #text是在option标签文本的值,是显示在下拉框的值 select.select_by_value(value) #value是option标签的一个属性值,并不是显示在下拉框中的值
取消选择
select.deselect_all()
六、弹窗处理
Selenium WebDriver 内置了对处理弹出对话框的支持。在你的某些动作之后可能会触发弹出对话框,你可以像下面这样访问对话框:
alert = driver.switch_to.alert() # 切换进alert print(alert.text())# 打印alert文本内容 alert.accept()# 关闭弹框(接受) # alert.dismiss() 关闭弹窗(拒绝) # alert.send_keys('selenium') 向弹窗里输入内容
七、页面切换
浏览器一般会打开多个窗口,切换窗口的方法如下:
driver.switch_to.window("窗口名")
或者你也可以在”switch_to_window()”中使用”窗口句柄”来打开它, 知道了这些,你就可以迭代所有已经打开的窗口了:
for handle in driver.window_handles: driver.switch_to_window(handle)
八、访问浏览器历史记录
在浏览历史中前进和后退你可以使用:
driver.forward() driver.back()
九、cookies
获取所有cookies
driver.get_cookies()
删除某个cookie
driver.delete_cookie("CookieName")
删除所有cookies
driver.delete_all_cookies()
十、页面等待(Waits)
现在的大多数的Web应用程序是使用Ajax技术。当一个页面被加载到浏览器时,该页面内的元素可以在不同的时间点被加载。这使得定位元素变得困难,如果元素不再页面之中,会抛出ElementNotVisibleException异常。使用 waits, 我们可以解决这个问题。waits提供了一些操作之间的时间间隔,主要是定位元素或针对该元素的任何其他操作。
Selenium Webdriver 提供两种类型的waits:隐式和显式。显式等待会让WebDriver等待满足一定的条件以后再进一步的执行。而隐式等待让Webdriver等待一定的时间后再才是查找某元素。
显示等待
显式等待是你在代码中定义等待一定条件发生后再进一步执行你的代码。
这里有一些方便的方法让你只等待需要的时间。WebDriverWait结合ExpectedCondition 是实现的一种方式。
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: driver.quit()
在抛出TimeoutException异常之前将等待10秒。 WebDriverWait 默认情况下会每0.5秒调用一次ExpectedCondition直到结果成功返回。 ExpectedCondition成功的返回结果是一个布尔类型的true或是不为null的返回值。
下面是一些内置的等待条件,你可以直接调用这些条件:
title_is title_contains presence_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 invisibility_of_element_located element_to_be_clickable – it is Displayed and Enabled. staleness_of element_to_be_selected element_located_to_be_selected element_selection_state_to_be element_located_selection_state_to_be alert_is_present
隐氏等待
隐式等待比较简单,就是简单地设置一个等待时间,单位为秒。
如果不设置,默认等待时间为0秒。
from selenium import webdriver driver = webdriver.Firefox() driver.implicitly_wait(10) # seconds driver.get("http://somedomain/url_that_delays_loading") myDynamicElement = driver.find_element_by_id("myDynamicElement")
十一、执行JS
可以在加载完成的页面上使用execute_script方法执行js。 比如调用javascript API滚动页面到底部或页面的任何位置
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
十二、传文件到文件上传控件
选择 <input type="file"> 元素并且调用 send_keys() 方法传入要上传文件的路径,可以 是对于测试脚本的相对路径,也可以是绝对路径。