Python Web Scraping 简明教程

Python Web Scraping - Testing with Scrapers

本章介绍如何在 Python 中使用网络抓取进行测试。

Introduction

在大型网络项目中,网站后端的自动化测试会定期进行,但前端测试往往会被跳过。其主要原因在于,网站的编程就像各种标记和编程语言的网络。我们可以针对一种语言编写单元测试,但如果交互是使用另一种语言完成的,就会变得具有挑战性。这就是说,我们必须拥有一套测试,以确保我们的代码按预期执行。

Testing using Python

当我们谈论测试时,意思是说单元测试。在深入探究使用 Python 进行测试之前,我们必须了解单元测试。以下是单元测试的一些特征:

  1. 单元测试中会测试组件功能的一个方面。

  2. 每个单元测试都是独立的,还可以独立运行。

  3. 单元测试不会影响任何其他测试的成功或失败。

  4. 单元测试可以按任意顺序运行,且必须包含至少一个断言。

Unittest − Python Module

名为 Unittest 的 Python 模块用于单元测试,该模块附带所有标准 Python 安装。我们只需要导入它,其余的就是 unittest.TestCase 类的任务,它将执行以下操作:

  1. unittest.TestCase 类提供了 SetUp 和 tearDown 函数。这些函数可以在每个单元测试前和后运行。

  2. 它还提供 assert 语句以使测试能够通过或失败。

  3. 它会运行所有以 test_ 开头的函数,作为单元测试。

Example

在这个示例中,我们将结合 unittest 使用网络抓取。我们将测试 Wikipedia 页面,以搜索字符串“Python”。它主要会执行两个测试:第一个测试是,标题页面是与搜索字符串(即“Python”)相同或不同;第二个测试是,页面包含一个内容块 div。

首先,我们将导入必需的 Python 模块。我们使用 BeautifulSoup 进行网络抓取,当然我们也使用 unittest 进行测试。

from urllib.request import urlopen
from bs4 import BeautifulSoup
import unittest

现在,我们需要定义一个类,它将扩展 unittest.TestCase。全局对象 bs 将会在所有测试之间共享。由 unittest 指定的函数 setUpClass 将会完成它。这里我们将定义两个函数,一个用于测试标题页面,另一个用于测试页面内容。

class Test(unittest.TestCase):
   bs = None
   def setUpClass():
      url = '<a target="_blank" rel="nofollow" href="https://en.wikipedia.org/wiki/Python">https://en.wikipedia.org/wiki/Python'</a>
      Test.bs = BeautifulSoup(urlopen(url), 'html.parser')
   def test_titleText(self):
      pageTitle = Test.bs.find('h1').get_text()
      self.assertEqual('Python', pageTitle);
   def test_contentExists(self):
      content = Test.bs.find('div',{'id':'mw-content-text'})
      self.assertIsNotNone(content)
if __name__ == '__main__':
   unittest.main()

在运行完上述脚本后,我们将获得以下输出:

----------------------------------------------------------------------
Ran 2 tests in 2.773s

OK
An exception has occurred, use %tb to see the full traceback.

SystemExit: False

D:\ProgramData\lib\site-packages\IPython\core\interactiveshell.py:2870:
UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
 warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)

Testing with Selenium

让我们讨论如何使用 Python Selenium 进行测试。这也被称为 Selenium 测试。Python unittestSelenium 并没有太多共同点。我们知道 Selenium 将标准的 Python 命令发送到不同的浏览器,尽管它们的浏览器设计存在差异性。请记住,我们已经在之前的章节中安装了 Selenium 并使用过它。我们将在 Selenium 中创建测试脚本,并将其用于自动化。

Example

在此 Python 脚本的帮助下,我们为 Facebook 登录页面的自动化创建了测试脚本。你可以修改该示例来自动化你所选择的其他表单和登录,但其概念是一样的。

首先要连接到 Web 浏览器,我们要从 selenium 模块导入 webdriver −

from selenium import webdriver

现在,我们需要从 selenium 模块导入 Keys。

from selenium.webdriver.common.keys import Keys

接下来我们需要提供用于登录 Facebook 帐户的用户名和密码

user = "gauravleekha@gmail.com"
pwd = ""

接下来,提供 Chrome 的 Web 驱动程序路径。

path = r'C:\\Users\\gaurav\\Desktop\\Chromedriver'
driver = webdriver.Chrome(executable_path=path)
driver.get("http://www.facebook.com")

现在,我们将使用 assert 关键字来验证条件。

assert "Facebook" in driver.title

通过下面的代码行,我们正在将值发送到电子邮件部分。我们在这里通过其 id 进行搜索,但我们可以通过按 name driver.find_element_by_name("email") 进行搜索来执行此操作。

element = driver.find_element_by_id("email")
element.send_keys(user)

通过下面的代码行,我们正在将值发送到密码部分。我们在这里通过其 id 进行搜索,但我们可以通过按 name driver.find_element_by_name("pass") 进行搜索来执行此操作。

element = driver.find_element_by_id("pass")
element.send_keys(pwd)

下一行代码用于在电子邮件和密码字段中插入值后按回车键/登录。

element.send_keys(Keys.RETURN)

现在,我们将关闭浏览器。

driver.close()

运行完上述脚本后,Chrome Web 浏览器将会打开,并且您可以看到电子邮件和密码正在被插入并单击登录按钮。

facebook login

Comparison: unittest or Selenium

unittest 和 selenium 的比较很困难,因为如果您想使用大型测试套件,那么需要 unites 的句法灵活性。另一方面,如果您要测试网站灵活性,那么 Selenium 测试将是我们的首选。但是如果我们可以将它们结合起来呢。我们可以将 selenium 导入 Python unittest 并充分利用两者。Selenium 可用于获取有关网站的信息,unittest 可评估该信息是否符合通过测试的标准。

例如,我们对上述 Python 脚本重新编制,以便通过结合两者自动执行 Facebook 登录,如下所示 −

import unittest
from selenium import webdriver

class InputFormsCheck(unittest.TestCase):
   def setUp(self):
      self.driver = webdriver.Chrome(r'C:\Users\gaurav\Desktop\chromedriver')
      def test_singleInputField(self):
      user = "gauravleekha@gmail.com"
      pwd = ""
      pageUrl = "http://www.facebook.com"
      driver=self.driver
      driver.maximize_window()
      driver.get(pageUrl)
      assert "Facebook" in driver.title
      elem = driver.find_element_by_id("email")
      elem.send_keys(user)
      elem = driver.find_element_by_id("pass")
      elem.send_keys(pwd)
      elem.send_keys(Keys.RETURN)
   def tearDown(self):
      self.driver.close()
if __name__ == "__main__":
   unittest.main()