文章目录
selenium使用
介绍
selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器
使用
1 下载驱动
谷歌浏览器驱动
注意:驱动要跟浏览器版本对应(可以稍低一点,但不能高)
- 下载完解压即可
2 下载selenium模块
pip3 install selenium
Selenium支持非常多的浏览器,如Chrome、Firefox、Edge等,还有Android、BlackBerry等手机端的浏览器。另外,也支持无界面浏览器PhantomJS。
from` `selenium ``import` `webdriver`` ` `browser ``=` `webdriver.Chrome()``browser ``=` `webdriver.Firefox()``browser ``=` `webdriver.Edge()``browser ``=` `webdriver.PhantomJS()``browser ``=` `webdriver.Safari()
3. 简单使用
from selenium import webdriver
import time
# 使用time模块主要是加入等待,防止页面还没加载,程序就跑完了
# 获得一个谷歌浏览器对象
bro = webdriver.Chrome(executable_path='./chromedriver.exe')
time.sleep(2)
bro.get('https://www.baidu.com/') # 在地址栏里输入百度
time.sleep(2)
print(bro.page_source) # 返回页面源码
time.sleep(2)
# 关闭浏览器
bro.close()
# 模拟百度搜索
from selenium import webdriver
import time
bro = webdriver.Chrome(executable_path='./chromedriver.exe')
bro.get('https://www.baidu.com/') # 在地址栏里输入百度
time.sleep(0.01)
# 找到搜索框
input_k = bro.find_element_by_id('kw')
input_k.send_keys('美女') # 在框里写入美女
time.sleep(2)
# 找到搜索按钮
sou = bro.find_element_by_id('su')
sou.click() # 点击按钮
time.sleep(4)
bro.close()
4. selenium方法介绍
4.1 元素定位
webdriver 提供了一系列的元素定位方法,常用的有以下几种:
元素 | 方法 |
---|---|
id | find_element_by_id() |
name | find_element_by_name() |
class name | find_element_by_class_name() |
tag name | find_element_by_tag_name() |
link text | find_element_by_link_text() |
link text | find_element_by_partial_link_text() |
link text | find_element_by_xpath() |
css selector | find_element_by_css_selector() |
注意:
-
find_element_by_xxx找的是第一个符合条件的标签,find_elements_by_xxx找的是所有符合条件的标签。
-
根据ID、CSS选择器和XPath获取,它们返回的结果完全一致。
-
另外,Selenium还提供了通用方法
find_element()
,它需要传入两个参数:查找方式By.
和值。实际上,它就是find_element_by_id()
这种方法的通用函数版本,比如find_element_by_id(id)
就等价于find_element(By.ID, id)
,二者得到的结果完全一致。
4.2 节点交互
Selenium可以驱动浏览器来执行一些操作,也就是说可以让浏览器模拟执行一些动作。比较常见的用法有:输入文字时用
send_keys()
方法,清空文字时用clear()
方法,点击按钮时用click()
方法。
常用:
clear()——如果是文本输入框,就清除文本。
click()——单击
send_keys("值")——文字输入
了解:
get_attribute(name)——获取元素的属性值
get_property(name)——获取元素的给定属性值
is_displayed()——元素对用户是否可见
is_enabled()——是否启用元素
is_selected()——是否选择了复选框或者单选框
screenshot(filename)——将当前元素的屏幕截图保存到png文件中
示例:element.screenshot('/Screenshots / foo.png')
submit()——提交表格
value_of_css_property(属性名)——获取css属性的值
text——元素的文本
tag_name——当前元素的标签名
size——元素的大小
location——元素在当前可渲染画布的位置
location_once_scrolled_into_view——用来找到元素在屏幕上的位置。(位置是屏幕左上角的位置,返回None表示不可见)
screenshot_as_base64——以base64编码字符串的形式获取当前元素的屏幕快照
示例:img_b64 = element.screenshot_as_base64
screenshot_as_png——二进制数据获取当前元素的屏幕截图
parent——(官网原文)Internal reference to the WebDriver instance this element was found from
rect——(官网原文)A dictionary with the size and location of the element
4.3 动作链
在上面的实例中,一些交互动作都是针对某个节点执行的。比如,对于输入框,我们就调用它的输入文字和清空文字方法;对于按钮,就调用它的点击方法。其实,还有另外一些操作,它们没有特定的执行对象,比如鼠标拖曳、键盘按键等,这些动作用另一种方式来执行,那就是动作链。
比如,现在实现一个节点的拖曳操作,将某个节点从一处拖曳到另外一处,可以这样实现:
from selenium import webdriver
from selenium.webdriver import ActionChains
import time
browser = webdriver.Chrome()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame('iframeResult')
source = browser.find_element_by_css_selector('#draggable')
target = browser.find_element_by_css_selector('#droppable')
actions = ActionChains(browser)
# actions.drag_and_drop(source, target)
actions.click_and_hold(source)
time.sleep(3)
for i in range(5):
actions.move_by_offset(xoffset=17,yoffset=0).perform()
time.sleep(0.5)
actions.release()
4.4 执行JavaScript
对于某些操作,Selenium API并没有提供。比如,下拉进度条,它可以直接模拟运行JavaScript,此时使用execute_script()
方法即可实现,代码如下:
from selenium import webdriver
browser = webdriver.Chrome()
browser.get('https://www.jd.com/')
browser.excute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("123")')
4.5 获取节点信息
通过
page_source
属性可以获取网页的源代码,接着就可以使用解析库(如正则表达式、Beautiful Soup、pyquery等)来提取信息了。不过,既然Selenium已经提供了选择节点的方法,返回的是
WebElement
类型,那么它也有相关的方法和属性来直接提取节点信息,如属性、文本等。这样的话,我们就可以不用通过解析源代码来提取信息了,非常方便。
#获取标签属性,
print(tag.get_attribute('src'))
#获取标签ID,位置,名称,大小(了解)
print(tag.id)
print(tag.location)
print(tag.tag_name)
print(tag.size)
4.6 延时等待
在Selenium中,
get()
方法会在网页框架加载结束后结束执行,此时如果获取page_source
,可能并不是浏览器完全加载完成的页面,如果某些页面有额外的Ajax请求,我们在网页源代码中也不一定能成功获取到。所以,这里需要延时等待一定时间,确保节点已经加载出来。这里等待的方式有两种:一种是隐式等待,一种是显式等待。
- 隐式等待(推荐使用):
当使用隐式等待执行测试的时候,如果Selenium没有在DOM中找到节点,将继续等待,超出设定时间后,则抛出找不到节点的异常。换句话说,当查找节点而节点并没有立即出现的时候,隐式等待将等待一段时间再查找DOM,默认的时间是0。示例如下:
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys # 键盘按键操作
from selenium.webdriver.support.wait import WebDriverWait # 等待页面加载某些元素
browser=webdriver.Chrome()
# 隐式等待:在查找所有元素时,如果尚未被加载,则等10秒
browser.implicitly_wait(10)
browser.get('https://www.baidu.com')
input_tag=browser.find_element_by_id('kw')
input_tag.send_keys('美女')
input_tag.send_keys(Keys.ENTER)
contents=browser.find_element_by_id('content_left') # 没有等待环节而直接查找,找不到则会报错
print(contents)
browser.close()
- 显示等待:
隐式等待的效果其实并没有那么好,因为我们只规定了一个固定时间,而页面的加载时间会受到网络条件的影响。这里还有一种更合适的显式等待方法,它指定要查找的节点,然后指定一个最长等待时间。如果在规定时间内加载出来了这个节点,就返回查找的节点;如果到了规定时间依然没有加载出该节点,则抛出超时异常。
# 用法 等待id为content_left的标签 10s
wait=WebDriverWait(browser,10)
wait.until(EC.presence_of_element_located((By.ID,'content_left')))
4.7 前进后退
Selenium也可以完成前进后退操作,它使用back()
方法后退,使用forward()
方法前进。
#模拟浏览器的前进后退
import time
from selenium import webdriver
browser=webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.get('https://www.taobao.com')
browser.get('http://www.sina.com.cn/')
browser.back()
time.sleep(10)
browser.forward()
browser.close()
4.8 无界面浏览器(phantomjs)
# 谷歌浏览器支持不打开页面
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
chrome_options = Options()
chrome_options.add_argument('window-size=1920x3000') # 指定浏览器分辨率
chrome_options.add_argument('--disable-gpu') # 谷歌文档提到需要加上这个属性来规避bug
chrome_options.add_argument('--hide-scrollbars') # 隐藏滚动条, 应对一些特殊页面
chrome_options.add_argument('blink-settings=imagesEnabled=false') # 不加载图片, 提升速度
chrome_options.add_argument('--headless') # 浏览器不提供可视化页面. linux下如果系统不支持可视化不加这条会启动失败
4.9 Cookies
使用Selenium,还可以方便地对Cookies进行操作,例如获取、添加、删除Cookies等。示例如下:
browser = webdriver.Chrome(executable_path='./chromedriver.exe')
browser.get('https://www.zhihu.com/explore')
print(browser.get_cookies())
browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'germey'})
print(browser.get_cookies())
browser.delete_all_cookies()
print(browser.get_cookies())
browser.close()
4.10 异常处理
try:
# 写出操作代码
browser=webdriver.Chrome()
browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
browser.switch_to.frame('iframssseResult')
except TimeoutException as e:
print(e)
except NoSuchFrameException as e:
print(e)
finally:
browser.close()