浏览器自动化
什么是 selenium
selenium 是浏览器自动化测试框架,原本被用于网页测试。但到了爬虫领域,它又成为了爬虫的好帮手。selenium 可以控制你的浏览器,模仿人浏览网页,从而获取数据,自动操作等。一图胜千言
安装 selenium
和其他 Python 第三方库的安装一样,我们要在命令行中使用 pip 命令安装 selenium:
1 pip install selenium -i https://pypi.doubanio.com/simple
selenium 还需要安装相应的浏览器驱动才能控制浏览器
chromedriver驱动下载网站:
https://registry.npmmirror.com/binary.html?path=chromedriver/
将下载好的 chromedriver 解压缩,Windows 系统得到 chromedriver.exe,MacOS 得到 chromedriver,这个就是我们需要的浏览器驱动。我们要将它放到 Python 所在安装目录里。 如果你忘了 Python 的安装目录,可以根据下面的操作来找到。
1 import sys 2 print(sys.executable)
打开浏览器:
from selenium import webdriver browser = webdriver.Chrome() # 打开网页 browser.get('https://wpblog.x0y1.com') # 关闭浏览器 browser.quit()
browser 是我们实例化的浏览器。我们将网址传给 browser 对象的 get() 方法,即可打开对应的网页。最后调用 quit() 方法将浏览器关闭。
我们的目的是获取数据,接下来让我们用 browser 对象的 page_source 属性来获取网页的源代码。值得注意的是,用 selenium 获取的网页源代码是数据加载完毕后最终的源代码,也就是网页加载后通过 API 获取的数据也在这个源代码中。
因此,我们就不用再区分要爬取的网页是静态网页还是动态网页了,在 selenium 眼里统统都一样
用 selenium 打印出博客的网页源代码:
from selenium import webdriver browser = webdriver.Chrome() browser.get('https://wpblog.x0y1.com') # 打印出网页源代码 print(browser.page_source) browser.quit()
处理数据
我们之前掌握了用 BeautifulSoup 对获取的网页源代码进行处理,提取出我们需要的内容。selenium 也同样可以进行数据的处理,它俩原理类似,只是语法上有所不同。
接下来,我们来看看如何用 selenium 处理数据。我们以获取博客的 h1 标签为例,代码可以这样写:
from selenium import webdriver browser = webdriver.Chrome() browser.get('https://wpblog.x0y1.com') h1 = browser.find_element_by_tag_name('h1') print(h1.text) browser.quit()
Selenium常用的查找元素的方法:
我们来看几个例子你就明白了,下面的例子中,注释内容是要找的 HTML 元素代码,下面是获取该元素的 Python 代码:
1 # <p>扇贝编程,带你打开编程世界的大门</p> 2 browser.find_element_by_tag_name('p') 3 4 # <p class="slogan">扇贝编程,带你打开编程世界的大门</p> 5 browser.find_element_by_class_name('slogan') 6 7 # <p id="slogan">扇贝编程,带你打开编程世界的大门</p> 8 browser.find_element_by_id('slogan') 9 10 # <p name="slogan">扇贝编程,带你打开编程世界的大门</p> 11 browser.find_element_by_name('slogan') 12 13 # <a href="http://code.shanbay.com">扇贝编程</a> 14 browser.find_element_by_link_text('扇贝编程') 15 browser.find_element_by_partial_link_text('扇贝')
selenium
新增了一种更统一的方法 find_element()
,而具体通过什么来查找(tag name, class name 等)放进了参数中。
1 # <p>扇贝编程,带你打开编程世界的大门</p> 2 browser.find_element('tag name', 'p') 3 4 # <p class="slogan">扇贝编程,带你打开编程世界的大门</p> 5 browser.find_element('class name', 'slogan') 6 7 # <p id="slogan">扇贝编程,带你打开编程世界的大门</p> 8 browser.find_element('id', 'slogan') 9 10 # <p name="slogan">扇贝编程,带你打开编程世界的大门</p> 11 browser.find_element('name', 'slogan') 12 13 # <a href="http://code.shanbay.com">扇贝编程</a> 14 browser.find_element('link text', '扇贝编程') 15 browser.find_element('partial link text', '扇贝')
这些方法找到的元素(返回值)都是 WebElement 对象,它和 BeautifulSoup 里的 Tag 对象一样,也有一个 text 属性,一样也是获取元素里的文本内容。
不同的是,Tag 对象通过字典取值的方式获取元素的属性值,而 WebElement 对象则使用 get_attribute() 方法来获取。
我们来看个代码实例加深一下印象:
# <a href="http://code.shanbay.com">扇贝编程</a> link = browser.find_element_by_link_text('扇贝编程') print(link.get_attribute('href')) # 输出:http://code.shanbay.com print(link.text) # 输出:扇贝编程
如果想要查找所有符合条件的元素 只要把刚才介绍的那些方法名中的 element
改成 elements
即可
1 from selenium import webdriver 2 3 browser = webdriver.Chrome() 4 browser.get('https://wpblog.x0y1.com') 5 # 注意下面是 elements 6 a_tags = browser.find_elements_by_tag_name('a') 7 # 新版本写法: 8 # a_tags = browser.find_elements('tag name', 'a') 9 10 for tag in a_tags: 11 print(tag.text) 12 browser.quit()
控制浏览器
还记得我们上一关说的,登录博客并批量获取博客中的文章内容吗?我们可以使用 selenium
进行同样的操作,代码的可读性更强,我们写起来也更轻松。
要想做到这些,除了刚才学的那些查找元素的方法外,只要再学两个方法即可。这两个方法分别是 click() 和 send_keys(),我们来看看它俩的作用:
自动登录博客并获取文章内容的代码如下,请仔细阅读注释内容:
提示:我们在下面的代码还用了一对新的查找元素的方法:
find_element_by_css_selector()
和find_elements_by_css_selector()
,这就运用了上一课所说的 css 选择器的知识,将 css 选择器以字符串的形式填入括号中,能帮我们更精准地查找元素。
from selenium import webdriver import time browser = webdriver.Chrome() # 打开博客 browser.get('https://wpblog.x0y1.com') # 找到登录按钮 login_btn = browser.find_element_by_link_text('登录') # 点击登录按钮 login_btn.click() # 等待 2 秒钟,等页面加载完毕 time.sleep(2) # 找到用户名输入框 user_login = browser.find_element_by_id('user_login') # 输入用户名 user_login.send_keys('codetime') # 找到密码输入框 user_pass = browser.find_element_by_id('user_pass') # 输入密码 user_pass.send_keys('shanbay520') # 找到登录按钮 wp_submit = browser.find_element_by_id('wp-submit') # 点击登录按钮 wp_submit.click() # 找到 Python 分类文章链接 python_cat = browser.find_element_by_css_selector('section#categories-2 ul li a') # 上一句用新版本的写法如下 # python_cat = browser.find_element('css selector', 'section#categories-2 ul li a') # 点击该分类 python_cat.click() # 找到跳转的页面中的所有文章标题标签 titles = browser.find_elements_by_css_selector('h2.entry-title a') # 上一句用新版本的写法如下 # titles = browser.find_elements('css selector', 'h2.entry-title a') # 找到标题标签中内含的链接 links = [i.get_attribute('href') for i in titles] # 依次打开 links 中的文章链接 for link in links: browser.get(link) # 获取文章正文内容 content = browser.find_element_by_class_name('entry-content') print(content.text) browser.quit()
复习与总结
- 我们是从安装浏览器驱动开始的,为了能让 selenium 控制浏览器,驱动是必需的。
驱动安装完成后,我们迫不及待地用代码控制打开了浏览器,代码是这样的:
1 # 从 selenium 中导入 webdriver(驱动) 2 from selenium import webdriver 3 4 # 选择 Chrome 浏览器并打开 5 browser = webdriver.Chrome()
- 接着我们调用实例化后的浏览器对象(browser)的 get() 方法成功地打开了一个网页,并且通过其 page_source 属性拿到了网页的源代码。注意,最后一定要调用 quit() 方法将浏览器关闭。
-
1 from selenium import webdriver 2 3 browser = webdriver.Chrome() 4 browser.get('https://wpblog.x0y1.com') 5 # 打印出网页源代码 6 print(browser.page_source) 7 # 关闭浏览器 8 browser.quit()
-
- 有些网站数据较多,网页加载比较慢,打开网页后需要暂停几秒才能获取到完整的网页源代码。以上代码可以总结成下图:
- 光拿到网页源代码还不够,我们还要解析、处理它,从中提取出我们需要的数据。selenium 中解析与提取数据的方法如下:
-
上面是获取第一个符合条件的元素的方法,获取所有符合条件的元素的方法只需把 element 改成 elements 即可:
-
- 这些方法找到的元素(返回值)都是 WebElement 对象,它的常用属性和方法如下:’
- 举个获取 a 标签中链接和内容的例子:
-
1 # <a href="http://code.shanbay.com">扇贝编程</a> 2 link = browser.find_element_by_link_text('扇贝编程') 3 print(link.get_attribute('href')) 4 # 输出:http://code.shanbay.com 5 print(link.text) 6 # 输出:扇贝编程
-
- 接着我们学会了将 selenium 与 BeautifulSoup 相结合,用 selenium 获取网页源代码,用 BeautifulSoup 解析、提取数据。
-
1 from selenium import webdriver 2 from bs4 import BeautifulSoup 3 4 browser = webdriver.Chrome() 5 browser.get('https://wpblog.x0y1.com') 6 # 用 BeautifulSoup 解析网页源代码 7 soup = BeautifulSoup(browser.page_source, 'html.parser') 8 a_tags = soup.find_all('a') 9 for tag in a_tags: 10 print(tag.text) 11 browser.quit()
-
- 最后,我们还学习了 selenium 中操作浏览器的方法,
- 通过 selenium 查找元素的方法找到对应的元素后,调用其 click() 方法就可以模拟点击该元素,一般用于点击链接或按钮;调用其 send_keys() 方法用于模拟按键输入,传入要输入的内容即可,常用于账号密码等输入框的表单填写。
-
selenium简单明了,使用起来非常的直观,和我们正常使用浏览器的步骤一样,不需要分析浏览器背后发生的逻辑。
但它的缺点也很明显,因为 selenium 需要真实的打开浏览器,等待网页加载等。在大规模获取数据时,使用 selenium 爬取数据将会非常的低效。
为了提升爬取效率,我们可以将浏览器设置为静默模式,让浏览器不必真的打开,而是在后台默默地获取数据、操作页面。代码如下:
1 from selenium import webdriver 2 3 # 初始化配置 4 options = webdriver.ChromeOptions() 5 # headless 为静默模式 6 options.add_argument('--headless') 7 # 将配置传入浏览器 8 browser = webdriver.Chrome(options=options) 9 # 打开网页 10 browser.get('https://wpblog.x0y1.com') 11 # 关闭浏览器 12 browser.quit()
即使我们将浏览器配置成静默模式,在大规模爬取数据,selenium 的爬取速度和资源占用率都不太理想。所以,通常情况下,我们还是会用 requests 和 BeautifulSoup 爬取数据