> 技术文档 > Python编程进阶知识之第二课学习网络爬虫(selenium)

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文件中的类WebDriverwebdriver.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 webdriverfrom selenium.webdriver.edge.options import Optionsedge_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): ... # 获取当前网页的URL def 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): ... # 返回一组字典,对应于当前会话中可见的cookie def get_cookie(self, name): ... # 按名称获取单个Cookie def delete_cookie(self, name): ... # 删除指定名称的单个Cookie def delete_all_cookies(self): ... # 删除该会话范围内的所有Cookie def 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 webdriverfrom selenium.webdriver.edge.options import Optionsedge_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 webdriverfrom selenium.webdriver.edge.options import Optionsedge_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 webdriverfrom selenium.webdriver.edge.options import Optionsedge_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 webdriverfrom selenium.webdriver.chrome.options import Optionsfrom selenium.webdriver.common.keys import Keysedge_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 webdriverfrom selenium.webdriver.edge.options import Optionsfrom selenium.webdriver.common.keys import Keysedge_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\' # ^break HELP = \'\\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 webdriverfrom selenium.webdriver.edge.options import Optionsedge_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 webdriverfrom selenium.webdriver.edge.options import Optionsedge_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 webdriverfrom selenium.webdriver.edge.options import Optionsimport timeedge_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 webdriverfrom selenium.webdriver.edge.options import Optionsedge_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 的文本内容。读者可自行实践操作并观察执行代码后的显示效果。