本系列文档用于对Python爬虫技术的学习进行简单的教程讲解,巩固自己技术知识的同时,万一一不小心又正好对你有用那就更好了。
Python 版本是3.7.4
前面一篇文章讲了selenium的基础用法,这一篇我们讲述一些selenium比较高级的用法。
上面的示例代码在运行中都会弹出一个浏览器窗口,有时候会很不方便,这就需要我们不弹出窗口爬取数据。
Headless Chrome 是Chrome浏览器的无界面形态,可以在不打开浏览器的前提下,使用所有Chrome支持的特性,在命令行中运行你的脚本。以前在爬虫要使用Phantomjs来实现这些功能,但Phantomjs已经暂停开发,现在可以使用Headless Chrome来代替。
示例代码如下:
# 引入所需库
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# 定制option
chrome_options = Options()
# 设置无头
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
# 声明定义chromedriver路径
path = r'E:\Python_Code\s1\chromedriver_win32\chromedriver.exe'
browser = webdriver.Chrome(executable_path=path, options=chrome_options)
# 打开百度
url = 'http://www.baidu.com/'
browser.get(url)
time.sleep(3)
# 保存页面截图
browser.save_screenshot('baidu.png')
browser.quit()
from selenium import webdriver
# 进入浏览器设置
options = webdriver.ChromeOptions()
# 设置中文
options.add_argument('lang=zh_CN.UTF-8')
# 更换头部
options.add_argument('user-agent="Mozilla/5.0 (iPod; U; CPU iPhone OS 2_1 like Mac OS X; ja-jp) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5F137 Safari/525.20"')
browser = webdriver.Chrome(chrome_options=options)
url = "https://httpbin.org/get?show_env=1"
browser.get(url)
browser.quit()
有时候频繁爬取一些网页,服务器发现你是爬虫后会疯掉你的ip地址。这时我们可以更改代理ip来解决这个问题。更改代理ip,不同的浏览器有不同的实现方式,这里以Chrome
浏览器为例来讲解:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument('--proxy-server-http://123.56.74.13:8080')
# 声明定义chromedriver路径
path = r'E:\Python_Code\s1\chromedriver_win32\chromedriver.exe'
# 实例化Chrome
driver = webdriver.Chrome(executable_path=path, options=options)
driver.get('https://httpbin.org/ip')
启动参数 | 作用 |
---|---|
–user-agent=”“ | 设置请求头的User-Agent |
–window-size=长,宽 | 设置浏览器分辨率 |
–headless | 无界面运行 |
–start-maximized | 最大化运行 |
–incognito | 隐身模式 |
–disable-javascript | 禁用javascript |
–disable-infobars | 禁用浏览器正在被自动化程序控制的提示 |
更多参数说明:https://peter.sh/experiments/chromium-command-line-switches/
cookie
:for cookie in driver.get_cookies():
print(cookie)
cookie = driver.get_cookie('BD_HOME')
print(cookie)
driver.delete_all_cookies()
driver.delete_cookie('BD_HOME')
示例代码如下:
# 引入所需库
import time
from selenium import webdriver
# 声明定义chromedriver路径
path = r'E:\Python_Code\s1\chromedriver_win32\chromedriver.exe'
# 实例化Chrome
# 如果时其他浏览器需要实例化为对应的对象,例如火狐webdriver.firefox()
driver = webdriver.Chrome(path)
# 操作输入框
driver.get('https://www.baidu.com/')
time.sleep(2)
# 获取所有cookie
for cookie in driver.get_cookies():
print(cookie)
# 根据cookie的key获取value
# cookie = driver.get_cookie('BD_HOME')
# print(cookie)
# 删除所有cookie
# driver.delete_all_cookies()
# 删除某个cookie
# driver.delete_cookie('BD_HOME')
driver.close()
使用add_cookie(cookie_dict)
方法给当前会话可以添加一个cookie;cookie_dict
是一个字典对象,必须要有name
和value
两个键,可选的键有:path
, domain
, secure
, expiry
。例如:
driver.add_cookie({‘name’ : ‘foo’, ‘value’ : ‘bar’})
driver.add_cookie({‘name’ : ‘foo’, ‘value’ : ‘bar’, ‘path’ : ‘/’})
driver.add_cookie({‘name’ : ‘foo’, ‘value’ : ‘bar’, ‘path’ : ‘/’, ‘secure’:True})
使用示例代码如下:
from selenium import webdriver
browser = webdriver.Chrome()
url = "https://www.baidu.com/"
browser.get(url)
# 通过js新打开一个窗口
newwindow='window.open("https://www.baidu.com");'
# 删除原来的cookie
browser.delete_all_cookies()
# 携带cookie打开
browser.add_cookie({'name':'ABC','value':'DEF'})
# 通过js新打开一个窗口
browser.execute_script(newwindow)
input("查看效果")
browser.quit()
有时候在也页面中的操作可能要有很多很多,那么这时候可以使用鼠标行为链类ActionChains
来完成。比如现在要将鼠标移动到某个元素上并执行点击事件,那么示例代码如下:
import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
# 声明定义chromedriver路径
path = r'E:\Python_Code\s1\chromedriver_win32\chromedriver.exe'
# 实例化Chrome
# 如果时其他浏览器需要实例化为对应的对象,例如火狐webdriver.firefox()
driver = webdriver.Chrome(path)
# 操作输入框
driver.get('https://www.baidu.com/')
time.sleep(2)
# 根据id获取元素
input_kw = driver.find_element_by_id('kw')
submit_btn = driver.find_element_by_id('su')
# 实例化Action
action = ActionChains(driver)
action.move_to_element(input_kw)
action.send_keys_to_element(input_kw, 'python')
action.move_to_element(submit_btn)
action.click(submit_btn)
# 执行上述操作
action.perform()
time.sleep(5)
driver.close()
现在的网页越来越多采用了Ajax技术,这样程序便不能确定合适某个元素才完成加载出来。如果实际页面等待事件过长导致某个DOM元素还没出来,但是你的代码直接使用了这个页面元素,那么就会抛出NullPointer的异常。为了解决这个问题,所以Selenium提供了两种等待方式,一种是隐式等待、一种是显示等待。
隐式等待指的是,在webdriver中进行find_element_*
这一类查找操作时,如果找不到元素,则会默认的轮询等待一段时间。
调用driver.implicitly_wait(10)
。那么在获取不可用的元素之前,会先等待10秒的时间,示例代码如下:
driver = webdriver.Chrome(path)
# 设置隐式等待
driver.implicitly_wait(10)
# 请求网页
driver.get('https://www.baidu.com/')
显示等待是表明某个条件成立后才执行获取元素的操作。也可以在等待的时候指定一个最大的时间,如果超过这个时间那么就抛出一个异常。显示等待应该使用selenium.webdriver.support.expected_conditions
期望条件和selenium.webdriver.support.ui.WebDriverWait
来配合完成。
示例代码如下:
# 引入所需库
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
# 声明定义chromedriver路径
path = r'E:\Python_Code\s1\chromedriver_win32\chromedriver.exe'
# 实例化Chrome
# 如果时其他浏览器需要实例化为对应的对象,例如火狐webdriver.firefox()
driver = webdriver.Chrome(path)
# 请求网页
driver.get('https://www.baidu.com/')
# 设置显示等待
try:
element = WebDriverWait(driver, 10).until(
# 只能传一个参数,需要放到元组中
EC.presence_of_element_located((By.ID,'kw'))
)
print(element)
finally:
driver.close()
在上面例子中,我们在查找一个元素的时候,不再使用find_element_by_*
这样的方式来查找元素,而是使用了WebDriverWait
。
try代码块中的代码的意思是:在抛出元素不存在异常之前,最多等待10秒。在这10秒中,WebDriverWait
会默认每500ms运行一次until之中的内容,而until中的EC.presence_of_element_located
则是检查元素是否已经被加载,检查的元素则通过By.ID
这样的方式来进行查找。
也就是说,在10秒内,默认每0.5秒检查一次元素是否存在,存在则将元素赋值给element
这个变量。如果超过10秒这个元素仍不存在,则抛出超时异常。
title_is
:判断title,返回布尔值
WebDriverWait(driver,10).until(EC.title_is(u"百度一下,你就知道"))
title_contains
:判断title,返回布尔值
WebDriverWait(driver,10).until(EC.title_contains(u"百度一下"))
presence_of_element_located
:判断元素对象是否被加载到dom树里; 并不代表该元素一定可见, 如果定位到就返回Webelement
WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,'some')))
visibility_of_element_located
:判断元素对象是否被加载到dom里并且可见, 一般在对象可能会被其他元素对象遮挡的情况下使用
WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.ID,'some')))
visibility_of
:判断元素是否可见,如果可见就返回这个元素.
WebDriverWait(driver,10).until(EC.visibility_of(driver.find_element(by=By.ID,value='some')))
presence_of_all_elements_located
:判断是否至少有1个元素存在dom树中,如果定位(找)到就返回列表.WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,'some')))
visibility_of_any_elements_located
:判断是否至少有一个元素在页面中可见,如果定位到就返回列表.
WebDriverWait(driver,10).until(EC.visibility_of_any_elements_located((By.CSS_SELECTOR,'some')))
text_to_be_present_in_element
:判断指定的元素中是否包含了预期的字符串,返回布尔值.
WebDriverWait(driver,10).until(EC.text_to_be_present_in_element((By.XPATH,"some"),u'设置'))
text_to_be_present_in_element_value
:判断指定元素的属性值中是否包含了预期的字符串,返回布尔值.
WebDriverWait(driver,10).until(EC.text_to_be_present_in_element_value((By.CSS_SELECTOR,'some'),u'百度一下'))
invisibility_of_element_located
:判断某个元素在是否存在于dom或不可见,如果可见返回False,不可见返回这个元素.
WebDriverWait(driver,10).until(EC.invisibility_of_element_located((By.CSS_SELECTOR,'some')))
element_to_be_clickable
:判断某个元素中是否有可见并且是enable(可点击)的.
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"some"))).click()
element_to_be_selected
: 判断某个元素是否被选中了,一般用在下拉列表.
WebDriverWait(driver,10).until(EC.element_to_be_selected(driver.find_element(By.XPATH,"some")))
有时候窗口中有很多子tab,这时候肯定是需要进行切换的,selenuim
提供了一个叫做switch_to_window
来进行切换,具体切换到那个页面,可以从driver.window_handles
中找到。示例代码如下:
# 引入所需库
from selenium import webdriver
# 声明定义chromedriver路径
path = r'E:\Python_Code\s1\chromedriver_win32\chromedriver.exe'
# 实例化Chrome
# 如果时其他浏览器需要实例化为对应的对象,例如火狐webdriver.firefox()
driver = webdriver.Chrome(path)
# 操作输入框
driver.get('https://www.baidu.com/')
driver.execute_script('window.open("http://www.douban.com/")')
print(driver.window_handles)
driver.switch_to.window(driver.window_handles[1])
print(driver.current_url)
# 虽然在窗口中切换到了新页面,但是driver中还没有切换.
# 如果想要在代码中切换到新的页面,并且做一些爬虫,
# 那么应该使用driver.switch_to.window()来切换到指定窗口
# 从driver.window_handlers中取出jurisdiction第几个窗口
# driver.window_handlers是一个列表,里面装的都是窗口句柄.
# 它会按照打开页面的顺序来存储窗口的句柄.