对于使用JavaScript丰富构建的动态网站,Selenium是从中提取数据的首选工具。现在就来阅读本文,以了解如何使用Selenium从网页中提取数据。
从中抓取数据最容易的网站是静态页面,可根据要求下载所有内容。可悲的是,这些类型的网站正在逐渐淡出,动态网站正在逐渐接管。
对于动态网站,加载页面时不会提供页面上的所有内容,而是在特定的JavaScript事件之后动态添加内容,这与为静态网站设计的抓取工具带来了不同的问题。幸运的是,使用Selenium之类的工具,无论页面的JavaScript丰富程度如何,您都可以触发JavaScript事件并抓取所需的任何页面。
使用Selenium,您就不会像其他工具那样局限于一种语言。Selenium支持Python,Ruby,Java,C#和JavaScript。在本文中,我们将利用Selenium和Python提取Web数据。在进行详细介绍之前,明智的做法是查看Selenium和何时应使用它的实例。
目录
Selenium WebDriver –概述
Selenium最初不是为Web抓取而开发的-最初是为测试Web应用程序而开发的,但已发现其在Web抓取中的用途。从技术上讲,Selenium或更合适的是Selenium WebDriver是用于测试Web应用程序的可移植框架。
简而言之,Selenium所做的就是使Web浏览器自动化。正如Selenium背后的团队正确地指出的那样,您使用该功能的一切取决于您!Selenium支持Windows,macOS和Linux。在浏览器支持方面,您可以使用它来自动执行Chrome,Firefox,Internet Explorer,Edge和Safari。同样重要的是,可以使用第三方插件扩展Selenium。
使用Selenium,您可以在线自动填写表格,单击按钮,拍摄页面快照以及其他特定任务。这些任务之一是Web提取。虽然您可以将其用于卷筒纸刮擦,但它绝对不是瑞士的卷筒纸刮刀。它有它自己的缺点,这将使您避免在某些用例中使用它。
它最明显的缺点是速度慢。如果您尝试使用Scrapy或Requests和Beautifulsoup的组合,那么您将获得一个速度基准,可以使Selenium的排名降低。这并非与它使用真实的浏览器并必须进行渲染这一事实无关。
因此,开发人员仅在处理具有丰富JavaScript的站点时才使用Selenium,您会发现很难调用基础API。使用Selenium,您要做的就是使过程自动化,所有事件都将被触发。
对于可以快速复制API请求并在加载时下载所有内容的静态站点,您将需要使用更好的选项,即Scrapy或Requests和Beautifulsoup的组合。
- Scrapy、Beautifulsoup 、Selenium用于Web抓取
安装指南
Selenium是第三方库,因此,您需要先安装它,然后才能使用它。在安装Selenium之前,请确保已经安装了Python。要安装Python,您可以访问Python官方下载页面。为了使Selenium正常工作,您将需要安装Selenium软件包,然后安装要自动化的特定浏览器驱动程序。您可以使用pip安装该库。
pip install Selenium
对于浏览器驱动程序,它们支持Chrome,Firefox和许多其他驱动程序。本文的重点是Chrome。如果您的计算机上未安装Chrome,则可以从Google Chrome官方页面上下载。安装了Chrome后,您可以继续并在此处下载Chrome驱动程序二进制文件。
让您下载已安装的Chrome版本的驱动程序。该文件是一个zip文件,其中包含实际的驱动程序。解压缩实际的Chrome驱动程序(chromedriver.exe),并将其与您正在编写的任何Selenium脚本放在同一文件夹中。
Selenium Hello World
正如编码教程的传统一样,我们从经典的hello world程序开始编写本Selenium指南。该代码目前尚未抓取任何数据。它所做的只是尝试登录一个虚构的Twitter帐户。让我们看一下下面的代码。
import time from selenium import webdriver from selenium.webdriver.common.keysimport Keys username = "concanated" password = "djhhfhfhjdghsd" driver = webdriver.Chrome() driver.get("https://twitter.com/login") name_form = driver.find_element_by_name("session[username_or_email]") name_form.send_keys(username) pass_form = driver.find_element_by_name(("session[password]")) pass_form.send_keys(password) pass_form.send_keys((Keys.RETURN)) time.sleep(5) driver.quit()
用户名和密码变量的值是假的。当您运行上述代码时,它将启动Chrome,然后打开Twitter登录页面。用户名和密码将被输入然后发送。
由于用户名和密码不正确,因此会显示错误消息,并在5秒钟后关闭浏览器。从上面可以看到,您需要指定特定的Web浏览器,并且可以看到我们在第7行上做了。get方法发送GET请求。页面成功加载后,我们使用
driver.find_element_by_name
查找用户名和输入元素然后使用的方法
.send_keys
用于用适当的数据填充输入字段。
发送网络请求
使用Selenium发送Web请求是最简单的任务之一。与其他工具不同,Selenium中的POST和GET请求之间存在差异,它们的发送方式相同。所需要做的就是您在将URL作为参数传递的驱动程序上调用get方法。让我们看看下面的操作是如何完成的。
from selenium import webdriver driver = webdriver.Chrome() # visit Twitter homepage driver.get("https://twitter.com/") # page source print(driver.page_source) driver.quit()
运行上面的代码将以自动化模式启动Chrome,并访问Twitter主页并使用来打印页面的HTML源代码。
driver.page_source
您会在地址栏下方看到一条通知,告知您Chrome由自动测试软件控制。
- Playwright、Puppeteer, Selenium:有什么区别?
无头模式的Chrome
综上所述,Chrome启动了–这是一种有效的方法,主要用于调试。如果您准备在服务器或生产环境中启动脚本,则不希望启动Chrome 您希望它在后台运行。这种不启动而运行Chrome浏览器的方法称为无头Chrome模式。以下是在无头模式下运行Selenium Chrome的方法。
from selenium import webdriver from selenium.webdriver.chrome.optionsimport Options # Pay attention to the code below options = Options() options.headless = True driver = webdriver.Chrome(options=options) # visit Twitter homepage driver.get("https://twitter.com/") # page source print(driver.page_source) driver.quit()
运行上面的代码将无法启动Chrome浏览器,您只能看到访问的页面的源代码。此代码与之前的代码唯一的不同是,该代码在无头模式下运行。
- 无头浏览器101:Chrome无头浏览器Firefox版本
- 使用Chrome无头和专用代理抓取任何网站
访问页面上的元素
Web抓取基本上涉及三件事:发送Web请求,解析页面源,然后处理或保存解析的数据。前两个通常是重点,因为它们会带来更多挑战。
您已经学习了如何发送Web请求。现在,让我向您展示如何访问其他元素以解析它们中的数据或执行任务。在上面的代码中,我们使用
page_source
访问页面源的方法。仅当您要使用Beautifulsoup或其他解析库进行解析时,此功能才有用。如果要使用Selenium,则不必使用
page_source
方法:
driver.title
用于检索页面标题
driver.current_url
用于检索视图中页面的URL
driver.find_element_by_name
用于通过元素名称检索元素,例如使用名称password输入密码
driver.find_element_by_tag_name
用于通过标签名称(例如a,div,span,body,h1等)检索元素。
driver.find_element_by_class_name
用于通过类名称检索元素
driver.find_element_by_id
用于通过id查找元素
对于每个
find_element_by ***
方法,有一种对应的方法可检索元素列表,而不是一个元素列表,除了
find_element_by_id
举例来说,如果您想使用“ thin-long”类检索所有元素,则可以使用
driver.find_elements_by_class_name(“thin-long”)
代替
driver.find_element_by_class_name(“thin-long”)
区别在于函数中的多个element关键字
与页面上的元素进行交互
通过以上内容,您可以在页面上找到特定的元素。但是,您不只是为了做这些而已。您将需要与它们进行交互以触发某些事件或从中检索数据。让我们看一下使用Selenium和Python与页面上的元素可以进行的一些交互。
element.text
将检索附加到元素的文本
element.click()
将会触发点击动作和随后的事件
element.send_keys(“test text”)
用于填写输入表格
element.is_displayed()
用于检测元素是否对真实用户可见这非常适合蜜罐检测
element.get_attributes(“ class”)
用于检索元素属性的值。您可以为任何其他属性更改“ class”关键字。
有了以上内容,您就具有开始从网页上抓取数据的条件。我将使用以上内容从Britannica网站上抓取其资本,人口(普查)和估计人口的美国各州的列表。看下面的代码。
from selenium import webdriver from selenium.webdriver.chrome.optionsimport Options # Pay attention to the code below options = Options() options.headless = True driver = webdriver.Chrome(options=options) driver.get("https://www.britannica.com/topic/list-of-state-capitals-in-the-United-States-2119210") list_states = [] trs = driver.find_element_by_tag_name("tbody").find_elements_by_tag_name("tr") for iin trs: tr = i.find_elements_by_tag_name("td") tr_data = [] for x in tr: tr_data.append(x.text) list_states.append(tr_data) print(list_states) driver.quit()
综上所述,我们几乎将上面讨论的所有内容付诸实践。注意trs变量。如果查看页面的源代码,您会发现状态列表和相关信息包含在表中。该表没有类,其主体也没有。
有趣的是,它是唯一的表,因此,我们可以使用find.element_by_tag_name(“ tbody”)方法来检索tbody元素。tbody元素中的每一行代表一个状态及其信息,每个信息都嵌入td元素中。我们调用了find.elements_by_tag_name(“ td”)来检索td元素。
第一个循环用于遍历tr元素。第二个是迭代每个tr元素的td元素。Element.text用于检索附加到元素的文本。
您已经学习了基础知识:现在呢?
综上所述,我们已经向您展示了如何使用Selenium和Python抓取页面。但是,您需要知道所学的只是基础知识。您还需要学习更多。您将需要知道如何执行其他移动和键盘操作。
有时,只需立即用文本字符串填写表单,就会发现流量是由机器人发起的。在这种情况下,您将必须模仿每个人输入的字母来模仿打字。使用Selenium,您甚至可以拍摄页面快照,执行自定义JavaScript并执行许多自动化任务。我建议您在Selenium官方网站上详细了解Selenium Web浏览器。
- 如何在Selenium上设置代理
- 使用Selenium和代理构建Web爬网程序
结论
Selenium在慢速方面有其自身的挫折。但是,事实证明,当您需要从功能丰富的JavaScript网站中抓取数据时,它是最佳选择。
关于Selenium,您会喜欢的一件事是,它使抓取的整个过程变得很容易,因为您不必处理Cookie,也不必进行复制即可复制Web请求。有趣的是,它很容易使用。
- 什么是HTTP标头以及如何检查HTTP标头?
- 代理API,数据中心,用于剪贴的住宅代理
- 如何抓取网站,永不列入黑名单
- Web Scraping API可帮助抓取和提取数据