浏览器抓取网页(一起学(复)习模拟浏览器运行的库Selenium运行)
优采云 发布时间: 2022-01-30 22:19浏览器抓取网页(一起学(复)习模拟浏览器运行的库Selenium运行)
以下文章来自你可以叫我菜哥,作者刀菜
今天带大家学习(复习)模拟浏览器运行的库Selenium。它是用于 Web 应用程序测试的工具。Selenium 测试直接在浏览器中运行,就像真正的用户一样。支持的浏览器包括 IE (7, 8, 9, 10, 11), Mozilla Firefox, Safari, Google Chrome, Opera and Edge等。
这里我以 Chrome 为例来演示 Selenium 的功能~
0. 准备工作
在开始后续功能演示之前,我们需要安装Chrome浏览器并配置ChromeDriver,当然还要安装selenium库!
0.1. 安装 selenium 库
pip install selenium
0.2. 安装浏览器驱动
其实浏览器驱动的安装方式有两种:一种是常见的手动安装,另一种是使用第三方库自动安装。
以下前提:每个人都安装了Chrome浏览器。
手动安装
先查看本地Chrome浏览器版本:(两种方式都可以)
然后选择版本号对应的驱动版本
下载链接:
最后配置环境变量,即将对应的ChromeDriver可执行chromedriver.exe文件拖到Python Scripts目录下。
注意:当然,你可以不这样做,但你也可以在调用时指定chromedriver.exe的绝对路径。
自动安装
自动安装需要使用第三方库 webdriver_manager。先安装这个库,然后调用对应的方法。
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from webdriver_manager.chrome import ChromeDriverManager
browser = webdriver.Chrome(ChromeDriverManager().install())
browser.get('http://www.baidu.com')
search = browser.find_element_by_id('kw')
search.send_keys('python')
search.send_keys(Keys.ENTER)
# 关闭浏览器
browser.close()
上面代码中,ChromeDriverManager().install()方法是自动安装驱动。它将自动获取当前浏览器版本并在本地下载相应的驱动程序。
====== WebDriver manager ======
Current google-chrome version is 96.0.4664
Get LATEST chromedriver version for 96.0.4664 google-chrome
There is no [win32] chromedriver for browser in cache
Trying to download new driver from https://chromedriver.storage.googleapis.com/96.0.4664.45/chromedriver_win32.zip
Driver has been saved in cache [C:\Users\Gdc\.wdm\drivers\chromedriver\win32\96.0.4664.45]
如果浏览器通道在本地已经存在,会提示已经存在。
====== WebDriver manager ======
Current google-chrome version is 96.0.4664
Get LATEST driver version for 96.0.4664
Driver [C:\Users\Gdc\.wdm\drivers\chromedriver\win32\96.0.4664.45\chromedriver.exe] found in cache
完成以上准备后,我们就可以开始学习本文的官方内容啦~
1. 基本用法
在本节中,我们从初始化浏览器对象、访问页面、设置浏览器大小、刷新页面以及前进和后退等基本操作开始。
1.1. 初始化浏览器对象
在准备部分,我们提到需要将浏览器通道添加到环境变量或指定绝对路径。前者可以直接初始化,后者需要指定。
from selenium import webdriver
# 初始化浏览器为chrome浏览器
browser = webdriver.Chrome()
# 指定绝对路径的方式
path = r'C:\Users\Gdc\.wdm\drivers\chromedriver\win32\96.0.4664.45\chromedriver.exe'
browser = webdriver.Chrome(path)
# 关闭浏览器
browser.close()
可以看到上面是有界面的浏览器,我们也可以将浏览器初始化为无界面的浏览器。
from selenium import webdriver
# 无界面的浏览器
option = webdriver.ChromeOptions()
option.add_argument("headless")
browser = webdriver.Chrome(options=option)
# 访问百度首页
browser.get(r'https://www.baidu.com/')
# 截图预览
browser.get_screenshot_as_file('截图.png')
# 关闭浏览器
browser.close()
在完成浏览器对象的初始化并赋值给浏览器对象之后,我们就可以调用浏览器执行各种方法来模拟浏览器的操作了。
1.2. 访问页面
get方法用于页面访问,传入的参数是要访问的页面的URL地址。
from selenium import webdriver
# 初始化浏览器为chrome浏览器
browser = webdriver.Chrome()
# 访问百度首页
browser.get(r'https://www.baidu.com/')
# 关闭浏览器
browser.close()
1.3. 设置浏览器大小
set_window_size()方法可以用来设置浏览器的大小(也就是分辨率),maximize_window就是设置浏览器全屏!
from selenium import webdriver
import time
browser = webdriver.Chrome()
# 设置浏览器大小:全屏
browser.maximize_window()
browser.get(r'https://www.baidu.com')
time.sleep(2)
# 设置分辨率 500*500
browser.set_window_size(500,500)
time.sleep(2)
# 设置分辨率 1000*800
browser.set_window_size(1000,800)
time.sleep(2)
# 关闭浏览器
browser.close()
这里就不截图了,大家自己演示一下效果吧~
1.4. 刷新页面
刷新页面是我们在操作浏览器时很常见的操作,这里可以使用refresh()方法来刷新浏览器页面。
from selenium import webdriver
import time
browser = webdriver.Chrome()
# 设置浏览器全屏
browser.maximize_window()
browser.get(r'https://www.baidu.com')
time.sleep(2)
try:
# 刷新页面
browser.refresh()
print('刷新页面')
except Exception as e:
print('刷新失败')
# 关闭浏览器
browser.close()
效果大家也自己演示一下,和F5快捷键一样。
1.5. 前进后退
前进和后退也是我们在使用浏览器时很常见的操作。这里可以用forward()方法实现forward,用back()方法实现backward。
from selenium import webdriver
import time
browser = webdriver.Chrome()
# 设置浏览器全屏
browser.maximize_window()
browser.get(r'https://www.baidu.com')
time.sleep(2)
# 打开淘宝页面
browser.get(r'https://www.taobao.com')
time.sleep(2)
# 后退到百度页面
browser.back()
time.sleep(2)
# 前进的淘宝页面
browser.forward()
time.sleep(2)
# 关闭浏览器
browser.close()
2. 获取页面的基本属性
当我们用 selenium 打开一个页面时,会有一些基本的属性,例如页面标题、URL、浏览器名称、页面源代码等信息。
from selenium import webdriver
browser = webdriver.Chrome()
browser.get(r'https://www.baidu.com')
# 网页标题
print(browser.title)
# 当前网址
print(browser.current_url)
# 浏览器名称
print(browser.name)
# 网页源码
print(browser.page_source)
输出如下:
百度一下,你就知道
https://www.baidu.com/
chrome
span.bg.s_ipt_wr.new-pmd.quickdelete-wrap > span.soutu-btn")
# 悬停操作
ActionChains(browser).move_to_element(move).perform()
time.sleep(5)
# 关闭浏览器
browser.close()
8. 模拟键盘操作
selenium 中的 Keys() 类提供了大部分的键盘操作方法,通过 send_keys() 方法模拟键盘上的按键。
引入 Keys 类
from selenium.webdriver.common.keys import Keys
常用键盘操作
send_keys(Keys.BACK_SPACE):删除键(BackSpace)
send_keys(Keys.SPACE):空格键(Space)
send_keys(Keys.TAB):Tab键(TAB)
send_keys(Keys.ESCAPE):后备键(ESCAPE)
send_keys(Keys.ENTER):回车键(ENTER)
send_keys(Keys.CONTRL,'a'): 全选 (Ctrl+A)
send_keys(Keys.CONTRL,'c'): 复制 (Ctrl+C)
send_keys(Keys.CONTRL,'x'): 剪切 (Ctrl+X)
send_keys(Keys.CONTRL,'v'): 粘贴 (Ctrl+V)
send_keys(Keys.F1): 键盘 F1
......
send_keys(Keys.F12): 键盘 F12
示例操作演示:
找到需要操纵的元素,然后操纵它!
from selenium.webdriver.common.keys import Keys
from selenium import webdriver
import time
browser = webdriver.Chrome()
url = 'https://www.baidu.com'
browser.get(url)
time.sleep(2)
# 定位搜索框
input = browser.find_element_by_class_name('s_ipt')
# 输入python
input.send_keys('python')
time.sleep(2)
# 回车
input.send_keys(Keys.ENTER)
time.sleep(5)
# 关闭浏览器
browser.close()
9. 延迟等待
如果遇到使用 ajax 加载的网页,页面元素可能不会同时加载。此时,在执行get方法时尝试获取网页的源代码,可能不是浏览器完全加载的页面。因此,在这种情况下,需要设置一个延迟并等待一定的时间,以确保所有节点都加载完毕。
三种玩法:强制等待、隐式等待和显式等待
9.1. 强制等待
很简单,直接time.sleep(n)强制等待n秒,执行get方法后执行。
9.2. 隐式等待
Implicitly_wait() 设置等待时间。如果有一个元素节点到时候没有加载,就会抛出异常。
from selenium import webdriver
browser = webdriver.Chrome()
# 隐式等待,等待时间10秒
browser.implicitly_wait(10)
browser.get('https://www.baidu.com')
print(browser.current_url)
print(browser.title)
# 关闭浏览器
browser.close()
9.3. 显式等待
设置等待时间和条件,在规定时间内,每隔一段时间检查条件是否成立。如果是,程序会继续执行,否则会抛出超时异常。
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
# 设置等待时间10s
wait = WebDriverWait(browser, 10)
# 设置判断条件:等待id='kw'的元素加载完成
input = wait.until(EC.presence_of_element_located((By.ID, 'kw')))
# 在关键词输入:关键词
input.send_keys('Python')
# 关闭浏览器
time.sleep(2)
browser.close()
WebDriverWait的参数说明:
WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)
驱动:浏览器驱动
timeout:超时,等待的最长时间(还要考虑隐式等待时间)
poll_frequency:每次检测的时间间隔,默认为0.5秒
ignore_exceptions:超时后的异常信息,默认抛出NoSuchElementException
直到(方法,消息='')
method:在等待期间,每隔一段时间调用这个传入的方法,直到返回值不为False
message:如果超时,抛出 TimeoutException 并将消息传递给异常
直到_not(方法,消息='')
until_not 与直到相反。until 是当元素出现或满足某些条件时继续执行, until_not 是当元素消失或某些条件不满足时继续执行,参数相同。
其他等待条件
from selenium.webdriver.support import expected_conditions as EC
# 判断标题是否和预期的一致
title_is
# 判断标题中是否包含预期的字符串
title_contains
# 判断指定元素是否加载出来
presence_of_element_located
# 判断所有元素是否加载完成
presence_of_all_elements_located
# 判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于0,传入参数是元组类型的locator
visibility_of_element_located
# 判断元素是否可见,传入参数是定位后的元素WebElement
visibility_of
# 判断某个元素是否不可见,或是否不存在于DOM树
invisibility_of_element_located
# 判断元素的 text 是否包含预期字符串
text_to_be_present_in_element
# 判断元素的 value 是否包含预期字符串
text_to_be_present_in_element_value
#判断frame是否可切入,可传入locator元组或者直接传入定位方式:id、name、index或WebElement
frame_to_be_available_and_switch_to_it
#判断是否有alert出现
alert_is_present
#判断元素是否可点击
element_to_be_clickable
# 判断元素是否被选中,一般用在下拉列表,传入WebElement对象
element_to_be_selected
# 判断元素是否被选中
element_located_to_be_selected
# 判断元素的选中状态是否和预期一致,传入参数:定位后的元素,相等返回True,否则返回False
element_selection_state_to_be
# 判断元素的选中状态是否和预期一致,传入参数:元素的定位,相等返回True,否则返回False
element_located_selection_state_to_be
#判断一个元素是否仍在DOM中,传入WebElement对象,可以判断页面是否刷新了
staleness_of
10. 其他
添加一些
10.1. 运行 JavaScript
还有一些操作,比如下拉进度条,模拟javascript,使用execute_script方法来实现。
from selenium import webdriver
browser = webdriver.Chrome()
# 知乎发现页
browser.get('https://www.zhihu.com/explore')
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("To Bottom")')
10.2. Cookie
在 selenium 的使用过程中,获取、添加和删除 cookie 也非常方便。
from selenium import webdriver
browser = webdriver.Chrome()
# 知乎发现页
browser.get('https://www.zhihu.com/explore')
# 获取cookie
print(f'Cookies的值:{browser.get_cookies()}')
# 添加cookie
browser.add_cookie({'name':'才哥', 'value':'帅哥'})
print(f'添加后Cookies的值:{browser.get_cookies()}')
# 删除cookie
browser.delete_all_cookies()
print(f'删除后Cookies的值:{browser.get_cookies()}')
输出:
Cookies的值:[{'domain': '.zhihu.com', 'httpOnly': False, 'name': 'Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740*敏*感*词*9', 'path': '/', 'secure': False, 'value': '1640537860'}, {'domain': '.zhihu.com', ...]
添加后Cookies的值:[{'domain': 'www.zhihu.com', 'httpOnly': False, 'name': '才哥', 'path': '/', 'secure': True, 'value': '帅哥'}, {'domain': '.zhihu.com', 'httpOnly': False, 'name': 'Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740*敏*感*词*9', 'path': '/', 'secure': False, 'value': '1640537860'}, {'domain': '.zhihu.com',...]
删除后Cookies的值:[]
10.3. 反掩码
发现美团直接屏蔽了Selenium,不知道怎么办!!