一。环境部署
1.selenium安装
pip3 install selenium
1.安装浏览器驱动
WebDriver
需要通过浏览器驱动
来与浏览器
交互,以下列出几种常用的浏览器驱动下载地址:
Chrome:
http://chromedriver.storage.googleapis.com/index.html
Firefox:
https://github.com/mozilla/geckodriver/releases
Edge:
https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver
Safari:
https://webkit.org/blog/6900/webdriver-support-in-safari-10
使用不同的浏览器,需要下载对应版本驱动,并且确保驱动文件如chromedriver.exe放到你的系统环境PATH中,这里我将它放到python安装目录下。D:\Python36\chromedriver.exe
selenium思维导图详细使用介绍:
二。元素定位:
<!DOCTYPE html>
<html lang="zh-CN">
<body>
<h1 class="head_title">你好,<span id="world">世界!</span></h1>
<a href="https://www.kancloud.cn/@guanfuchang" target="_blank">我的看云首页</a>
<br/>
<br/>
<div id="login_form" class="login">
用户名:<input name="username" class="ptqa user_name" placeholder="用户名" value="Milton" required/>
密码:<input type="text" name="password" class="ptqa pwd" placeholder="密码" value="ptqa" required/>
地区:
<select class="city">
<option value="gz">广州</option>
<option value="fs">佛山</option>
<option value="mm">茂名</option>
<option value="hb">襄樊</option>
</select> <br>
<br>
<button>提交</button>
<br> </div>
</body>
</html>
环境准备
在同个目录下创建一个find_location.py文件,初始化工作
from selenium import webdriver
import os # 创建Chrome驱动实例
driver = webdriver.Chrome() # 启动浏览器并且导航到指定URL
# 这里为了覆盖更多的元素定位,我自己编写了一个本地的hello.html文件。
file_path = 'file:///' + os.path.abspath('hello.html')
driver.get(file_path)
初始化工作
find_element_by_class_name(self, name):
find_elements_by_class_name(self, name):
# 定位class名称为“head_title"的元素
head_title = driver.find_element_by_class_name("head_title")
print(head_title.text)
通过class定位
find_element_by_id(self, id_):
find_elements_by_id(self, id_):
# 定位id为“world”的元素
world = driver.find_element_by_id("world")
print(world.text)
通过id定位
find_element_by_name(self, name):
find_elements_by_name(self, name):
# 定位name为“username”的元素
username = driver.find_element_by_name("username")
print(username.get_attribute("value"))
通过name属性定位
find_element_by_tag_name(self, name):
find_elements_by_tag_name(self, name):
# 定位标签为<button>的元素
submit_btn = driver.find_element_by_tag_name("button")
print(submit_btn.text)
通过标签名定位
find_element_by_link_text(self, link_text):
find_element_by_partial_link_text(self, link_text): # 定位链接文本完全匹配“我的看云首页”的元素
kancloud = driver.find_element_by_link_text("我的看云首页")
print(kancloud.get_attribute("href")) # 定位链接文本部分匹配“看云首页”的元素
kancloud = driver.find_element_by_partial_link_text("看云首页")
print(kancloud.get_attribute("href"))
通过链接文本定位
find_element_by_xpath(self, xpath):
find_elements_by_xpath(self, xpath): # xpath定位,相对路径定位用户名输入框
username = driver.find_element_by_xpath("//body/div/input")
print(username.get_attribute("value")) # xpath定位,相对路径与属性结合 定位密码输入框
password = driver.find_element_by_xpath("//input[@name='password']")
print(password.get_attribute("value")) # xpath定位,多个属性结合 定位密码输入框
password = driver.find_element_by_xpath("//input[@name='password'][@type='text']")
print(password.get_attribute("value"))
通过xpath定位
find_element_by_css_selector(self, css_selector):
find_elements_by_css_selector(self, css_selector): # css选择器,标签+属性 定位用户名输入框
username = driver.find_element_by_css_selector("input[name='username']")
print(username.get_attribute("value")) 复制
# css选择器,标签+class类名 定位用户名输入框
username = driver.find_element_by_css_selector("input.user_name")
print(username.get_attribute("value")) # css选择器,标签+多个class类名,定位密码输入框,注意不要空格,空格代表下一级子元素
password = driver.find_element_by_css_selector("input.ptqa.pwd")
print(password.get_attribute("value")) # css选择器,id+多个class类名,定位密码输入框
password = driver.find_element_by_css_selector("#login_form .ptqa.pwd")
print(password.get_attribute("value")) # css选择器,多级class类名,定位密码输入框
password = driver.find_element_by_css_selector(".login .ptqa.pwd")
print(password.get_attribute("value")) # css选择器,class类名+属性,定位密码输入框
password = driver.find_element_by_css_selector(".login .ptqa[name='password']")
print(password.get_attribute("value")) #css 选择器,根据父子关系,定位密码输入框
password = driver.find_element_by_css_selector("div[id='login_form']>input[name='password']")
print(password.get_attribute("value")) # css 选择器,根据兄弟关系,定位密码输入框
password = driver.find_element_by_css_selector("input[name='username']+input")
print(password.get_attribute("value"))
通过css选择器定位
上面的所有元素定位 find_element_by_xxx和find_elements_by_xxx调用的结果,实际上都是在调用以下两种方法,我们也可以直接调用一下两种方法即可。 find_element(self, by=By.ID, value=None):
find_elements(self, by=By.ID, value=None): class By(object):
"""
Set of supported locator strategies.
""" 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" 例如:
from selenium.webdriver.common.by import By
# 根据id,定位id为“world”的元素
world = driver.find_element(By.ID,"world")
print(world.text) # xpath定位,相对路径与属性结合 定位密码输入框
password = driver.find_element(By.XPATH,"//input[@name='password']")
print(password.get_attribute("value")) # css选择器,标签+属性 定位用户名输入框
username = driver.find_element(By.CSS_SELECTOR,"input[name='username']")
print(username.get_attribute("value"))
通用的终极定位语法
三。元素操作:
清除文本输入框
clear(self) 点击元素
click(self) 提交表单
submit(self) 发送信息
send_keys(self, *value) 获取元素的文本
text
WebElement 中常见的元素操作
获取元素属性
get_attribute(self, name) 判断元素可见
is_displayed(self) 判断元素可用
is_enabled(self) 判断元素是否被选中
is_selected(self)
WebElement 中常见的元素属性
获取元素位置
location 获取元素大小
size 获取元素的文本
text
WebElement 中常见的属性方法
ActionChains中提供一些复杂操作,如鼠标移动,鼠标按钮操作,按键操作和上下文菜单交互等,这些操作在实际运用中其实复杂操作并不常用,这里只简单介绍一个元素拖拽的例子,其他方法,请自行查看源码。 element = driver.find_element_by_name("source")
target = driver.find_element_by_name("target") from selenium.webdriver import ActionChains
action_chains = ActionChains(driver)
# 拖拽(在元素A上按住鼠标左键不放,拖动到元素B上,然后松开鼠标)
action_chains.drag_and_drop(element, target).perform()
ActionChains 中的复杂操作
四。浏览器当行操作:
五。元素等待;
六。 示例演示
获取页面源码数据:
通过page_source
属性可以获取网页的源代码,接着就可以使用解析库(如正则表达式、Beautiful Soup、pyquery等)来提取信息了。
动作链:它们没有特定的执行对象,比如鼠标拖曳、键盘按键等,这些动作用另一种方式来执行,那就是动作链。
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.perform() #执行动作链
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()
示例:实现一个节点的拖曳操作,将某个节点从一处拖曳到另外一处
浏览器前进后退演示:
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()
需要:模拟浏览器的前进后退
Cookie处理:
使用Selenium,还可以方便地对Cookies进行操作,例如获取、添加、删除Cookies等。示例如下:
from selenium import webdriver browser = webdriver.Chrome()
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())
cookie操作演示
异常处理:
from selenium import webdriver
from selenium.common.exceptions import TimeoutException,NoSuchElementException,NoSuchFrameException 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()
异常处理演示
selenium实现模拟百度搜索功能
from selenium import webdriver
from time import sleep #实例化一个浏览器对象
bro = webdriver.Chrome(executable_path='./chromedriver.exe')
#基于url发起请求
sleep(2)
bro.get('https://www.baidu.com/')
#实现页面标签的定位
sleep(2)
input_tag = bro.find_element_by_id('kw')
input_tag.send_keys('周杰伦')
sleep(2)
btn = bro.find_element_by_id('su')
btn.click()
sleep(3)
#获取当前浏览器打开的页面对应的源码数据
page_text = bro.page_source
print(page_text)
sleep(2)
bro.quit()
需求:使用selenium在百度上进行数据搜索
selenium实现无可视化展示
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
from time import sleep
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu') #实例化一个浏览器对象
bro = webdriver.Chrome(executable_path='./chromedriver.exe',chrome_options=chrome_options)
#基于url发起请求
sleep(2)
bro.get('https://www.baidu.com/')
#实现页面标签的定位
sleep(2)
input_tag = bro.find_element_by_id('kw')
input_tag.send_keys('周杰伦')
sleep(2)
btn = bro.find_element_by_id('su')
btn.click()
sleep(3)
bro.save_screenshot('./1.jpg') # 进行截图保存
#获取当前浏览器打开的页面对应的源码数据
page_text = bro.page_source # 爬取页面源码
print(page_text)
sleep(2)
bro.quit()
使用无可视化界面搜索并截图和爬取页面源码
加载js文件实现动态加载浏览器数据
滚轮向下滑动一屏的高度:window.scrollTo(0,document.body.scrollHeight)
from selenium import webdriver
from time import sleep bro = webdriver.Chrome(executable_path='./chromedriver.exe')
# bro = webdriver.PhantomJS(executable_path = '')
bro.get(url='https://news.163.com/domestic/') # 线程阻塞代码,上一个未执行完,下一个是不会执行的
sleep(2)
#让滚轮向下滑动
js = 'window.scrollTo(0,document.body.scrollHeight)'
bro.execute_script(js) # 非阻塞代码异步实现,所以这块要给一个暂停时间防止网速不好或者一些因素引起的问题
sleep(2)
bro.execute_script(js)
sleep(2)
bro.execute_script(js)
sleep(2) a_tag = bro.find_element_by_xpath('/html/body/div/div[3]/div[4]/div[1]/div/div/a')
a_tag.click()
sleep(2) #源码数据就包含了所有的新闻数据
page_text = bro.page_source with open('./wangyi.html','w',encoding='utf-8') as fp:
fp.write(page_text)
需求:网易新闻,实现滚轮滑动加载更多数据
这里引出一个*面浏览器:phantomjs实现了一个*面的webkit浏览器。虽然没有界面,但dom渲染、js运行、网络访问、canvas/svg绘制等功能都很完备,在页面抓取、页面输出、自动化测试等方面有广泛的应用。
驱动包百度共享下载:链接:https://pan.baidu.com/s/15j5RpkVAryKRa_VFrjdqDw 提取码:zptn
from selenium import webdriver
from time import sleep # bro = webdriver.Chrome(executable_path='./chromedriver.exe')
bro = webdriver.PhantomJS(executable_path = './phantomjs.exe') #这里输入的是phantomjs.exe驱动路径
bro.get(url='https://news.163.com/domestic/') # 线程阻塞代码,上一个未执行完,下一个是不会执行的
sleep(2)
#让滚轮向下滑动
js = 'window.scrollTo(0,document.body.scrollHeight)'
bro.execute_script(js) # 非阻塞代码异步实现,所以这块要给一个暂停时间防止网速不好或者一些因素引起的问题
sleep(2)
bro.execute_script(js)
sleep(2)
bro.execute_script(js)
sleep(2) a_tag = bro.find_element_by_xpath('/html/body/div/div[3]/div[4]/div[1]/div/div/a')
a_tag.click()
sleep(2) #源码数据就包含了所有的新闻数据
page_text = bro.page_source with open('./wangyi.html','w',encoding='utf-8') as fp:
fp.write(page_text)
需求:通过*面浏览器爬取数据
PhantomJS为用户提供了一个截屏的功能,使用save_screenshot函数实现
from selenium import webdriver
import time # phantomjs路径
path = r'PhantomJS驱动路径'
browser = webdriver.PhantomJS(path) # 打开百度
url = 'http://www.baidu.com/'
browser.get(url)
time.sleep(3)
browser.save_screenshot(r'phantomjs\baidu.png') # 查找input输入框
my_input = browser.find_element_by_id('kw')
# 往框里面写文字
my_input.send_keys('美女')
time.sleep(3)
#截屏
browser.save_screenshot(r'phantomjs\meinv.png') # 查找搜索按钮
button = browser.find_elements_by_class_name('s_btn')[0]
button.click()
time.sleep(3)
browser.save_screenshot(r'phantomjs\show.png')
time.sleep(3)
browser.quit()
需求:PhantomJS截图演示
selenium实现切换iframe:
from selenium import webdriver
from time import sleep
bro = webdriver.Chrome(executable_path='./chromedriver.exe')
url = 'https://qzone.qq.com/'
bro.get(url=url)
#将当前页面切换到了指定的iframe中,后续才可以定位到iframe中存在的标签
bro.switch_to.frame('login_frame')
a_tag = bro.find_element_by_id('switcher_plogin')
a_tag.click()
sleep(3) bro.quit()
需求:模拟QQ空间登录切换iframe
import requests
from selenium import webdriver
from lxml import etree
import time driver = webdriver.Chrome(executable_path='/Users/bobo/Desktop/chromedriver')
driver.get('https://qzone.qq.com/')
#在web 应用中经常会遇到frame 嵌套页面的应用,使用WebDriver 每次只能在一个页面上识别元素,对于frame 嵌套内的页面上的元素,直接定位是定位是定位不到的。这个时候就需要通过switch_to_frame()方法将当前定位的主体切换了frame 里。
driver.switch_to.frame('login_frame')
driver.find_element_by_id('switcher_plogin').click() #driver.find_element_by_id('u').clear()
driver.find_element_by_id('u').send_keys('') #这里填写你的QQ号
#driver.find_element_by_id('p').clear()
driver.find_element_by_id('p').send_keys('xxxxxx') #这里填写你的QQ密码 driver.find_element_by_id('login_button').click()
time.sleep(2)
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(2)
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(2)
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
time.sleep(2)
page_text = driver.page_source tree = etree.HTML(page_text)
#执行解析操作
li_list = tree.xpath('//ul[@id="feed_friend_list"]/li')
for li in li_list:
text_list = li.xpath('.//div[@class="f-info"]//text()|.//div[@class="f-info qz_info_cut"]//text()')
text = ''.join(text_list)
print(text+'\n\n\n') driver.close()
需求:登录QQ空间,爬取数据代码
selenium规避被检测识别
现在不少大网站有对selenium采取了监测机制。比如正常情况下我们用浏览器访问淘宝等网站的 window.navigator.webdriver的值为
undefined。而使用selenium访问则该值为true。那么如何解决这个问题呢? 只需要设置Chromedriver的启动参数即可解决问题。在启动Chromedriver之前,为Chrome开启实验性功能参数excludeSwitches,它的值为['enable-automation'],完整代码如下:
from selenium.webdriver import Chrome
from selenium.webdriver import ChromeOptions option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
driver = Chrome(options=option)
from selenium import webdriver
from time import sleep
import time if __name__ == '__main__':
url = 'https://movie.douban.com/typerank?type_name=%E6%81%90%E6%80%96&type=20&interval_id=100:90&action='
# 发起请求前,可以让url表示的页面动态加载出更多的数据
path = r'C:\Users\Administrator\Desktop\爬虫授课\day05\ziliao\phantomjs-2.1.1-windows\bin\phantomjs.exe'
# 创建*面的浏览器对象
bro = webdriver.PhantomJS(path)
# 发起url请求
bro.get(url)
time.sleep(3)
# 截图
bro.save_screenshot('1.png') # 执行js代码(让滚动条向下偏移n个像素(作用:动态加载了更多的电影信息))
js = 'window.scrollTo(0,document.body.scrollHeight)'
bro.execute_script(js) # 该函数可以执行一组字符串形式的js代码
time.sleep(2) bro.execute_script(js) # 该函数可以执行一组字符串形式的js代码
time.sleep(2)
bro.save_screenshot('2.png')
time.sleep(2)
# 使用爬虫程序爬去当前url中的内容
html_source = bro.page_source # 该属性可以获取当前浏览器的当前页的源码(html)
with open('./source.html', 'w', encoding='utf-8') as fp:
fp.write(html_source)
bro.quit()
需求:使用懒加载爬取豆瓣网中的电影信息演示代码