Skip to content

Latest commit

 

History

History
636 lines (427 loc) · 35.2 KB

File metadata and controls

636 lines (427 loc) · 35.2 KB

八、使用 Selenium 爬取

到目前为止,我们已经学习了如何使用许多数据查找技术,以及如何通过实现各种用于 web 抓取的 Python 库来访问 web 内容

Selenium 是一个 web 应用程序测试框架,它自动化了浏览操作,可以用于简单和复杂的 web 抓取活动。Selenium 提供 web 浏览器作为界面或自动化工具。使用 JavaScript、cookie、脚本等的动态或安全 web 内容在 Selenium 的帮助下被加载、测试,甚至被删除。

关于 Selenium 框架有很多东西需要学习。在本章中,我们将介绍与 web 抓取相关的框架的主要概念。

本章将涵盖以下主题:

  • 硒简介
  • 使用 Selenium 进行 web 抓取

技术要求

本章需要 web 浏览器(Google Chrome 或 Mozilla Firefox),我们将使用以下 Python 库:

  • selenium(Python 库)
  • re

如果您当前的 Python 设置中没有这些库,那么您可以通过参考第 2 章Python 和 Web 中的设置部分,使用 urllib 和请求来设置或安装它们

除了前面提到的 Python 库和 web 浏览器之外,我们还将使用用于 Google Chrome 的 WebDriver。

代码文件可在线访问https://github.com/PacktPublishing/Hands-On-Web-Scraping-with-Python/tree/master/Chapter08

硒简介

正如我提到的,Selenium 是一个 web 应用程序框架,可用于 web 抓取活动。它还可以用作浏览器自动化工具

与 web 应用程序相关的任务或活动(如以下列表中的任务或活动)的自动化涉及在没有人直接参与的情况下执行的任务:

  • 浏览
  • 点击链接
  • 保存屏幕截图
  • 下载图像
  • 填写 HTML<form>模板和更多活动

Selenium 提供 web 浏览器作为界面或自动化工具。随着浏览操作的自动化,Selenium 也可以用于 web 抓取。使用 JavaScript、cookie、脚本等的动态或安全 web 服务在 Selenium 的帮助下被加载、测试、甚至爬网和抓取

Selenium 是开源的,可以跨多个平台访问。可以使用 Java 和 Python 等编程语言可用的库使用各种 web 浏览器进行测试。库用于创建与 Selenium 交互的脚本,以执行基于浏览器的自动化。

虽然在应用程序测试中使用 Selenium 在爬行和刮取等操作方面有很多优点,但也有其缺点,如时间和内存消耗。Selenium 是可扩展且有效的,但执行其操作的速度较慢,并且消耗大量内存空间。

For more detailed information on Selenium, please visit https://www.seleniumhq.org/.

在下一节中,我们将设置 SeleniumWebDriver 并使用 Python 库测试该设置,可以在中找到该库 https://selenium-python.readthedocs.io/

Selenium is a web testing framework, whereas Selenium (https://pypi.org/project/selenium/) is a Python library that binds Selenium WebDriver or is used to create scripts to interact with Selenium.

执行应用程序测试以确保应用程序满足要求,并检测错误和错误以确保产品质量。可以手动(在用户的帮助下)或使用自动化工具(如 Selenium)进行。测试基于 web 的应用程序是在通过 internet 启动应用程序之前完成的

硒项目

Selenium 由多个组件或工具组成,也称为 Selenium 项目,这使它成为基于 web 的应用程序测试的完整框架。现在我们来看看这些硒项目的一些主要组成部分

Selenium Web 驱动程序

Selenium WebDriver 是 Selenium 的一个组件,用于自动化浏览器。通过使用第三方驱动程序,如 Google Chrome 驱动程序、Mozilla Gecko 驱动程序和 Opera(等),为 Java、Python、JavaScript 等提供各种语言绑定的命令,可以实现浏览器的自动化 https://github.com/mozilla/geckodriver/ )。Selenium WebDriver 对任何其他软件或服务器都没有外部依赖性。

WebDriver 是一种面向对象的 API,具有更新的功能,克服并解决了以前的 Selenium 版本和 Selenium远程控制RC的限制。请访问 Selenium WebDriver 网页(https://www.seleniumhq.org/projects/webdriver/ 了解更多信息。

硒 RC

Selenium RC 是一个用 Java 编程的服务器。它使用 HTTP 接受浏览器的命令,并用于测试复杂的基于 AJAX 的 web 应用程序。

Selenium RC has been officially deprecated following the release of Selenium 2 (Selenium version 2). However, WebDriver contains the major features of Selenium RC. Please visit https://www.seleniumhq.org/projects/remote-control/ for more information. 

硒栅

Selenium Grid 也是一个服务器,它允许测试在多台机器上跨多个浏览器和操作系统并行运行,从而分配系统负载并减少性能问题,如时间消耗

采用复合试验将硒 RC 和硒格栅一起处理。自 2.0 版发布以来,Selenium 服务器现在内置了对 WebDriver、Selenium RC 和 Selenium Grid 的支持。请访问 Selenium Grid 网页(https://www.seleniumhq.org/projects/grid/ 了解更多信息

它包含了测试的录制

使用一个开源的 Selenium集成开发环境IDE)用 Selenium 构建测试用例。它基本上是一个 web 浏览器扩展,具有通过图形用户****界面GUI录制和播放 web 自动化等功能。

以下是 Selenium IDE 的几个关键功能:

  • 可扩展且易于调试
  • 弹性试验
  • 跨浏览器支持
  • 可以创建可以运行命令和支持控制流结构的脚本

请访问 Selenium IDE 网页(https://www.seleniumhq.org/selenium-ide/ 了解更多信息和安装程序。请访问 Selenium 项目网页(https://www.seleniumhq.org/projects/ 了解更多有关硒成分的信息。

现在我们知道了 Selenium 的用途及其一些主要组件,让我们看看如何使用 SeleniumWebDriver 安装和执行常规测试。

摆设

为了使用 Selenium 成功实现浏览器自动化和应用程序测试,需要设置 WebDriver。让我们通过以下步骤为 Google Chrome 设置 WebDriver:

  1. 访问https://www.seleniumhq.org/

SeleniumHQ Browser Automation main page

  1. 点击下载(或浏览至https://www.seleniumhq.org/download/ )。
  2. 在第三方驱动程序、绑定和插件部分下,单击 Google Chrome 驱动程序(或浏览至https://sites.google.com/a/chromium.org/chromedriver/

Third -party drivers, Selenium

  1. 来自 ChromeDriver-WebDriver for Chrome(https://sites.google.com/a/chromium.org/chromedriver ),下载 ChromeDriver 最新稳定版本,适合平台:

ChromeDriver listings

  1. 解压下载的chromedriver*.zip。应出现一个名为chromedriver.exe的应用程序文件。我们可以将.exe文件放在包含代码的主文件夹中。

We will be using Google Chrome and ChromeDriver throughout the chapter; for details about using other browsers, or more information on Selenium, please visit   SeleniumHQ . For more information on the installation, please refer to https://selenium-python.readthedocs.io/installation.html.

现在我们已经完成了 WebDriver 和 Selenium Python 库的设置,让我们通过 Python IDE 验证这个设置。如下图所示,selenium包含webdriver模块,子模块有ChromeAndroidFirefoxIeOpera等。当前版本为3.14.1

Printing the selenium.webdriver version 

我们将在 Google Chrome 中使用 Selenium,因此让我们来探索webdriver中的Chrome内容:

Exploring Chrome from Selenium WebDriver.

如前一个屏幕截图所示,有许多函数将被调用并用于实现浏览器自动化。您还可以看到,有许多函数名以find_element*开头,类似于我们在前面的刮片活动章节中使用和学习的遍历和解析函数。

在下一节中,我们将了解selenium.webdriver

硒的探索

在本节中,我们将使用并介绍webdriverwebdriver.Chrome的各种属性,同时查看一些实际案例。以下各节将说明硒的使用并探索其主要属性。

访问浏览器属性

在本节中,我们将演示如何使用 Selenium 和 Chrome WebDriver 加载带有 URL 的 Google Chrome 并访问某些基于浏览器的功能。

首先,让我们从selenium导入webdriver并将路径设置为chromedriver.exe——我们称之为chromedriver_path。加载 Google Chrome 需要创建的路径。根据应用程序的位置,应提及chromedriver.exe的完整路径,并且是成功实施所必需的:

    from     selenium     import     webdriver
import re

#setting up path to 'chromedriver.exe'
chromedriver_path=    'chromedriver' #C:\\Users\\....\\...\chromedriver.exe     

selenium.webdriver用于实现各种浏览器,在本例中为 Google Chrome。webdriver.Chrome()短语提供了 Chrome WebDriver 的路径,以便chromedriver_path可以用于执行。

短语driverselenium.webdriver.chrome.webdriver.WebDriver类的对象,它是使用webdriver.Chrome()创建的,现在它将提供对webdriver中各种属性和属性的访问:

driver = webdriver.Chrome(    executable_path    =chromedriver_path)

chromedriver.exe将在此实例或创建driver 对象时实例化。将加载终端屏幕和 Google Chrome 的空新窗口,如以下屏幕截图所示:

The Terminal screen and empty browser page

如果到目前为止在执行代码时遇到任何错误,请执行以下步骤,然后再次执行代码:

  1. 获取最新的 ChromeDriver 并更换现有的 ChromeDriver
  2. 更新并验证chromedriver_pathPATH

Google Chrome 的新窗口将使用webdriver中的get()函数提供 URL。

get()短语接受要加载到浏览器上的 URL。让我们提供https://www.python.org 作为get()的参数;浏览器将开始加载 URL,如以下屏幕截图所示:

driver.get('https://www.python.org')

正如您在下面的屏幕截图中所看到的,地址栏下方会显示一条通知,其中包含消息Chrome 正在由自动测试软件控制。此消息还确认了selenium.webdriver活动的成功执行,并且可以为其提供进一步的代码,以对已加载的页面进行操作或使其自动化:

Chrome browser loaded with https://www.python.org

成功加载页面后,我们可以使用driver访问和探索其属性。为了说明这一点,让我们从 HTML<title>标记中提取或打印标题,并打印可访问的当前 URL:

print("Title: ",driver.title) #print <title> text
Title:  Welcome to Python.org

print("Current Page URL: ",driver.current_url) #print current url, loaded in the browser
Current Page URL:  https://www.python.org/

如前代码所示,页面标题可用driver.title,当前页面 URL 用driver.current_url找到。current_url短语可用于验证加载初始 URL 后是否发生了 URL 重定向。让我们保存一个带有条件的页面截图,该条件使用 Python 库re中的search()进行验证:

#check if pattern matches the current url loaded

if re.search(r'python.org',driver.current_url):
    driver.save_screenshot("pythonorg.png") #save screenshot with provided name
    print("Python Screenshot Saved!")

save_screenshot()短语随文件名一起提供,作为图像的参数,并创建 PNG 图像。图像将保存在当前代码位置;还可以提供完整的目的地或所需的路径。

为了进一步探索,我们从收集网络 cookiehttps://www.python.orgget_cookies()短语用于检索 cookies,如下所示:

#get cookie information
cookies = driver.get_cookies() 
print("Cookies obtained from python.org")
print(cookies)

Cookies obtained from python.org
[{'domain': '.python.org', 'expiry': 1619415025, 'httpOnly': False, 'name': '__utma', 'path': '/', 'secure': False, 'value': '32101439.1226541417.1556343026.1556343026.1556343026.1'},........ {'domain': '.python.org', 'expiry': 1556343625, 'httpOnly': False, 'name': '__utmt', 'path': '/', 'secure': False, 'value': '1'}]

可使用driver.page_source获取页面来源。

要手动获取页面源,右击页面,点击查看页面源,或按Ctrl+U

print(driver.page_source) #page source

可使用driver.refresh()重新加载或刷新页面。

要手动刷新页面源,右键单击页面并单击“重新加载”,或按Ctrl+R

driver.refresh() #reload or refresh the browser

利用前面代码中使用driver访问的功能,让我们继续从加载、截图和访问 cookiehttps://www.google.com 使用以下代码:

driver.get('https://www.google.com')
print("Title: ",driver.title)
print("Current Page URL: ",driver.current_url)

if re.search(r'google.com',driver.current_url):
    driver.save_screenshot("google.png")
    print("Google Screenshot Saved!")

cookies = driver.get_cookies()

使用执行的操作 http://google.com 将在用于访问的同一浏览器窗口上进行 http://python.org 。这样,我们现在可以使用浏览器历史执行操作(即,我们将使用 web 浏览器中可用的后退和前进按钮)并检索 URL,如以下代码所示:

print("Current Page URL: ",driver.current_url)

driver.back() #History back action
print("Page URL (Back): ",driver.current_url)

driver.forward() #History forward action
print("Page URL (Forward): ",driver.current_url)

在前面的代码中,back()将浏览器返回一个页面,而forward()将其沿着浏览器历史向前移动一步。收到的输出如下:

Current Page URL: https://www.google.com/
Page URL (Back): https://www.python.org/
Page URL (Forward): https://www.google.com/

成功执行代码后,建议您关闭并退出驱动程序以释放系统资源。我们可以使用以下功能执行终止操作:

driver.close() #close browser
driver.quit()  #quit webdriver

上述代码包含以下两个短语:

  • close()终止加载的浏览器窗口
  • quit()结束 WebDriver 应用程序

到目前为止,我们在本节中执行的完整代码如下:

from selenium import webdriver
import re
chrome_path='chromedriver'
driver = webdriver.Chrome(executable_path=chrome_path)  #print(type(driver))
driver.get('https://www.python.org')  
print("Title: ",driver.title)
print("Current Page URL: ",driver.current_url)

if re.search(r'python.org',driver.current_url):
    driver.save_screenshot("pythonorg.png")
    print("Python Screenshot Saved!")
cookies = driver.get_cookies()

print(driver.page_source)
driver.refresh()

driver.get('https://www.google.com')
print("Title: ",driver.title)
print("Current Page URL: ",driver.current_url)
if re.search(r'google.com',driver.current_url):
    driver.save_screenshot("google.png")
    print("Google Screenshot Saved!")
cookies = driver.get_cookies()

print("Current Page URL: ",driver.current_url)
driver.back()
print("Page URL (Back): ",driver.current_url)
driver.forward()
print("Page URL (Forward): ",driver.current_url)

driver.close()
driver.quit()

前面的代码演示了selenium.webdriver的用法及其各种属性。在下一节中,我们将演示webdriver和 web 元素(来自 web 页面的元素)的使用。

定位 web 元素

在本节中,我们将对进行搜索 http://automationpractice.com 获取与搜索查询匹配的产品列表,说明selenium.webdriver的用法。Web 元素是在网页中列出或在网页源中找到的元素。我们还研究了一个名为WebElement的类,用作selenium.webdriver.remote.webelement.WebElement

The automation practice website (http://automationpractice.com/) is a sample e-commerce website from http://www.seleniumframework.com  that you can use for practice.

首先,我们从selenium导入webdriver,设置chromedriver.exe的路径,创建webdriver的对象,即driver,如前一节所实现,访问浏览器属性-加载 URL,http://automationpractice.com

driver.get('http://automationpractice.com')

新的 Google Chrome 窗口将加载提供的 URL。找到购物车上方的搜索(输入)框,如以下屏幕截图所示:

Inspecting elements (search box) from http://automationpractice.com

要继续在脚本中搜索,我们需要用 HTML<input>标识元素。请参考第 3 章中的使用 web 浏览器开发工具访问 web 内容部分,使用 LXML、XPath 和 CSS 选择器

在我们的例子中,搜索框可以通过前面屏幕截图中显示的属性来识别,甚至可以通过使用 XPath 或 CSS 选择器来识别:

  • id="search_query_top"
  • name="search_query"
  • class="search_query" 

selenium.webdriver提供了大量定位器(用于定位元件的方法),可方便地应用于遇到的情况。

定位器返回单个、多个或多个 WebElement 实例列表,写为selenium.webdriver.remote.webelement.WebElement*。*以下是一些定位器,并简要说明:

  • find_element_by_id():通过id 属性查找元素。此方法返回单个 WebElement*。*
  • find_element_by_name():通过name属性定义单个元素。使用find_elements_by_name()可以找到或定位多个 WebElement。
  • find_element_by_tag_name():该函数通过其 HTML 标记的名称定义单个元素。使用find_elements_by_tag_name()可以定位多个 WebElement。
  • find_element_by_class_name():通过其 class 属性定义单个元素。使用find_elements_by_class_name()可以定位多个 WebElement。 ** find_element_by_link_text():通过链接文本标识的链接定义单个元素。使用find_elements_by_link_text()可以定位多个 WebElement** find_element_by_partial_link_text()此 f 通过元素所承载的部分文本标识的链接来标识单个元素。使用 find_elements_by_partial_link_text() 可以定位多个 WebElement。** find_element_by_xpath()此函数通过提供 XPath 表达式来定义单个元素。使用find_elements_by_xpath()可以定位多个 WebElement。 *** find_element_by_css_selector():这通过提供 CSS 选择器来定义单个元素。使用find_elements_by_css_selector()可以定位多个 WebElement。 *****

***现在,让我们使用find_element_by_id()找到输入框:

searchBox = driver.find_element_by_id('search_query_top')
#searchBox = driver.find_element_by_xpath('    //*[@id="search_query_top"]    ')
#searchBox = driver.find_element_by_css_selector('    #search_query_top    ')

正如您在前面的代码中所看到的,searchBox可以使用随各自参数提供的任何方便的定位器进行定位。

可以通过以下属性和常规方法以及更多方法访问获得的 WebElement:

  • get_attribute():返回提供的键参数的属性值,如valueidnameclass
  • tag_name:返回特定 WebElement 的 HTML 标记名。
  • text:返回 WebElement 的文本。
  • clear():清除 HTML 表单元素的文本。
  • send_keys():用于填充文本,提供按键效果,如selenium.webdriver.commonselenium.webdriver.common.keys模块提供的ENTERBACKSPACEDELETE按键,可用于 HTML 表单元素。
  • click():对 WebElement 执行点击操作。这用于 HTML 元素,如 Submit 按钮。

在下面的代码中,我们将使用前面在searchBox中列出的函数和属性:

print("Type :",type(searchBox))
<class 'selenium.webdriver.remote.webelement.WebElement'>

print("Attribute Value :",searchBox.get_attribute("value")) #is empty
Attribute Value *:* 

print("Attribute Class :",searchBox.get_attribute("class"))
Attribute Class : search_query form-control ac_input

print("Tag Name :",searchBox.tag_name)
Tag Name : input

让我们清除searchBox内的文本,并输入要搜索的文本Dress。我们还需要提交位于searchBox右侧的按钮,点击它,使用 WebElement 方法click()执行搜索:

searchBox.clear() 
searchBox.send_keys("Dress")
submitButton = driver.find_element_by_name("submit_search")
submitButton.click()

浏览器将处理提交文本Dress的搜索操作并加载结果页面。

搜索操作完成后,为了验证搜索是否成功,我们将使用以下代码提取有关产品编号和计数的信息:

#find text or provided class name
resultsShowing = driver.find_element_by_class_name(    "product-count"    )
    print    (    "Results Showing: "    ,resultsShowing.text) 

Results Showing: Showing 1-7 of 7 items

#find results text using XPath
resultsFound = driver.find_element_by_xpath(    '//*[@id="center_column"]//span[@class="heading-counter"]'    )
    print    (    "Results Found: "    ,resultsFound.text)

Results Found:     7 results have been found.    

根据找到的物品数量和产品数量,这向我们的搜索过程传达了一条成功的信息。现在,我们可以继续使用 XPath、CSS 选择器等查找产品:

#Using XPath
products = driver.find_elements_by_xpath('//*[@id="center_column"]//a[@class="product-name"]')

#Using CSS Selector
#products = driver.find_elements_by_css_selector('ul.product_list li.ajax_block_product a.product-name')

foundProducts=[]
for product in products:
    foundProducts.append([product.text,product.get_attribute("href")])

从前面的代码中,迭代获得的products并将单个项添加到 Python 列表foundProducts中。product是 WebElement 的对象,即selenium.webdriver.remote.webelement.WebElement*,而属性是通过textget_attribute()采集的*

**```py print(foundProducts)

[['Printed Summer Dress', 'http://automationpractice.com/index.php?id_product=5&controller=product&search_query=Dress&results=7'], ['Printed Dress', 'http://automationpractice.com/index.php?id_product=4&controller=product&search_query=Dress&results=7'], ['Printed Summer Dress', 'http://automationpractice.com/index.php?id_product=6&controller=product&search_query=Dress&results=7'], ['Printed Chiffon Dress', 'http://automationpractice.com/index.php?id_product=7&controller=product&search_query=Dress&results=7'],['PrintedDress', 'http://automationpractice.com/index.php?id_product=3&controller=product&search_query=Dress&results=7'], ['Faded Short Sleeve T-shirts', 'http://automationpractice.com/index.php?id_product=1&controller=product&search_query=Dress&results=7'],['Blouse', 'http://automationpractice.com/index.php?id_product=2&controller=product&search_query=Dress&results=7']]


在本节中,我们探讨了`selenium.webdriver`中用于处理浏览器、使用 HTML 表单、读取页面内容等的各种属性和方法。请访问[https://selenium-python.readthedocs.io](https://selenium-python.readthedocs.io) 了解 Python Selenium 及其模块的更多详细信息。在下一节中,我们将使用本节中使用的大多数方法从网页中获取信息。

# 使用 Selenium 进行 web 抓取

Selenium 用于测试 web 应用程序。它主要用于使用各种基于编程语言的库和浏览器驱动程序执行浏览器自动化。正如我们在上一节*探索 Selenium*中所看到的,我们可以使用 Selenium 导航和定位页面中的元素,并执行爬行和抓取相关活动

让我们看几个使用 Selenium 从网页中抓取内容的示例。

# 示例 1–报废产品信息

在本例中,我们将继续使用在*探索硒*部分中从`foundProducts`获得的搜索结果

我们将从`foundProducts`中找到的每个产品链接中提取一些具体信息,如下所示:

*   `product_name`*:*产品名称
*   `product_price`*挂牌价*
**   `image_url`:产品主图像的 URL*   `item_condition`*产品状况***   `product_description`*产品简介***

 ***使用`driver.get()`加载`foundProducts`中的每个产品链接:

```py
dataSet=[]
if len(foundProducts)>0:
   for foundProduct in foundProducts:
       driver.get(foundProduct[1])

       product_url = driver.current_url
       product_name = driver.find_element_by_xpath('//*[@id="center_column"]//h1[@itemprop="name"]').text
       short_description = driver.find_element_by_xpath('//*[@id="short_description_content"]').text
       product_price = driver.find_element_by_xpath('//*[@id="our_price_display"]').text
       image_url = driver.find_element_by_xpath('//*[@id="bigpic"]').get_attribute('src')
       condition = driver.find_element_by_xpath('//*[@id="product_condition"]/span').text
       dataSet.append([product_name,product_price,condition,short_description,image_url,product_url])

print(dataSet)

要提取的目标字段或信息使用 XPath 获取,并附加到dataSet中。请参考第 3 章中的使用 web 浏览器开发工具访问 web 内容部分,使用 LXML、XPath、,和 CSS 选择器*。*

*dataSet的输出如下:

[['Printed Summer Dress','$28.98','New','Long printed dress with thin adjustable straps. V-neckline and wiring under the bust with ruffles at the bottom of the dress.', 'http://automationpractice.com/img/p/1/2/12-large_default.jpg', 'http://automationpractice.com/index.php?id_product=5&controller=product&search_query=Dress&results=7'],
['Printed Dress','$50.99','New','Printed evening dress with straight sleeves with black .............,
['Blouse','$27.00','New','Short sleeved blouse with feminine draped sleeve detail.', 'http://automationpractice.com/img/p/7/7-large_default.jpg','http://automationpractice.com/index.php?id_product=2&controller=product&search_query=Dress&results=7']]

最后,使用close()quit()保持系统资源免费。此示例的完整代码如下所示:

    from     selenium     import     webdriver
chrome_path=    'chromedriver'
    driver = webdriver.Chrome(    executable_path    =chrome_path)
driver.get(    'http://automationpractice.com'    )

searchBox = driver.find_element_by_id(    'search_query_top'    )
searchBox.clear()
searchBox.send_keys(    "Dress"    )
submitButton = driver.find_element_by_name(    "submit_search"    )
submitButton.click()

resultsShowing = driver.find_element_by_class_name(    "product-count"    )
resultsFound = driver.find_element_by_xpath(    '//*[@id="center_column"]//span[@class="heading-counter"]'    )

products = driver.find_elements_by_xpath(    '//*[@id="center_column"]//a[@class="product-name"]'    )
foundProducts=[]
    for     product     in     products:
    foundProducts.append([product.text,product.get_attribute(    "href"    )])

dataSet=[]
    if         len    (foundProducts)>    0    :
       for     foundProduct     in     foundProducts:
       driver.get(foundProduct[    1    ])
       product_url = driver.current_url
       product_name = driver.find_element_by_xpath(    '//*[@id="center_column"]//h1[@itemprop="name"]'    ).text
       short_description = driver.find_element_by_xpath(    '//*[@id="short_description_content"]'    ).text
       product_price = driver.find_element_by_xpath(    '//*[@id="our_price_display"]'    ).text
       image_url = driver.find_element_by_xpath(    '//*[@id="bigpic"]'    ).get_attribute(    'src'    )
       condition = driver.find_element_by_xpath(    '//*[@id="product_condition"]/span'    ).text
       dataSet.append([product_name,product_price,condition,short_description,image_url,product_url])

driver.close()
driver.quit()

在本例中,我们执行了基于 HTML<form>的操作,并从每个页面提取了所需的详细信息。表单处理是 web 应用程序测试期间执行的主要任务之一

示例 2–剪贴簿信息

在本例中,我们将使浏览器自动处理提供的主 URL 中的类别和分页链接。我们有兴趣从的多个页面中提取食品和饮料类别的详细信息 http://books.toscrape.com/index.html

类别中的单个页面包含产品(书籍)列表,特定信息如下所示:

  • title:所列书名
  • titleLarge所列书籍的标题(完整标题,作为title 属性的值找到) ** price:上市图书价格* stock:与上市账簿相关的股票信息* image:图书图片的 URL* starRating:评级(发现的星星数)* url:列出的每本书的 URL。*

*A similar example was also shown in Chapter 3,   Using LXML, XPath and CSS Selectors in t he section named Web Scraping Using LXML, under the name Example 2 – Looping with XPath and scraping data from multiple pages. There, we used the Python library lxml.  

导入selenium.webdriver并设置 Chrome 驱动程序路径后,开始加载http://books.toscrape.com/index.html 。当主页加载时,我们将看到各种类别出现,一个列在另一个下面。

目标类别包含文本食品和饮料,可以通过find_element_by_link_text()找到(我们可以使用任何适用的find_element...方法找到特定类别)。通过click()进一步处理找到的元素-单击返回的元素。此操作将在浏览器中加载特定类别 URL:

driver.get(    'http://books.toscrape.com/index.html'    )

driver.find_element_by_link_text(    "Food and Drink"    ).click()
    print    (    "Current Page URL: "    , driver.current_url)
totalBooks = driver.find_element_by_xpath(    "//*[@id='default']//form/strong[1]"    )
    print    (    "Found: "    , totalBooks.text)

为了处理迭代中发现的多个页面,将导入selenium.common.exceptions中的NoSuchElementException

    from     selenium.common.exceptions     import     NoSuchElementException

由于我们将在下一步使用分页按钮,NoSuchElementException将有助于处理没有找到下一页或下一页的情况

如以下代码所示,分页选项 next 位于页面中,并通过click() 操作进行处理。此操作将把它包含的 URL 加载到浏览器中,迭代将继续,直到下一个被代码中的except块捕获,在页面中找不到或找不到:

    try    :
        #Check for Pagination with text 'next'
                driver.find_element_by_link_text(    'next'    ).click()
        continue
        except     NoSuchElementException:
    page =     False    

此示例的完整代码如下所示:

    from     selenium     import     webdriver
    from     selenium.common.exceptions     import     NoSuchElementException
chrome_path =     'chromedriver'
    driver = webdriver.Chrome(    executable_path    =chrome_path)
driver.get(    'http://books.toscrape.com/index.html'    )

dataSet = []
driver.find_element_by_link_text(    "Food and Drink"    ).click()
totalBooks = driver.find_element_by_xpath(    "//*[@id='default']//form/strong[1]"    )

page =     True
        while     page:
    listings = driver.find_elements_by_xpath(    "//*[@id='default']//ol/li[position()>0]"    )
        for     listing     in     listings:
        url=listing.find_element_by_xpath(    ".//article[contains(@class,'product_pod')]/h3/a"    ). get_attribute(    'href'    )
        title=listing.find_element_by_xpath(    ".//article[contains(@class,'product_pod')]/h3/a"    ).text
        titleLarge=listing.find_element_by_xpath(    ".//article[contains(@class,'product_pod')]/h3/a"    ). get_attribute(    'title'    )
        price=listing.find_element_by_xpath(    ".//article/div[2]/p[contains(@class,'price_color')]"    ).text
        stock=listing.find_element_by_xpath(    ".//article/div[2]/p[2][contains(@class,'availability')]"    ). text
        image=listing.find_element_by_xpath(    ".//article/div[1][contains(@class,'image_container')]/a/img"    ) .get_attribute(    'src'    )
        starRating=listing.find_element_by_xpath(    ".//article/p[contains(@class,'star-rating')]"    ). get_attribute(    'class'    )
        dataSet.append([titleLarge,title,price,stock,image,starRating.replace(    'star-rating '    ,    ''    ),url])

        try    :
                driver.find_element_by_link_text(    'next'    ).click()
            continue
            except     NoSuchElementException:
        page =     False

driver.close()
driver.quit()

最后,迭代完成后,dataSet将包含所有页面的列表数据,如下所示:

[['Foolproof Preserving: A Guide to Small Batch Jams, Jellies, Pickles, Condiments, and More: A Foolproof Guide to Making Small Batch Jams, Jellies, Pickles, Condiments, and More', 'Foolproof Preserving: A Guide ...','£30.52','In stock', 'http://books.toscrape.com/media/cache/9f/59/9f59f01fa916a7bb8f0b28a4012179a4.jpg','Three','http://books.toscrape.com/catalogue/foolproof-preserving-a-guide-to-small-batch-jams-jellies-pickles-condiments-and-more-a-foolproof-guide-to-making-small-batch-jams-jellies-pickles-condiments-and-more_978/index.html'], ['The Pioneer Woman Cooks: Dinnertime: Comfort Classics, Freezer Food, 16-Minute Meals, and Other Delicious Ways to Solve Supper!', 'The Pioneer Woman Cooks: ...', '£56.41', 'In stock', 'http://books.toscrape.com/media/cache/b7/f4/b7f4843dbe062d44be1ffcfa16b2faa4.jpg', 'One', 'http://books.toscrape.com/catalogue/the-pioneer-woman-cooks-dinnertime-comfort-classics-freezer-food-16-minute-meals-and-other-delicious-ways-to-solve-supper_943/index.html'],................, 
['Hungry Girl Clean & Hungry: Easy All-Natural Recipes for Healthy Eating in the Real World', 'Hungry Girl Clean & ...', '£33.14', 'In stock', 'http://books.toscrape.com/media/cache/6f/c4/6fc450625cd672e871a6176f74909be2.jpg', 'Three', 'http://books.toscrape.com/catalogue/hungry-girl-clean-hungry-easy-all-natural-recipes-for-healthy-eating-in-the-real-world_171/index.html']]

在本节中,我们探讨了selenium.webdriver中的方法和属性,并将其用于 web 抓取活动。

总结

在本章中,我们学习了 Selenium,并使用 Selenium 的 Python 库执行浏览器自动化、web 内容的抓取、基于浏览器的活动以及 HTML<form>处理。Selenium 可用于处理多个活动,这是 Selenium 相对于 Python 专用库(如lxmlpyquerybs4scrapy)的主要优势之一

在下一章中,我们将学习更多关于使用正则表达式的 web 抓取技术。

进一步阅读