Selenium 模块使用
Beijing: ☁️ 🌡️+18°C 🌬️↓4km/h
写在前面
日常工作中,在使用网页爬虫抓取网页数据受到限制时,我们可能考虑会对一些无需登录验证的网页,使用模拟浏览器点击,例如获取网页的检索结果、批量下载文件等,Selenium 模块提供 API 调用 webdriver,可以在一定程度上满足我们的需求,但同时需要下载设置路径等操作,因此还需要配合 webdrvier Manager 才可以对 webdriver 进行便捷化管理。
通过 pip install selenium webdriver-manager
完成相关 Python 库的安装。
driver 安装
Chrome 安装
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(ChromeDriverManager().install())
Firefox 安装
from selenium import webdriver
from webdriver_manager.firefox import GeckoDriverManager
from selenium.webdriver.firefox.service import Service
ser = Service(GeckoDriverManager().install())
driver = webdriver.Firefox(service=ser)
Edge 安装
from selenium import webdriver
from webdriver_manager.microsoft import EdgeChromiumDriverManager
driver = webdriver.Edge(EdgeChromiumDriverManager().install())
在多次尝试使用过程中,Firefox体验相对较好。
基本使用
获取 driver 后,我们需要使用 driver.get(url)
使得浏览器访问我们需要的页面,结束时使用 driver.close()
关闭即可。
定位元素
在对网页的元素定位中,最常使用的是 xpath,因为我们只要确定浏览器网页的操作顺序,进入浏览器开发者模式,复制对应的页面元素 xpath 路径即可,例如:
# 通过xpath定位并点击元素
driver.find_element('xpath', '//*[@id="exportToExcelButton"]').click()
页面交互
有时候我们在选择对应的页面元素后,还需要填写相应的内容或敲击对应的键盘按键,这里使用比较直接的键盘输入方法:
from selenium.webdriver.common.keys import Keys
# 找到对应元素并敲击对应按键
start = driver.find_element('name', 'markFrom')
start.send_keys(Keys.BACKSPACE)
# 填写对应的文本内容
driver.find_element('name', 'markFrom').send_keys('123456')
时间等待
当今许多页面加载中使用 AJAX 技术,当网页在浏览器中载入时,其中的许多元素并非是同一时间段进行加载,因此需要经过等待,slenium 提供了 Explicit Waits 以及 Implicit Waits 两种方式。
显式等待(Explicit Waits)
代码在执行前必须满足某一条件,否则将抛出异常。下面这段代码表示给予 driver 最多 10 秒时间去定位 ID 为 myDynamicElement
的元素(PS:即使网页其它元素未加载完成也会继续执行下一步),如果 10 秒内未能定位到,则抛出异常。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
隐式等待(Implicit Waits)
是的 driver 作用于全局,webdriver 被要求等待一段特定的时间直至整个页面加载完成,然后进行下一步操作。
from selenium import webdriver
from webdriver_manager.firefox import GeckoDriverManager
from selenium.webdriver.firefox.service import Service
ser=Service(GeckoDriverManager().install())
driver = webdriver.Firefox(service=ser)
driver.implicitly_wait(1) # seconds
driver.get("https://www.baidu.com/")
driver.find_element('xpath', '/html/body/div[1]/div[1]/div[5]/div/div/div[3]/div/a[2]/span').click()
driver.quit()
多进程
通常我们会有同时打开多个浏览器窗口的需求,这里我们结合 Python multiprocessing
模块进行演示:
import time
import os
from multiprocessing import Pool
from selenium import webdriver
from webdriver_manager.firefox import GeckoDriverManager
from selenium.webdriver.firefox.service import Service
def browser():
driver = webdriver.Chrome()
return driver
def task(url):
driver = browser()
driver.get(url)
time.sleep(3)
driver.close()
if __name__ =='__main__':
links = ['https://www.baidu.com', 'https://bilibili.com']
print('Parent process %s.' % os.getpid())
pool = Pool(processes=4)
for i in range(len(links)):
pool.apply_async(task, args={links[i]})
print('Waiting for all subprocesses done...')
pool.close()
pool.join()
print('All subprocesses done.')