目录
基本用法
运行本例之前,需要将chromedriver或chromedriver.exe文件放在当前目录的webdriver子目录中。
运行程序,会立刻启动Chrome浏览器,并打开京东首页,然后在京东首页上方的搜索框中输入“Python从菜鸟到高手”
WebDriverWait类,该类是为了在执行的过程中等待一段时间,这里设置为4秒。、
按Enter键后,并不一定马上显示搜索结果,需要有一定的延长,但python程序不会等待搜索结果出来再往下执行,python程序会一直执行下去,所以如果不等待一定时间,就会造成python程序已经运行到处理搜索结果页面的位置时,搜索结果页面还没显示出来。所以就需要使用WebDriverWait类的until方法判断结果页面是否显示完成。
判断搜索结果页面是否显示完全:如果搜索页面加载完成,页面中所有的节点肯定已经加载完成了,所以只要随便获取页面中的某个节点,如果获取成功,说明已经加载完成。
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
browser=webdriver.Chrome('D:\chromedriver_win32\chromedriver')
try:
# 打开京东
browser.get('https://www.jd.com/')
# 根据id属性的值查找搜索框
input1=browser.find_element(By.ID,'key')
# 使用send_keys方法向搜索框输入"python从菜鸟到高明"文本
input1.send_keys('python从菜鸟到高明')
# 使用send_keys方法模拟按下<Enter>键
input1.send_keys(Keys.ENTER)
# 创建WebDriverWait对象,设置最长等待时间(4秒)
wait=WebDriverWait(browser,4)
# 等待搜索页面显示(通过查找id为goodsList的节点判断搜索页面是否显示)
wait.until(ec.presence_of_all_elements_located((By.ID,'J_goodsList')))
# 显示搜索页面的标题
print(browser.title)
# 显示搜索页面的URL
print(browser.current_url)
# 显示搜索页面的代码
print(browser.page_source)
# 关闭浏览器
browser.close()
except Exception as e:
print(e)
browser.close()
查找节点
查找单个节点
看源码可知,browser.find_element方法支持(id,name,class_name元素定位)
def find_element(self, by=By.ID, value: Optional[str] = None)
if by == By.ID:
by = By.CSS_SELECTOR
value = '[id="%s"]' % value
elif by == By.CLASS_NAME:
by = By.CSS_SELECTOR
value = ".%s" % value
elif by == By.NAME:
by = By.CSS_SELECTOR
value = '[name="%s"]' % value
查找多个节点
方法同上
区别:browser.find_elements返回一个列表,包含符合条件的所有节点,如果没有符合条件的节点,就会返回空列表(长度为0的列表)
节点交互
点击
click()
模拟鼠标移动
使用actions.move_to_element方法,以下为ActionChains类常用方法
1、perform():执行所有ActionChains中存储的行为
2、context_click():右击
3、double_click():双击
4、move_to_element():悬停
5、drag_and_drop(source, target):拖动
最后都必须调用perform方法才能生效
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
import time
browser=webdriver.Chrome('D:\chromedriver_win32\chromedriver')
try:
browser.get('https://www.jd.com/')
# 创建ActionChains对象
actions=ActionChains(browser)
# 通过CSS选择器查找所有class属性值为cate_menu_item的li节点,每一个li节点是一个二级导航菜单
li_list=browser.find_elements(By.CSS_SELECTOR,'.cate_menu_item')
for li in li_list:
actions.move_to_element(li).perform()
time.sleep(1)
except Exception as e:
print(e)
browser.close()
拖动节点
使用drag_and_drop方法拖到节点
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
browser=webdriver.Chrome('D:\chromedriver_win32\chromedriver')
try:
browser.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
# 切换到id属性值为iframeResult的iframe节点上
browser.switch_to.frame('iframeResult')
# 使用CSS选择器获取id属性值为draggable的拖动节点
sourse=browser.find_element(By.CSS_SELECTOR,'#draggable')
# 使用CSS选择器获取id属性值为droppable的接收节点
target = browser.find_element(By.CSS_SELECTOR, '#droppable')
# 创建ActionChains对象
actions=ActionChains(browser)
# 调用drag_and_drop方法拖动节点
actions.drag_and_drop(sourse,target)
# 调用perfrom方法让拖动生效
actions.perform()
except Exception as e:
print(e)
browser.close()
执行JavaScript代码
有些操作Selenium没有提供相应的API,例如下拉页面
可以使用Selenium得execute_script方法直接运行JavaScript代码,便于扩展Selenium功能
from selenium import webdriver
browser=webdriver.Chrome('D:\chromedriver_win32\chromedriver')
browser.get('https://www.jd.com/')
# 将京东商城首页滚动到最底端
browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
# 弹出对话框
browser.execute_async_script('alert("已经到最底端")')
time.sleep(10)
获取节点信息
如节点位置(相当于页面绝对坐标)、节点名称、节点尺寸(高和宽)、节点属性值
from selenium import webdriver
from selenium.webdriver.common.by import By
options=webdriver.ChromeOptions()
# 添加参数,不然Chrome浏览器显示,只在后台运行
options.add_argument('headless')
browser=webdriver.Chrome('D:\chromedriver_win32\chromedriver',chrome_options=options)
browser.get('https://www.jd.com/')
# 查找页面中id属性值为navitems-group1的第1个节点(是一个ul节点)
ul=browser.find_element(By.ID,'navitems-group1')
# 输出节点的文本
print(ul.text)
# 输出节点内部使用的id,注意,不是id属性值
print('id','=',ul.id)
# 输出节点的位置(相对于页面的绝对坐标)
print('location','=',ul.location)
# 输出节点的名称
print('tag_name','=',ul.tag_name)
# 输出节点的尺寸
print('size','=',ul.size)
# 搜索该节点内的所有名为li的节点
li_list=ul.find_elements(By.TAG_NAME,'li')
for li in li_list:
# 输出li的类型
print(type(li))
# 输出li节点的文本和class属性值,如果属性没找到,返回None
print('<',li.text,'>','class=',li.get_attribute('class'))
# 查找li节点内名为a的子节点
a=li.find_element(By.TAG_NAME,'a')
# 输出a节点的href属性值
print('href','=',a.get_attribute('class'))
browser.close()
基于selenium的爬虫通常会加上headless选项、这样爬取数据过程就不会弹出Chrome浏览器,但是他会在后台进行页面加载、数据提取等工作
管理cookie
获取cookie,添加cookie,删除cookie
from selenium import webdriver
browser=webdriver.Chrome('D:\chromedriver_win32\chromedriver')
browser.get('https://www.jd.com/')
# 获取cookie列表
print(browser.get_cookies())
# 添加新的cookie
browser.add_cookie({'name':'name','value':'jd','domain':'www.jd.com'})
print(browser.get_cookies())
# 删除所有的cookie
browser.delete_all_cookies()
print(browser.get_cookies())
改变节点属性值
selenium没有改变节点属性的API,所以要通过JavaScript代码改变
通过selenium获取的节点可以直接作为DOM使用,意味着在JavaScript代码使用查找到的节点
execute_script方法第1个参数用于指定JavaScript代码,后面的可变参数,可以为JavaScript代码传递参数。通过arguments变量获取每一个参数值,例如arguments[0]第一个参数arguments[0]第二个参数,以此类推
例子1:使用JavaScript代码改变百度搜索按钮的位置,让这个按钮多个位置移动,2秒一次
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
browser=webdriver.Chrome('D:\chromedriver_win32\chromedriver')
browser.get('https://www.baidu.com')
# 查找百度搜索按钮
search_button=browser.find_element(By.ID,'su')
# 定义搜索按钮可以移动的x坐标的位置
x_positions=[50,90,130,170]
# 定义搜索按钮可以移动的y坐标的位置,与x坐标列表中元素的个数要相等
y_positions=[100,120,160,90]
# 迭代位置列表,每隔2秒移动一次搜索按钮
for i in range(len(x_positions)):
# 用于移动搜索按钮的JavaScript代码,arguments[0]就是搜索按钮对应的DOM
js="""
arguments[0].style.position="absolute";
arguments[0].style.left="{}px"
arguments[0].style.top="{}px";
""".format(x_positions[i],y_positions[i])
# 执行JavaScript代码,并开始移动搜索按钮
browser.execute_script(js,search_button)
time.sleep(2)
例子2:修改页面文本以及链接
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
browser=webdriver.Chrome('D:\chromedriver_win32\chromedriver')
browser.get('https://www.jd.com')
# 查找id属性值为navitems-group1的节点
ul=browser.find_element(By.ID,'navitems-group1')
# 查找该节点下所有名为li的子节点
li_list=ul.find_elements(By.TAG_NAME,'li')
# 查找第1个li节点中第一个名为a的子节点
a1=li_list[0].find_element(By.TAG_NAME,'a')
# 查找第2个li节点中第一个名为a的子节点
a2=li_list[1].find_element(By.TAG_NAME,'a')
# 下面的JavaScript代码用于修改上面查找到的两个a节点的文本和链接(href属性值)
js="""
arguments[0].text='Python从菜鸟到高手'
arguments[0].href='https://item.jd.com/12417265.html'
arguments[1].text='极客起源'
arguments[1].href='https://geekori.com'
"""
browser.execute_script(js,a1,a2)
time.sleep(5)