1、selenium是什么呢?
selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法执行javaScript代码的问题。
它可以做什么呢?它可以用几行代码,控制浏览器,做出自动打开、输入、点击等操作,就像是有一个真正的用户在操作一样。
selenium允许让人去手动输入验证码,然后把剩下的操作交给机器。 而对于那些交互复杂、加密复杂的网站,selenium问题简化 ,爬动态网页如爬静态网页一样简单。
安装
pip install selenium # Windows电脑安装selenium
selenium的脚本可以控制所有常见浏览器的操作,在使用之前,需要安装浏览器的驱动。
我推荐的是Chrome浏览器,打开下面的链接,就可以下载Chrome的安装包了,Windows和Mac都有。
国内镜像网站地址
国内镜像网站地址:
http://npm.taobao.org/mirrors/chromedriver/2.38/
设置浏览器引擎
下载chromed浏览器驱动:
把下载好的chromedriver.exe放到python安装路径的scripts目录中即可,注意最新版本是2.38,并非2.9
和以前一样,使用一个新的Python库,首先要调用它。
selenium有点不同,除了调用,还需要设置浏览器引擎。
#本地Chrome浏览器设置方法
from selenium import webdriver # 从selenium库中调用webdriver库
driver_path = r'E:\chromedriver_win32\chromedriver.exe'
driver = webdriver.Chrome(executable_path=driver_path)
#设置引擎为Chrome,真实地打开一个Chrome浏览器
2、基本使用
from selenium import webdriver #用来驱动浏览器的
from selenium.webdriver import ActionChains #破解滑动验证码的时候用,可拖动图片
from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys #键盘按键操作
from selenium.webdriver.support import expected_conditions as EC # 和下面WebDriverWait一起用的
from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素
import time
try:
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
wait = WebDriverWait(driver,10)
input_tag = wait.until(EC.presence_of_element_located((By.ID,'kw')))
input_tag.send_keys('美女')
input_tag.send_keys(Keys.ENTER)
time.sleep(5)
finally:
driver.close()
from selenium import webdriver # 用来驱动浏览器的
from selenium.webdriver.common.by import By # 按照什么方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.support import expected_conditions as EC # 和下面WebDriverWait一起用的
from selenium.webdriver.support.wait import WebDriverWait # 等待页面加载某些元素
import time
option = webdriver.ChromeOptions()
# 通过add_argument为配置添加参数
# 此参数用于跳过 "正受到自动测试软件的控制"
option.add_argument('disable-infobars')
driver = webdriver.Chrome(chrome_options=option)
try:
driver.get('https://china.nba.com/') # 往NBA官网发送get请求
wait = WebDriverWait(driver,10) # 获取等待对象,可等待某个元素10秒
game = wait.until(EC.presence_of_element_located((By.CLASS_NAME,'nav-schedule')))
# 查找赛程标签并点击
game.click()
time.sleep(10)
except:
driver.close()
3、等待元素被加载
'''
1、selenium只是模拟浏览器的行为,而浏览器解析页面是需要时间的(执行css,js),一些元素可能需要过一段时间才能加载出来,为了保证所有元素都能查到,必须等待。
2、等待的方式分两种:
隐式等待:在browser.get('xxx')前就设置,针对所有元素有效
bro.implicitly_wait(10)
显式等待:在browser.get('xxx')之后设置,只针对某个元素有效
不要使用
'''
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys #键盘按键操作
from selenium.webdriver.support import expected_conditions as EC
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()
隐式等待
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys #键盘按键操作
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素
browser=webdriver.Chrome()
browser.get('https://www.baidu.com')
input_tag=browser.find_element_by_id('kw')
input_tag.send_keys('美女')
input_tag.send_keys(Keys.ENTER)
#显式等待:显式地等待某个元素被加载
wait=WebDriverWait(browser,10)
wait.until(EC.presence_of_element_located((By.ID,'content_left')))
contents=browser.find_element(By.CSS_SELECTOR,'#content_left')
print(contents)
browser.close()
显式等待
4、选择器
element和elements
element是查找一个标签 elements是查找所有标签
5、元素定位
find_element_by_tag_name
通过标签名称查找<img><a><P>
此方式可以通过 元素的标签名称 来查找元素,但是一般WEB网站的标签名都是会重复的所有用的并不太方便。
find_element_by_class_name
通过元素的 class 属性选择
browser.find_element_by_class_name("s_ipt")
find_element_by_id
通过元素的 id 属性选择
browser.find_element_by_id("kw")
获取 HTML
page = driver.find_element_by_id('js_content').get_attribute('outerHTML')
find_element_by_name
通过标签的属性选择
browser.find_element_by_name("wd")
find_element_by_css_selector
(#)表示通过 id 属性来定位元素,(.)表示通过 class 属性来定位元素
<p id="intro">This is a paragraph of introduction.</p> find_element_by_css_selector("#intro")
- id组合属性定位
driver.find_element_by_css_selector("input#kw")
- class组合属性定位
driver.find_element_by_css_selector("input.s_ipt")
- 其他属性组合定位
driver.find_element_by_css_selector("input[name='wd']")
- 仅有属性名,没值也可以
driver.find_element_by_css_selector("input[name]")
- 两个其他属性组合定位
driver.find_element_by_css_selector("[name='wd'][autocomplete='off']")
通过后代选择器
#choose_car option 含空格的,后面的元素不必是前面元素的直接子元素,只要在父元素的里面
#choose_car > option 含>键的, 后面的元素必须是前面元素的直接子元素
#ul > ol > li > em 可以是很多级的父子关系
通过组合型
#food > span , p 选择id 为food的所有span子元素和所有的p(包括非food的子元素)
#food > span , #food > p 选择id为food的所有span子元素和所有p子元素
#food > * 选择id为food的所有子元素
兄弟节点的选择(平级关系)
#food + div 只选择id为food紧跟后面的div
#food ~div 选择id为food后面的div或div们,只需要在id的后面,不需要紧跟
方法二 根据元素的属性及属性值来选择元素 :
*[style] 选择所有有stype属性的元素
p[spec=len2] 选择spec属性值只等于len2的p元素
yp[spec='len2 len3' ] 选择spec属性值只等于len2 len3的p元素 有空的值一定要加引号
p[spec*='len2'] 选择spec属性值包含len2的p元素
p[spec^='len2'] 选择spec属性值以len2开头的p元素
p[spec&='len2'] 选择spec属性值以len2结尾的p元素
p[class=special][name=p1] 选择class值等于special,并且name值等于p1的p元素
p:nth-child(1) 选择第一个p元素
p:nth-last-child(1) 选择倒数第一个p元素(要保证最后一个元素是p)
6、find_element_by_link_text
通过链接文本获取超链接
7、find_element_by_partial_link_text
通过链接的部分文本获取超链接
from selenium import webdriver
from selenium.webdriver import ActionChains
import time
option = webdriver.ChromeOptions()
option.add_argument('disable-infobars')
# 通过add_argument为配置添加参数
# 此参数用于跳过 "正受到自动测试软件的控制"
driver = webdriver.Chrome(chrome_options=option)
driver.get('https://qzone.qq.com/')
driver.implicitly_wait(10)
# 1、find_element_by_link_text 通过全局文本去找
driver.switch_to.frame('login_frame')
login_clike = driver.find_element_by_link_text('帐号密码登录').click()
# 2、find_element_by_id 通过id去找
user = driver.find_element_by_id('u')
user.send_keys('1394551891')
pwd = driver.find_element_by_id('p')
pwd.send_keys('zxczxc')
# 3、find_element_by_class_name 根据属性名查找
login = driver.find_element_by_class_name('btn').click()
# 让光标悬浮在个人中心
action = ActionChains(driver).move_to_element(driver.find_element_by_id('slideBlock')).perform()
# 4、find_element_by_partial_link_text 通过局部文本去找
login_tag = driver.find_element_by_partial_link_text('登')
login_tag.click()
# 6、find_element_by_css_selector 根据属性选择器查找
login_btn = driver.find_element_by_css_selector('.btn-login')
login_btn.click()
# 7、find_element_by_tag_name 根据标签名查找
a_s = driver.find_elements_by_tag_name('a')
for a in a_s:
# 打印字数超过10位的文本
if len(a.text) > 10:
print(a.tex
8、find_element_by_xpath("xpath")
XPath 是一门在 XML 文档中查找信息的语言。XPath 用于在 XML 文档中通过元素和属性进行查找。
在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点。
XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。
选区节点
表达式 | 描述 |
---|---|
节点的名字 | 选取此节点中的所有子节点 |
/ | 从根节点选取 |
// | 选取当前节点文档中的任意一个节点 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
from selenium import webdriver
'''
<html><head>
<base href="http://example.com/">
<title>Example website</title>
</head>
<body>
<div id="images">
<a href="image1.html">Name: My image 1 <br><img src="image1_thumb.jpg"></a>
<a href="image2.html">Name: My image 2 <br><img src="image2_thumb.jpg"></a>
<a href="image3.html">Name: My image 3 <br><img src="image3_thumb.jpg"></a>
<a href="image4.html">Name: My image 4 <br><img src="image4_thumb.jpg"></a>
<a href="image5.html">Name: My image 5 <br><img src="image5_thumb.jpg"></a>
</div>
</body></html>
'''
from selenium import webdriver
driver = webdriver.Chrome()
try:
driver.get('https://doc.scrapy.org/en/latest/_static/selectors-sample1.html')
driver.implicitly_wait(3)
# 获取当html标签内的所有子节点
html = driver.find_element_by_xpath('html')
# 查找html中所有的a标签
a_s = html.find_elements_by_tag_name('a')
print(len(a_s))
# 从根节点开始查找html元素
html = driver.find_element_by_xpath('./html')
print(html.tag_name)
# 查找html元素子节点内的body标签,注意只能从根开始查找
body = driver.find_element_by_xpath('html/body')
print(body.tag_name)
# 从当前文档内全局查找,找所有的img标签
imgs = driver.find_elements_by_xpath('//img')
for img in imgs:
print(img.get_attribute('src'))
#查找html元素下的所有a的节点
a_tag_s = driver.find_elements_by_xpath('html//a')
for a in a_tag_s:
print(a.get_attribute('href'))
finally:
driver.close()
获取 cookie
登陆之后,拿到cookie:就可以自己搭建cookie池(requests模块发请求,携带者cookie)
import time bro=webdriver.Chrome(executable_path='./chromedriver') bro.get("https://www.baidu.com") print(bro.get_cookies()) bro.close() # #搭建cookie池和代理池的作用是什么?封ip ,封账号(弄一堆小号,一堆cookie)
无界面浏览器
from selenium.webdriver.chrome.options import Options 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下如果系统不支持可视化不加这条会启动失败 bro=webdriver.Chrome(executable_path='./chromedriver',options=chrome_options) bro.get("https://www.baidu.com") print(bro.get_cookies()) bro.close()
获取标签属性
重点
print(tag.get_attribute('src'))
print(tag.get_attribute('href'))
print(tag.text)
了解
标签属性 | 描述 |
---|---|
id | 标签id |
tag_name | 标签名 |
size | 标签大小 |
location | 标签高宽 |
from selenium import webdriver
from selenium.webdriver.common.by import By # 按照什么方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait # 等待页面加载某些元素
from time import sleep
browser = webdriver.Chrome()
try:
browser.get('https://www.baidu.com/s?wd=美女')
wait = WebDriverWait(browser,10)
img_tag = wait.until(EC.presence_of_element_located((By.CLASS_NAME,'op-img-address-link-imgs')))
#获取标签属性
print(img_tag.get_attribute('src'))
# 获取标签ID,位置,名称,大小(了解)
print(img_tag.id)
print(img_tag.location)
print(img_tag.tag_name)
print(img_tag.size)
# 获取页面上图片长宽 大小
print(img_tag.size['height'], img_tag.size['width'])
print(img_tag.location['x'], img_tag.location['y'])
finally:
browser.close()
元素交互操作
点击 click,清空 clear,输入文字 send_keys
点击清除
from selenium import webdriver #用来驱动浏览器
from selenium.webdriver.common.keys import Keys #键盘按键操作
import time
#获取驱动浏览器配置信息对象,可对其信息进行修改
option = webdriver.ChromeOptions()
# 通过add_argument为配置添加参数
# 此参数用于跳过 "正受到自动测试软件的控制"
option.add_argument('disable-infobars')
driver = webdriver.Chrome(chrome_options=option)
try:
driver.get('https://www.jd.com')
driver.implicitly_wait(10)
input_tag = driver.find_element_by_id('key')
input_tag.send_keys('大炮')
search_button = driver.find_element_by_class_name('button').click()
time.sleep(1)
#清空
input_tag = driver.find_element_by_class_name('text')
input_tag.clear()
input_tag.send_keys('哇哈哈哈')
input_tag.send_keys(Keys.ENTER)
except Exception:
driver.close()
在交互动作比较难实现的时候可以自己写JS(万能方法 )
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys #键盘按键操作
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素
try:
browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.execute_script('alert("hello world")') #打印警告
finally:
browser.close()
模拟浏览器的前进后退
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
driver.get('https://www.taobao.com')
driver.get('https://www.sina.com.cn')
driver.back() # 退到上一个
time.sleep(2)
driver.forward() # 前进下一个
driver.close()
选项卡管理
#选项卡管理:切换选项卡,有js的方式windows.open,有windows快捷键:ctrl+t等,最通用的就是js的方式
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get_cookie('https://baidu.com')
driver.execute_script('window.open()')
print(driver.window_handles) #获取所有的选项卡
driver.switch_to_window(driver.window_handles[1])
driver.get('https://www.taobao.com')
time.sleep(1)
driver.switch_to_window(driver.window_handles[0])
driver.get('https://www.sina.com.cn')
异常处理
from selenium import webdriver
from selenium.common.exceptions import TimeoutException,NoSuchElementException,NoSuchFrameException
try:
driver = webdriver.Chrome()
driver.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
driver.switch_to_frame('iframssseResult')
except TimeoutException as e:
print(e)
except NoSuchFrameException as e:
print(e)
finally:
driver.close()