Python爬虫4.4 — selenium高级用法教程

综述

本系列文档用于对Python爬虫技术的学习进行简单的教程讲解,巩固自己技术知识的同时,万一一不小心又正好对你有用那就更好了。
Python 版本是3.7.4

前面一篇文章讲了selenium的基础用法,这一篇我们讲述一些selenium比较高级的用法。

Headless Chrome

上面的示例代码在运行中都会弹出一个浏览器窗口,有时候会很不方便,这就需要我们不弹出窗口爬取数据。

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来解决这个问题。更改代理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')

常用启动项参数options设置

启动参数 作用
–user-agent=”“ 设置请求头的User-Agent
–window-size=长,宽 设置浏览器分辨率
–headless 无界面运行
–start-maximized 最大化运行
–incognito 隐身模式
–disable-javascript 禁用javascript
–disable-infobars 禁用浏览器正在被自动化程序控制的提示

更多参数说明:https://peter.sh/experiments/chromium-command-line-switches/

Cookie操作

  1. 获取所有的cookie
    for cookie in driver.get_cookies():
        print(cookie)
    
  2. 根据cookie的key获取value:
    cookie = driver.get_cookie('BD_HOME')
    print(cookie)
    
  3. 删除所有cookie:
    driver.delete_all_cookies()
    
  4. 删除某个cookie:
    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()

selenium设置cookie

使用add_cookie(cookie_dict)方法给当前会话可以添加一个cookie;cookie_dict是一个字典对象,必须要有namevalue两个键,可选的键有: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()

常用的行为链操作方法(ActionChains类方法)

  • click(on_element=None) : 左键单击传入的元素,如果不传入的话,点击鼠标当前位置。
  • context_click(on_element=None): 右键单击。
  • double_click(on_element=None) : 双击。
  • click_and_hold(on_element=None): 点击但不松开鼠标
  • drag_and_drop(source, target) : 在source元素上点击抓起,移动到target元素上松开放下。
  • drag_and_drop_by_offset(source,xoffset,yoffset):在source元素上点击抓起,移动到相对于source元素偏移xoffset和yoffset的坐标位置放下。
  • send_keys(*keys_to_send): 将键发送到当前聚焦的元素。
  • send_keys_to_element(element, *keys_to_send): 将键发送到指定的元素。
  • reset_actions(): 清除已经存储的动作。
  • 更多方法请参考:http://sekenium-python.readthedocs.io/api.html

页面等待

现在的网页越来越多采用了Ajax技术,这样程序便不能确定合适某个元素才完成加载出来。如果实际页面等待事件过长导致某个DOM元素还没出来,但是你的代码直接使用了这个页面元素,那么就会抛出NullPointer的异常。为了解决这个问题,所以Selenium提供了两种等待方式,一种是隐式等待、一种是显示等待。

1. 隐式等待

隐式等待指的是,在webdriver中进行find_element_*这一类查找操作时,如果找不到元素,则会默认的轮询等待一段时间。

调用driver.implicitly_wait(10)。那么在获取不可用的元素之前,会先等待10秒的时间,示例代码如下:

driver = webdriver.Chrome(path)
# 设置隐式等待
driver.implicitly_wait(10)
# 请求网页
driver.get('https://www.baidu.com/')

2. 显示等待

显示等待是表明某个条件成立后才执行获取元素的操作。也可以在等待的时候指定一个最大的时间,如果超过这个时间那么就抛出一个异常。显示等待应该使用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秒这个元素仍不存在,则抛出超时异常。

expected_conditions类中其他方法

  1. title_is:判断title,返回布尔值
    • WebDriverWait(driver,10).until(EC.title_is(u"百度一下,你就知道"))
  2. title_contains:判断title,返回布尔值
    • WebDriverWait(driver,10).until(EC.title_contains(u"百度一下"))
  3. presence_of_element_located:判断元素对象是否被加载到dom树里; 并不代表该元素一定可见, 如果定位到就返回Webelement
    • WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,'some')))
  4. visibility_of_element_located:判断元素对象是否被加载到dom里并且可见, 一般在对象可能会被其他元素对象遮挡的情况下使用
    • WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.ID,'some')))
  5. visibility_of:判断元素是否可见,如果可见就返回这个元素.
    • WebDriverWait(driver,10).until(EC.visibility_of(driver.find_element(by=By.ID,value='some')))
  6. presence_of_all_elements_located:判断是否至少有1个元素存在dom树中,如果定位(找)到就返回列表.
    WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,'some')))
  7. visibility_of_any_elements_located:判断是否至少有一个元素在页面中可见,如果定位到就返回列表.
    • WebDriverWait(driver,10).until(EC.visibility_of_any_elements_located((By.CSS_SELECTOR,'some')))
  8. text_to_be_present_in_element:判断指定的元素中是否包含了预期的字符串,返回布尔值.
    • WebDriverWait(driver,10).until(EC.text_to_be_present_in_element((By.XPATH,"some"),u'设置'))
  9. text_to_be_present_in_element_value:判断指定元素的属性值中是否包含了预期的字符串,返回布尔值.
    • WebDriverWait(driver,10).until(EC.text_to_be_present_in_element_value((By.CSS_SELECTOR,'some'),u'百度一下'))
  10. invisibility_of_element_located:判断某个元素在是否存在于dom或不可见,如果可见返回False,不可见返回这个元素.
    • WebDriverWait(driver,10).until(EC.invisibility_of_element_located((By.CSS_SELECTOR,'some')))
  11. element_to_be_clickable:判断某个元素中是否有可见并且是enable(可点击)的.
    • WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH,"some"))).click()
  12. element_to_be_selected: 判断某个元素是否被选中了,一般用在下拉列表.
    • WebDriverWait(driver,10).until(EC.element_to_be_selected(driver.find_element(By.XPATH,"some")))
  13. 更多方法请参考:http://sekenium-python.readthedocs.io/waits.html

切换页面

有时候窗口中有很多子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是一个列表,里面装的都是窗口句柄.
# 它会按照打开页面的顺序来存储窗口的句柄.

其他博文链接

发布了154 篇原创文章 · 获赞 404 · 访问量 65万+

猜你喜欢

转载自blog.csdn.net/Zhihua_W/article/details/102890725