对于静态网页,使用requests等库可以很方便的得到它的网页源码,然后提取出想要的信息。但是对于动态网页,情况就要复杂很多,这种页面的源码往往只有一个框架,其内容都是由JavaScript渲染出来的。这时候,我们就可以使用selenium来直接驱动浏览器进行爬取。
selenium是一个自动化测试工具,利用它可以驱动浏览器进行一系列操作,并且可以得到当前呈现的网页的源码,对动态页面的爬取非常有效。下面来说一下selenium的简单使用。
一、安装
1. selenium
推荐使用pip直接安装:
pip install selenium
2. ChromeDriver
selenium是一个自动化测试工具,需要配合浏览器驱动来使用,以Chrome为例,首先需要下载自己浏览器对应版本的驱动。版本对照可以到chromedriver与chrome版本映射表查看。另外Chrome版本70以上的可以直接到ChromeDriverMirror根据浏览器版本下载。
下载完成后需要将可执行文件配置到环境变量里,Windows系统可以将chromedriver.exe文件直接拖到python环境的scripts目录下,也可以将其所在路径配置到系统环境变量,Linux系统下可以将可执行文件移动到环境变量目录中:
sudo mv chromedriver /usr/bin
配置完成后,在命令行直接输入 chromedriver
如果有如下输出,则环境配置成功:
二、使用
1. 声明浏览器对象
from selenium import webdriver
chrome = webdriver.Chrome()
这样初始化之后在使用它进行浏览器操作时会弹出浏览器界面直到关闭,显然一般情况下我们是希望它默默地在后台干活而不弹出任何界面的,所以还需要设置chrome的无界面模式(老版本可能不支持)
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
chrome = webdriver.Chrome(chrome_options=chrome_options)
2. 访问页面
访问页面使用get函数传入url即可
chrome.get('https://www.baidu.com')
print(chrome.page_source) # 输出当前页面源码
3. 查找节点
用get方法打开一个页面以后就可以用page_source方法获得它的源码进而使用BeautifulSoup等库进行解析,不过selenium已经提供了对节点进行操作的一系列方法,就不用再额外使用解析库了。
对于id,class等常见属性的节点可以通过find_element_by_id
这样的方法获得,获取单个节点的方法有:
find_element_by_tag_name()
find_element_by_id()
find_element_by_name()
find_element_by_class_name()
另外还有查找节点的通用方法find_element(属性名, 值)
,可以很灵活的查找自定义属性的节点。以上方法都是获取单个节点的方法,如果页面中有多个符合条件的节点则只能返回第一个结果,如果想找到所有符合条件的节点,只需要将方法中的 element 改为 elements 即可,这将返回一个节点列表
4. 获取节点信息
定位到某个节点之后就可以使用get_attribute('属性名')
方法获取它的属性信息,获取节点内容可以使用.txt方法
node = chrome.find_element_by_id('kw')
print(node.get_attribute('class'))
print(node.text)
5. 节点交互
selenium提供了对节点的一系列操作方法,比如向输入框填入内容:
input = chrome.find_element_by_id('kw')
input.send_keys('python') # 填入内容
input.clear() # 清空输入
input.send_keys('zzu')
点击指定按钮:
button = chrome.find_element_by_id('su')
button.click()
6. 延时等待
打开一个页面时可能会由于网络问题或者页面需要加载很多动态信息从而导致立即对页面进行操作时发生错误,所以最好在打开页面后等待一段时间再进行操作,最简单的等待方式是使用time库:
import time
time.sleep(3)
显然这种方式是很不灵活的,大多数页面都可以很快的加载出来,这样的固定延时就会浪费很多时间。更好的方法是使用WebDriverWait类,用一个浏览器对象和一个最大等待时间初始化之后再调用until方法,传入等待完成的条件,最大等待时间内条件满足则立即结束等待,否则抛出异常,例如:
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
# 5秒内id为content_left的节点出现则结束等待,否则抛出异常
WebDriverWait(chrome, 5).until(EC.presence_of_element_located(('id', 'content_left')))
完整的等待条件可以查看官方文档
7. 执行JavaScript代码
selenium提供了直接运行JavaScript代码的方法 excute_script ,对于selenium没有提供的动作都可以通过执行JavaScript代码来实现,比如下拉进度条以加载更多内容:
# 下拉进度条到最底部
chrome.execute_script('window.scrollTo(0, document.body.scrollHeight)')
chrome.execute_script('alert("to bottom")')
网友评论