如何在Python中使用Selenium进行网页抓取
Selenium 是 Python 开发人员的关键抓取工具之一。欢迎来了解如何使用它以更少的麻烦成功地执行您的抓取任务。
Python 中用于抓取的实际工具是 Requests 和 Beautifulsoup 的组合,或者是抓取框架。这两个方法都非常快速且易于使用,直到您需要渲染 JavaScript 时,您才会发现它们是多么无用。
在渲染 Javascript 时,您将需要使用无头浏览器来访问和抓取感兴趣的内容。不同的编程语言都有专门的工具来抓取 JavaScript 密集型页面。Python 将 Selenium 作为可用的流行选项。
您熟悉 Selenium Web 驱动程序吗?你知道如何利用它吗?如果您确实知道如何利用它从网络上抓取数据,那么这篇文章就是为您编写的。
读完本文后,您应该了解如何使用 Selenium 完成常见任务。诸如如何设置、访问网页、查找元素、单击按钮、滚动等任务。
Selenium概述
如果您访问Selenium Web 驱动程序的官方网站,您会注意到这样一句话:Selenium 自动化 Web 浏览器;你选择做什么取决于你。这是迄今为止对该工具最好的描述——您只需将其适应您的用例即可。
在我们自己的例子中,我们选择使用 Selenium 进行网页抓取。Python 开发人员可用的旧版 Web 抓取工具不支持JavaScript 渲染。使用 Selenium,您可以自动使用您最喜欢的浏览器来加载页面并呈现其所有内容,以便您可以从中抓取内容。
与其他特定于某种编程语言的网络抓取工具不同,Selenium 确实支持多种编程语言。
除了 Python 之外,它还支持 Java、NodeJS、Ruby 和 C#。您可以在 Windows、Mac 和 Linux 上使用此工具。就您可以使用此工具控制的 Web 浏览器而言,Selenium Web 驱动程序可以自动化 Chrome、Firefox、Edge、Opera、Safari 和 Internet Explorer。
正如您所看到的,Selenium 是一种可以在多种平台、浏览器和编程语言上使用的工具。它与 Puppeteer 有很大不同,后者仅适用于仅自动化 Chrome Web 浏览器的 NodeJS 开发人员。
Python 的 Selenium 安装指南
Selenium 新手面临的主要问题之一是它的安装。安装并不像安装类似 Puppeteer 甚至 Scrapy 那样简单。有些事情你必须自己完成。除了安装 Python 之外,您还需要安装 Selenium,然后安装您想要自动化的浏览器的特定驱动程序。以下是在您的设备上安装 Selenium 的其他步骤。
步骤1:从Python官方网站安装最新版本的Python 。您的计算机上可能已经安装了 Python。但是,它很可能是 Python 2 版本。这就是为什么您需要安装最新版本(Python 3)。
步骤 2:在命令提示符中运行“python —version”命令以验证 Python 是否已成功安装,然后再继续下一步。
步骤3:运行“pip install selenium”命令安装Selenium。安装完成后,您就成功安装了 Selenium。但是,这并不意味着您还可以使用它。它有一个您需要安装的依赖项,即您要安装的特定驱动程序的 Web 驱动程序。我们将使用 Chrome 进行自动化,因此,我们必须使用 Chrome Web 驱动程序。
步骤 4:从此页面下载适合您的 Chrome 版本的 Chrome 驱动程序。如果您下载其他版本的版本,Selenium 将无法工作。
第 5 步:解压缩下载的文件并将其放入一个文件夹中 – 这将是本指南的项目文件夹。
通过上述内容,您已经成功设置了 Selenium,并且可以继续开始在 Python 中自动执行 Web 抓取任务。
要验证安装以及一切是否正确,请创建一个新的 python 文件并运行以下代码。
指南项目
虽然您可以通过逐步学习而不参与项目来学习 Selenium,但我建议您通过执行一些项目来学习它。因此,我们将在这里边学习边开展一个项目。我们将从事的项目是一个网络抓取工具,用于抓取域名的过期日期。该项目非常容易开发,可以作为一个很好的初学者指南。我们将带您了解如何在 Selenium 中实现某些任务的具体过程。
项目解决方案
要为这个项目开发网络爬虫,我们需要知道它是如何手动完成的,然后用Python将其自动化对我们来说并不是一件困难的任务。ICANN 域名查找工具是您可以用来检查与域名相关的大量详细信息(包括其到期日期)的网站之一。我们所要做的就是访问该网站,输入我们的域名及其扩展名,然后单击提交按钮。这些是要在代码中复制的操作。
第 1 步:发送 Web 请求
在 Python 中使用 Selenium 可以执行的最基本任务是打开网页。有趣的是,这甚至是使用它自动化任务所需的第一步。这是因为在抓取数据之前,您必须有权访问呈现感兴趣数据的页面。Selenium 有一个简单的方法,称为“get”,类似于 Requests 模块的“get”方法,您可以使用该方法在其他模块中发送 Web 请求来加载页面。我们将使用该方法来加载网页。以下是加载 ICANN 域查找工具的代码。
from selenium.webdriver import Chrome browser = Chrome() browser.get("https://lookup.icann.org/en")
第 2 步:填写表格
Selenium 网络抓取的另一个重要方面是填写表格。如果您使用 requests 和 Beautifulsoup,您只需添加表单输入的值作为有效负载。对于 Selenium,必须加载页面,然后您自己添加值。在我们的例子中,我们将添加该值,就像从键盘输入一样。这是 Selenium 的优势之一——如果使用得当,它会让自动化看起来像手工工作。
为了在表单中输入域名,您需要知道搜索输入框的 ID 或类别。为此,请务必使用开发人员工具检查页面。对于 Chrome 用户,请转到菜单,向下滚动到“更多工具”,然后单击“开发人员工具”。确保“元素”选项卡处于焦点位置。
从上面可以看出,搜索输入表单的id是“input-domain”。要获取此元素,我们可以在浏览器元素上使用 find_element_by_id 方法,然后使用 send_keys 方法输入域。下面是代码。
from selenium.webdriver import Chrome browser = Chrome() browser.get("https://lookup.icann.org/en") searchbox = browser.find_element_by_id("input-domain") searchbox.send_keys("twitter.com" )
第三步:提交表格
发送表单的方式取决于该表单的构建方式。对于某些情况,您可以在表单上使用提交方法。对于其他人,您需要按住特定的提交按钮才能执行此操作。在这种情况下,我们需要抓住特定的按钮。
从上面的屏幕截图中,您可以在搜索输入框正下方看到提交按钮(查找)HTML 元素。它的类名称为“submit-lookup”。我们使用 find_element_by_class 方法来获取它,然后单击按钮提交表单。下面是包含该项目的提交表单按钮的代码。
from selenium.webdriver import Chrome browser = Chrome() browser.get("https://lookup.icann.org/en") searchbox = browser.find_element_by_id("input-domain") searchbox.send_keys("twitter.com") browser.find_element_by_class_name("submit-lookup").click()
第 4 步:抓取域名过期详细信息
该步骤是抓取域名到期详细信息。到目前为止的代码将打开该工具的页面,输入域名,然后单击“查找”按钮。这将获取要加载的域详细信息页面。由于我们没有使用无头 Chrome 配置,因此您将看到 Chrome 加载并且发生上述所有操作。域详细信息页面的一件事是您需要等待它加载。如果不等待,您将无法获取数据,因为页面将在数据加载之前打开 – 某种 JavaScript 渲染正在发挥作用。Selenium 确实提供了一个等待函数,您将在下面的代码中看到它。
from selenium.webdriver import Chrome from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.common.exceptions import TimeoutException browser = Chrome() browser.get("https://lookup.icann.org/en") searchbox = browser.find_element_by_id("input-domain") searchbox.send_keys("twitter.com") browser.find_element_by_class_name("submit-lookup").click() try: myElem = WebDriverWait(browser, 7).until(EC.presence_of_element_located((By.CLASS_NAME, 'registry-expiration'))) c = browser.find_element_by_class_name("registry-expiration") print(c.text) except TimeoutException: print("Something went wrong") browser.close()
第 5 步:优化代码
上面的代码有效。但它并不灵活。当您需要检查域名到期日期时,您将需要输入域名。让我们将代码构造成一个函数,以便它将域名作为输入并在控制台中打印其到期日期。
from selenium.webdriver import Chrome from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.common.exceptions import TimeoutException def domain_expiration_date(domain_name): """extract domain expiration date""" browser = Chrome("/Users/abdulwaliyahaya/Desktop/Automate/chromedriver") browser.get("https://lookup.icann.org/en") searchbox = browser.find_element_by_id("input-domain") searchbox.send_keys(domain_name) browser.find_element_by_class_name("submit-lookup").click() try: myElem = WebDriverWait(browser, 7).until(EC.presence_of_element_located((By.CLASS_NAME, 'registry-expiration'))) c = browser.find_element_by_class_name("registry-expiration") print(c.text) except TimeoutException: print("Something went wrong") browser.close() domain_list = ["amazon.com", "facebook.com", "twitter.com"] for i in domain_list: domain_expiration_date(i)
其他重要的Selenium功能
以上是如何完成感兴趣的项目的步骤。由于我们的注意力集中,Python 的 Selenium 网络抓取的一些关键方面被忽略了。在本节中,我们将了解其中的一些内容,以便为您提供 Selenium Web 驱动程序的良好背景知识,以便更好地了解如何使用它。
无头模式
Selenium Web 驱动程序自动化基本上有两种类型的模式。有一种头部模式,即上面指南中使用的一种。对于此模式,您将看到浏览器 UI 启动,并看到浏览器正在自动执行其任务。此方法只能用于调试目的。在生产环境中流行的另一种方法是无头模式。对于无头模式,不会启动任何浏览器供您查看,因此速度更快且消耗的资源更少。以下是如何在无头模式下使用 Selenium。
from selenium import webdriver from selenium.webdriver.chrome.options import Options options = Options() options.headless = True options.add_argument("--window-size=1920,1200") driver = webdriver.Chrome(options=options, executable_path=DRIVER_PATH)
Selenium页面属性
您可以使用 Selenium 抓取一些特定的页面属性。Selenium 使您可以轻松访问页面标题、当前 URL,甚至完整源代码。您还可以调整屏幕和许多其他分辨率。下面的代码向您展示了如何抓取页面标题、当前 URL 和整页源代码 (HTML)。
from selenium import webdriver from selenium.webdriver.chrome.options import Options options = Options() options.headless = True driver = webdriver.Chrome(options=options) driver.get(“https://www.twitter.com/”) print(driver.page_source) print(driver.title) print(driver.current_url) driver.quit()
在页面上定位元素
网页是使用 HTML 标记设计的。这些是指定页面结构的元素。这些元素有一些属性,如类、ID,以及一些自定义属性,如“data-**”,可用于识别它们。一旦页面上的元素可以使用其类、ID 或其他属性唯一地标识或访问,那么定位它并抓取其中的文本内容就变得很容易。
您可以使用元素的类、ID、名称和标签等来查找页面上的元素。下面的代码向您展示了如何使用 Selenium 和 Python 来定位页面上的元素。如果没有这个,您将无法成功使用 Selenium 进行抓取。
driver.find_element(By.NAME, 'h1') driver.find_element(By.CLASS_NAME, 'someclass') driver.find_element(By.XPATH, '//h1') driver.find_element(By.XPATH, '/html/ body/h1') driver.find_element(By.ID, 'greatID')
结论
毫无疑问,Selenium 具有一些功能,如果使用正确,抓取依赖于 JavaScript 的页面会变得更容易。虽然它们非常适合网络抓取,但除非您使用一些规避技术,否则它们也很容易被检测到。重要的是您要知道,除非需要 JavaScript 渲染,否则 Selenium 并不是 Python 中网页抓取的最佳工具。
这是因为与不渲染 JavaScript 的工具相比,它是 Python 中最慢的抓取工具之一。从上面的内容中,您可以看出它的适应性如何,因此,除了网页抓取之外,您还可以将其用于一般自动化。