Python编程进阶知识之第二课学习网络爬虫(selenium)
selenium
库是一种用于 Web 应用程序测试的工具,它可以驱动浏览器执行特定操作,自动按照脚本代码做点击、输入、打开、验证等操作,支持的浏览器包括 IE、Firefox、Safari、Chrome、Opera 等。而在办公自动化中如果经常需要使用浏览器操作某些内容,就可以使用selenium
库来实现,例如将大量数据上传到网页中,与requests
库不同的是,selenium
库是基于浏览器的驱动程序来驱动浏览器执行操作的。且浏览器可以渲染网页代码,因此通过selenium
库还可以轻松获取网页中渲染后的数据信息。
1.使用 selenium 库前的准备
1. selenium 库驱动浏览器的原理
浏览器是在浏览器内核基础之上开发而成的,浏览器内核主要负责对网页语法进行解释并渲染(显示)网页。例如 360 浏览器和 Chrome 浏览器都使用 Chrome 内核, 虽然浏览器内核可以被selenium
库驱动,但还是需要安装对应版本的浏览器内核驱动程序,以便于控制 Web 浏览器的行为。每个浏览器都有一个特定的用于支持浏览器运行的 WebDriver,被称为驱动程序。
2.安装 WebDriver
这里以 edge浏览器为例,开始介绍安装浏览器内核驱动程序 WebDriver 的方法。
查看浏览器内核(版本)
打开: Microsoft Edge WebDriver | Microsoft Edge Developer,选择自己对应版本进行下载。
下载后解压将 msedgedriver.exe给添加到自己Python的安装目录中Scripts中,如:
C:\Users\DELL\AppData\Local\Programs\Python\Python39\Scripts
完成这几步就安装完成了
3.安装selenium库
在命令提示符窗口或终端中执行以下命令:
pip install selenium
2.驱动浏览器
selenium
库支持的浏览器包括 Chrome、IE 7~11、Firefox、Safari、Opera、Edge、HtmlUnit、PhantomJS 等,几乎覆盖了当前计算机端和手机端的所有类型的浏览器。在selenium
库源代码文件夹下的webdriver
中可查看所有支持的浏览器类型
webdriver.浏览器类型名()
例如驱动 Chrome 浏览器的使用方法为webdriver.Edge(),
当调用webdriver.Edge()
时,会默认调用Edge/webdriver.py
文件中的类WebDriver
。webdriver.Edge()
的使用形式如下:
webdriver.Edge(executable_path = "chromedriver", port = 0, options = None)
- 功能:创建一个新的edge浏览器驱动程序。
- 参数
executable_path
:表示浏览器的驱动路径,默认为环境变量中的path
,通常计算机中可能存在多个浏览器软件,当没有在环境变量中设置浏览器path
时,可以使用参数options
。 - 参数
port
:表明希望服务运行的端口,如果保留为 0,驱动程序将会找到一个空闲端口。 - 参数
options
:表示由类Options
(位于selenium/webdriver/edge/options.py
)创建的对象,用于实现浏览器的绑定。
from selenium import webdriver
from selenium.webdriver.edge.options import Options
edge_options = Options()
edge_options.binary_location = r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"
driver = webdriver.Edge(options=edge_options)
第 3 行代码使用类 Options 创建了一个对象 edge_options,使用 binary_location () 方法绑定了浏览器。
第 5 行代码使用 webdriver.Edge () 设置 options 参数值为绑定 edge浏览器的对象 edge_options。执行代码后将会自动打开 edge浏览器,实现驱动浏览器的第一步。
binary_location () 方法绑定了浏览器的路径是自己桌面上浏览器的位置。
3.加载网页
使用类 webdriver.Chrome 创建的驱动浏览器对象中包含大量操作浏览器的方法,类 webdriver.Chrome 基于基础类 WebDriver,该类位于 selenium 库webdriver\remote\webdriver.py 文件中。
类 WebDriver 的简洁定义:
class WebDriver(object):def __init__(self, ...):self.file_detector = ...def name(self):...def start(self):...def start_client(self):...def stop_client(self):...def start_session(self, ...):...def create_web_element(self, ...):...def execute(self, ...):...def get(self, url):...def title(self):...# 返回当前网页的标题def find_element_by_id(self, id_):...# 通过标签id获取网页中的一个元素def find_elements_by_id(self, id_):...# 通过标签id获取网页中的多个元素def find_element_by_xpath(self, xpath):...# 通过xpath获取网页元素,xpath是与正则表达式类似的一种语法规则def find_elements_by_xpath(self, xpath):...# 通过xpath获取网页中的多个元素def find_element_by_link_text(self, link_text):...# 通过链接文本获取网页中的一个元素def find_elements_by_link_text(self, link_text):...# 通过链接文本获取网页中的多个元素def find_element_by_partial_link_text(self, link_text):...# 通过元素链接文本的部分匹配来查找一个元素def find_elements_by_partial_link_text(self, link_text):...# 通过元素链接文本的部分匹配来查找多个元素def find_element_by_name(self, name):...# 通过标签name获取网页中的一个元素def find_elements_by_name(self, name):...# 通过标签name获取网页中的多个元素def find_element_by_tag_name(self, name):...# 通过标签名称获取网页中的一个元素def find_elements_by_tag_name(self, name):...# 通过标签名称获取网页中的多个元素def find_element_by_class_name(self, name):...# 通过标签class获取网页中的一个元素def find_elements_by_class_name(self, name):...# 通过标签class获取网页中的多个元素def find_element_by_css_selector(self, css_selector):...# 通过CSS选择器获取网页中的一个元素def find_elements_by_css_selector(self, css_selector):...# 通过CSS选择器获取网页中的多个元素def execute_script(self, script, *args):...# 同步执行当前窗口/框架中的JavaScript脚本def execute_async_script(self, script, *args):...# 异步执行当前窗口/框架中的JavaScript脚本def current_url(self):...# 获取当前网页的URLdef page_source(self):...# 获取当前网页的源代码def close(self):...# 关闭当前窗口def quit(self):...# 退出驱动程序并关闭所有相关的窗口def current_window_handle(self):...# 返回当前窗口的句柄(浏览器中每个标签页为一个句柄)def window_handles(self):...# 返回当前会话中所有窗口的句柄def maximize_window(self):...# 最大化当前窗口def fullscreen_window(self):...# 调用特定于窗口管理器的“全屏”操作def minimize_window(self):...# 调用特定于窗口管理器的“最小化”操作def switch_to(self):...# 返回一个包含所有可切换焦点的选项对象def back(self):...# 在浏览器历史中倒退了一页def forward(self):...# 在浏览器历史中前进了一页def refresh(self):...# 刷新当前页面def get_cookies(self):...# 返回一组字典,对应于当前会话中可见的cookiedef get_cookie(self, name):...# 按名称获取单个Cookiedef delete_cookie(self, name):...# 删除指定名称的单个Cookiedef delete_all_cookies(self):...# 删除该会话范围内的所有Cookiedef add_cookie(self, cookie_dict):...# 将Cookie添加到当前会话中def implicitly_wait(self, time_to_wait):...# 设置超时以隐式等待找到元素或完成命令def set_script_timeout(self, time_to_wait):...# 设置脚本等待时间def set_page_load_timeout(self, time_to_wait):...# 设置页面加载完成的超时时间def find_element(self, by=By.ID, value=None):...# 查找一个元素def find_elements(self, by=By.ID, value=None):...# 查找多个元素def desired_capabilities(self):...# 返回正在使用的驱动程序当前所需的功能def get_screenshot_as_file(self, filename):...# 将当前窗口的截图保存为.png格式图片def save_screenshot(self, filename):...# 将当前窗口的截图保存为.png格式图片def get_screenshot_as_png(self):...# 以二进制数据的形式获取当前窗口的截图def get_screenshot_as_base64(self):...# 获取当前窗口的截图def set_window_size(self, width, height, windowHandle='current'):...# 设置当前窗口的宽度和高度def get_window_size(self, windowHandle='current'):...# 获取当前窗口的宽度和高度def set_window_position(self, x, y, windowHandle='current'):...# 设置当前窗口的位置
下面介绍两种常用的加载浏览器网页的方法。
1.get () 方法
get () 方法用于打开指定的网页。其使用形式如下:
driver.get(url)
from selenium import webdriver
from selenium.webdriver.edge.options import Options
edge_options = Options()
edge_options.binary_location = r""
driver = webdriver.Edge(options=edge_options)
driver.get("https://www.ptpress.com.cn/periodical")
第 6 行代码使用 get () 方法加载人民邮电出版社官网的期刊页,执行代码后将会自动启动 edge 浏览器并加载出相应网页
2.execute_script () 方法
execute_script () 方法用于打开多个标签页,即在同一浏览器中打开多个网页。其使用形式如下:
driver.execute_script(script, *args)
功能:打开标签页,同步执行当前页面中的 JavaScript 脚本。JavaScript 是网页中的一种编程语言。
参数 script:表示将要执行的脚本内容,数据类型为字符串类型。使用 JavaScript 语言实现打开一个新标签页的语法形式为 "window.open (' 网址 url','_blank');"。
from selenium import webdriver
from selenium.webdriver.edge.options import Options
edge_options = Options()
edge_options.binary_location = r""
driver = webdriver.Edge(options=chrome_options)
driver.execute_script("window.open('https://www.ptpress.com.cn/login', '_blank');")
driver.execute_script("window.open('https://www.shuyishe.com/', '_blank');")
driver.execute_script("window.open('https://www.shuyishe.com/course', '_blank');")
第 7~9 行代码使用 execute_script () 方法执行括号中的 JavaScript 脚本,打开的新标签页分别为人民邮电出版社登录页面、数艺设的主页、数艺设的课程页面。
4.获取渲染后的网页代码
通过 get () 方法获取浏览器中的网页资源后,浏览器将自动渲染网页源代码内容,并生成渲染后的网页。此时使用 page_source () 方法即可获取渲染后的网页代码。
from selenium import webdriver
from selenium.webdriver.edge.options import Options
edge_options = Options()
edge_options.binary_location = r""
driver = webdriver.Edge(options=edge_options)
driver.get('https://www.ptpress.com.cn/')
print(driver.page_source)
第 7 行代码使用 driver 对象中的 page_source () 方法获取被 get () 方法获取到的渲染后的网页源代码。
5.获取和操作网页元素
1.获取网页中的指定元素
在获取了网页端某个元素后,就可以使用一下方法对此元素进行相应的操作
tag_name () 方法:获取元素的名称。
text () 方法:获取元素的文本内容。
click () 方法:单击此元素。
submit () 方法:提交表单。
send_keys () 方法:模拟输入信息。
size () 方法:获取元素的尺寸。
可进入 selenium 库文件夹下的 webdriver\remote\webelement.py 中查看更多的操作方法。
2.在元素中输入信息
send_keys () 方法可以实现在元素中输入信息,例如在窗口标签中输入信息。其使用形式如下:
send_keys(value)
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
edge_options = Options()
edge_options.binary_location = r""
driver = webdriver.Edge(options=edge_options)
driver.get('https://www.ptpress.com.cn/')
driver.find_element_by_tag_name("input").send_keys("Python")
第 8 行代码使用 find_element_by_tag_name () 方法找到标签名为 input 的元素(通过网页源代码可知搜索框的标签名为 input)。获取到标签后使用 send_keys () 方法实现在搜索框内输入字符串 "Python"。
对于不同的搜索框标签,其标签名可能不同,需要提前在网页源代码中确定标签名。
实现在搜索框中输入信息的代码程序后,还可以模拟用户的按键操作,其使用方法为在字符串后面继续追加按键转义字符串信息。
from selenium import webdriver
from selenium.webdriver.edge.options import Options
from selenium.webdriver.common.keys import Keys
edge_options = Options()
edge_options.binary_location = r""
driver = webdriver.Edge(options=edge_options)
driver.get("https://www.ptpress.com.cn/")
driver.find_element_by_tag_name("input").send_keys("Python" + Keys.RETURN)
上述代码在之前代码的基础上仅对第 8 行进行了修改,新行代码在 send_keys () 方法中增加了 Keys.RETURN。Keys.RETURN 表示按 Enter 键,这源于第 3 行代码导入的类 Keys,类 Keys 中定义了大部分按键的转义字符串。下面展示了类 Keys 在源代码中对按键的定义
类 Keys 的定义:
class Keys(object):"""Set of special keys codes."""NULL = '\ue000'CANCEL = '\ue001' # ^breakHELP = '\ue002'BACKSPACE = '\ue003'TAB = '\ue004'CLEAR = '\ue005'RETURN = '\ue006'ENTER = '\ue007'SHIFT = '\ue008'LEFT_SHIFT = '\ue009'CONTROL = '\ue00a'LEFT_CONTROL = '\ue00b'ALT = '\ue00c'LEFT_ALT = '\ue00d'PAUSE = '\ue00e'ESCAPE = '\ue00f'SPACE = '\ue010'PAGE_UP = '\ue011'PAGE_DOWN = '\ue012'END = '\ue013'HOME = '\ue014'LEFT = '\ue015'ARROW_LEFT = '\ue015'UP = '\ue016'ARROW_UP = '\ue016'RIGHT = '\ue017'ARROW_RIGHT = '\ue017'DOWN = '\ue018'ARROW_DOWN = '\ue018'INSERT = '\ue019'DELETE = '\ue01a'SEMICOLON = '\ue01b'EQUALS = '\ue01c'NUMPAD0 = '\ue01d'NUMPAD1 = '\ue01e'NUMPAD2 = '\ue01f'NUMPAD3 = '\ue020'NUMPAD4 = '\ue021'NUMPAD5 = '\ue022'NUMPAD6 = '\ue023'NUMPAD7 = '\ue024'NUMPAD8 = '\ue025'NUMPAD9 = '\ue026'MULTIPLY = '\ue027'ADD = '\ue028'SEPARATOR = '\ue029'SUBTRACT = '\ue02a'DECIMAL = '\ue02b'DIVIDE = '\ue02c'F1 = '\ue031'F2 = '\ue032'F3 = '\ue033'F4 = '\ue034'F5 = '\ue035'F6 = '\ue036'F7 = '\ue037'F8 = '\ue038'F9 = '\ue039'F10 = '\ue03a'F11 = '\ue03b'F12 = '\ue03c'META = '\ue03d'COMMAND = '\ue03d'
6.实现上传图片
实现在百度识图官网中上传一张图片。
from selenium import webdriver
from selenium.webdriver.edge.options import Options
edge_options = Options()
edge_options.binary_location = r""
driver = webdriver.Edge(options=edge_options)
driver.get("https://graph.baidu.com/pcpage/index?tpl_from=pc")
# 找到文件上传元素
file_input = driver.find_element_by_name("file")
# 输入图片路径
file_input.send_keys(r"E:\书\代码\识图.jpg")
第 7 行代码使用 find_element_by_name () 方法找到标签名为 file 的元素。
第 9 行代码直接使用 send_keys () 方法将图片路径以字符串的形式写入标签名为 file 的元素中,至此即可实现上传图片。执行代码后将自动打开百度识图官网,并将 "E:\ 书 \ 代码 \ 识图.jpg" 图片上传到网站中自动进行识别.
7.更多操作
1.模拟单击
获取网页元素后可以使用 click () 方法模拟单击元素,即模拟单击网页中的某个元素所在的位置。为了更方便且快速地进入用户需要访问的网页,接下来将使用 click () 方法实现单击人民邮电出版社官网中的 “图书”
from selenium import webdriver
from selenium.webdriver.edge.options import Options
edge_options = Options()
edge_options.binary_location = r""
driver = webdriver.Edge(options=edge_options)
driver.get("https://www.ptpress.com.cn/periodical")
elements = driver.find_elements_by_class_name("item")
for element in elements:print(element.text)
第 7 行代码使用 find_elements_by_class_name () 找到所有 class 名为 item 的元素。通过分析网页代码可知,要单击的位置处存在多个元素名称及 class 名称相同的元素,因此在使用 find_elements_by_class_name () 前要先获取 class 名称为 item 的所有元素。
第 8~11 行代码使用 for 循环分别遍历输出每个元素的内容,以便于找到需要的标签索引。
第 12 行代码确定了 “图书” 在 elements 列表中的索引为 3,并执行 click () 方法实现单击。
2.WebDriver 对象中的方法
back()
功能:返回到上一个页面。
forward()
功能:前进到下一个页面。
refresh()
功能:刷新当前页面。
quit()
功能:关闭当前浏览器。
close()
功能:关闭当前标签页(一个浏览器窗口中展示的每一个网页为一个标签页,当前标签页指当前正在显示的网页)。
from selenium import webdriver
from selenium.webdriver.edge.options import Options
import time
edge_options = Options()
edge_options.binary_location = r""
driver = webdriver.Edge(options=edge_options)
driver.get('https://www.ptpress.com.cn/')
elments = driver.find_elements_by_class_name("item")
elments[3].click() #点击图书
driver.back() #返回上一页
time.sleep(5)
driver.forward() #前进一页
time.sleep(5)
driver.refresh() #刷新网页
time.sleep(5)
driver.quit() #关闭浏览器
第 10 行代码使用 back () 方法实现返回上一个页面,即从图书页返回到官网主页。
第 12 行代码使用 forward () 方法再次从官网主页前进到图书页。
第 14 行代码使用 refresh () 方法实现刷新页面。
第 16 行代码使用 quit () 方法自动关闭当前的浏览器
而 sleep (5) 函数,这是为了避免代码执行过快而加入的暂停操作,便于观察显示效果。
3.不启动浏览器也能获取网页资源
在通过代码获取网页中的资源时,往往并不需要启动浏览器,因为用户需要获取的是处理后的结果,而不是展现的过程。因此在驱动浏览器时,可以设置无窗口模式,即驱动浏览器后并不会打开浏览器窗口,而是将网页代码在内存中处理,类 Options 中的 add_argument () 方法即可实现在不启动浏览器的情况下获取网页资源。其使用形式如下(写入参数 '--headless' 即表明不启动浏览器窗口):
chrome_options.add_argument('--headless')
from selenium import webdriver
from selenium.webdriver.edge.options import Options
edge_options = Options()
edge_options.add_argument('--headless')
edge_options.binary_location = r""
driver = webdriver.Chrome(options=edge_options)
driver.get("https://www.ptpress.com.cn/")
elements = driver.find_elements_by_tag_name("a")
for element in elements:print(element.text)
第 4 行代码设置浏览器启动无窗口模式。因此执行代码后虽然不会显示浏览器,但浏览器仍然会在内存中进行网页数据处理。
第 9~10 行代码获取人民邮电出版社官网中所有标签名为 a 的文本内容。读者可自行实践操作并观察执行代码后的显示效果。