返回博客

R 语言爬虫(使用 rvest 包)教程

Augustas Pelakauskas

2022-10-28

随着数字业务环境的快速发展,网络抓取的力量变得愈发不容忽视。通过网络抓取提取公共数据进行分析,以生成见解,从而改变和提升业务前景。

如果需要学习一门新的编程语言才能开始使用网络抓取,这可能令人望而却步。值得庆幸的是,越来越多的编程语言都有强大的库来帮助更方便地进行网页数据抓取。

数据和统计分析中最常用的编程语言之一是 R。它是一种开源编程语言,有许多开源库,大量用户都在用它来进行网络抓取。

尽管如此,R 语言对初学者来说还是很有挑战性,尤其是与 Python 等其他使用更为广泛的语言相比。重要的是要记住,R 主要是用于统计和数据分析,而 Python 则更为通用。如果您会 R 语言,那么从网页中抓取数据相对简单。可将网页转换为数据框或 CSV 文件以供进一步分析。

本教程将介绍 R 语言爬虫代码的基础知识。我们首先讲述如何抓取静态页面,然后重点讲述可用于从使用 JavaScript 呈现内容的动态网站中抓取数据的技术。了解如何构建R语言网络爬虫,rvest 爬虫。

安装要求

所需安装的组件分为两个部分:安装 R 和 RStudio,以及安装库。

安装 R 和 RStudio

第一阶段是准备 R 语言的开发环境。这将需要两个组件:R 和 RStudio。

  • 下载和安装 R,请访问此页面。点选安装 base 就可以了。

或者,您可以使用包管理器,例如针对 Mac 的 Homebrew,或针对 Windows 的 Chocolatey。

如果是 macOS,运行以下:

brew install r

如果是 Windows,则运行以下:

choco install r.project
  • 接下来是下载和安装 RStudio,前往此页面。选择 RStudio Desktop 免费版本就可以。

如果您更喜欢包管理器,请使用以下命令,用于 macOS 的 Homebrew 和用于 Windows 的 Chocolatey:

如果是 macOS,运行以下代码:

brew install --cask r-studio

如果是 Windows,则运行以下代码:

choco install r.studio

完成安装后,打开 RStudio。

打开 RStudio

安装所需的库

可以通过两种方法安装所需的库。  首先可以通过 RStudio 的用户界面。在 Help(帮助)部分中找到 Package(包)选项卡。选择 Packages(包)选项卡以激活相关的数据包部分。在这个部分中,点击 Install(安装)按钮。

此时就会打开 Install Package(安装包)对话框。在包的文本框中输入包的名称。最后,点击 Install(安装)

对于本教程的第一部分,我们将使用的包是 rvest。我们还需要 dplyr 包,以便使用管道操作符。这样做会使代码简洁易读。

分别输入这两个包名称,用逗号分隔,然后单击 Install(安装)

安装库

另一种方式是通过控制台安装这些包。在控制台中运行以下命令:

install.packages("rvest")
install.packages("dplyr")

现在库已安装好。下一步开始抓取数据。

用 rvest 进行网页抓取(rvest 爬虫)

R 语言中最常用于公共网页抓取的库就是 rvest。它提供了通过 CSS 选择器和 XPath 访问公共网页和查询特定元素的功能。这个库是 Tidyverse 数据科学软件包集合的组成部分,这就是说 Tidyverse 的所有库中的编码约定都是相同的。

我们使用 rvest 启动网页抓取操作。第一步是向目标网页发送 HTTP GET 请求。我们将尝试各种 rvest 示例。

本节以 rvest 备忘单的形式编写,方便您可以跳转到需要帮助学习的任何部分。

发送 GET 请求

在 Source 区域中输入以下内容开始加载 rvest 库:

library(rvest)

只需将光标放在所需的行,选择它,然后单击源区域右上方的 “Run” 按钮,即可执行在源区域中输入的所有命令。

或者,根据您的操作系统,您可以按组合键 Ctrl + Enter 或 Command + Enter。

在这个示例中,我们将从列出 ISO CountryCodes 的网页中抓取公开可用的数据。超链接可以存储在变量中:

link = "https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes"

可以使用简单函数 read_html() 向该页面发送 HTTP GET 请求。

此函数需要一个强制参数:路径或 URL。请注意,此函数还可以读取 HTML 字符串:

page = read_html(link)

以上函数向 URL 发送 HTTP GET 请求,检索网页,并返回一个 html_document 类型的对象。

html_document 对象包含来自 HTML 文档的所需公共数据。许多 rvest 函数都可用于查询和提取特定的 HTML 元素。

请注意,如果需要使用 rvest 代理,请运行以下命令在脚本中设置代理:

Sys.setenv(http_proxy="http://proxyserver:port")

rvest read_html timeout

read_html 不提供 timeout 的控制方法。可以通过 httr 库来处理rvest read_html timeout。此库中的 GET 函数和 tryCatch 可以帮助处理 timeout 错误。

或者,您可以使用 rvest 中的会话对象,如下所示:

url <- "https://quotes.toscrape.com/api/quotes?page=1"
page<-read_html(GET(url, timeout(10))) # Method 1
page <- session(url,timeout(10)) #Method 2

解析 HTML 内容

rvest 包提供了使用 CSS 选择器和 XPath 选择 HTML 元素的便捷方式。

通过 html_elements() 函数选择元素,此函数语法如下:

page %>% html_elements(css="")
page %>% html_elements(xpath="")

需要注意的一个重要方面是复数变体,它将返回匹配元素的列表。这个函数有一个特别变体,它只返回第一个匹配的 HTML 元素:

page %>% html_element()

如果未指定选择器类型,系统会假定它是 CSS 选择器。例如,此 Wiki 网页在表中包含所需的公共数据。

表单的 HTML 标记

此表格的 HTML 标记如下:

<table class="wikitable sortable jquery-tablesorter">

创建唯一选择器所需的类就是 sortable 类。这就意味着 CSS 选择器可以和 table.sortable 一样简单。使用此选择器,函数调用将如下所示:

htmlElement <- page %>% html_element("table.sortable")

它将生成的 html_element 存储在变量 htmlElement 中。

我们的网页抓取项目的下一步,就是将 html_element 中包含的公共数据转化为数据框。

使用 rvest 获取 HTML 元素属性

在上一节中,我们讨论了使用 html_element 函数选择元素。

通过这个函数可以轻松使用 rvest select class。例如,如果要选择具有类标题的元素,只需编写以下代码行:

heading <- page %>% html_element(".heading")

还有一个用例就是 rvest div class。如果您要用 rvest 来选择 div,那么您可以输入以下代码:

page %>% html_element(“div")

如果您用 rvest 来选择带有类的 div

page %>% html_element(“div.heading”)

您可能遇到选择 HTML 节点是 html_node() 的函数。请注意,这种在 rvest 中选择 HTML 节点的方式现在已过时;而应该使用 html_element()html_elements()

从这个函数,您可以通过调用函数 html_text() 提取文本,代码如下:

heading %>% html_text()

或者,如果要查找属性,可以使用 rvest html_attr 函数。例如,以下代码可以提取元素的 src 属性:

element %>% html_attr(“src")

在处理 HTML 表格时,可以使用 rvest 读取表格函数。此函数可以提取包含 <table> 元素的 HTML 并返回数据框。

html_table(htmlElement)

可以这样构建 rvest 提取表格代码:

page %>% html_table()

正如您所看到的,我们可以发送整个页面和 rvest 读取表格,所有这些数据。

使用 rvest 抓取 JavaScript 页面

如果要抓取使用 JavaScript 的页面,可以通过两种方式进行。第一种方式是使用 RSelenium。我们将在本文的下一节详细介绍这种方法。

在本节中,我们讨论第二种方法。这种方法可以查找包含相关数据的隐藏 API。

https://quotes.toscrape.com/scroll 就是个很好的示例,让我们来了解如何处理 rvest JavaScript。这个网站使用无限滚动。

在 Chrome 浏览器中打开网站,按 F12,然后前往网络选项卡。有了网络信息,我们就可以通过 rvest 轻松实现无限滚动。

向下滚动以加载更多内容并查看网络流量。您会注意到,每次加载一组新引号时,都会发送请求调用 URL https://quotes.toscrape.com/api/quotes?page=2,其中页码不断增加。

还有一点值得注意,响应是以 JSON 格式返回的。有一种构建 rvest JSON 解析器的简单方法。

首先读取页面,然后定位 <p> 标签。这类标签中包含文本格式的 JSON 数据。

page <- read_html("https://quotes.toscrape.com/api/quotes?page=1") 
json_as_text <- page %>% html_element("p")  %>% html_text()

要将这个 JSON 文本解析为 R 对象,需要使用另一个库 - jsonlite:

library(jsonlite)

现在,使用 fromJSON 方法将此 rvest JSON 文本转换为原生 R 对象。

r_object <- json_as_text %>% fromJSON()

您可以用循环来解析有无限滚动页面的 rvest javascript。在以下示例中,我们将运行此循环十次:

for (x in 1:10) {
  url <- paste("https://quotes.toscrape.com/api/quotes?page=",x, sep = '')
  page <- read_html(url)
  # parse page to get JSON
}

您可以根据自己的具体要求修改以上代码。

将数据保存到数据框

数据框是 R 语言的基本数据存储结构。它们类似于矩阵,但有一些关键区别。数据框是紧密耦合的变量集合,其中每一列都可以是不同的数据类型。这是存储大量数据的一种强大而有效的方法。

大多数数据和统计分析方法都需要将数据存储在数据框中。

要转换存储在 html_element 中的数据,可以使用函数 html_table

df <- html_table(htmlEl, header = FALSE)

变量 df 是数据框。

请注意使用可选参数 header = FALSE。只有特定场景下才需要使用这个参数。大多数情况下,使用默认值 TRUE 就可以。

对 Wiki 表格,标题会产生两行。这两行中的第一行可以丢弃,使其成为一个三步过程。

  1. 第一步是禁用标题的自动分配,我们已经禁用。

  2. 下一步是设置第二行的列名:

names(df) <- df[2,]
  1. 第三步删除数据框正文的前两行。

df = df[-1:-2,]

这个数据框现在可以用于进一步分析了。

将数据框导出到 CSV 文件

最后,从 HTML 文档中提取数据的最后一步是将数据框保存到 CSV 文件中。

要导出数据框,可以使用 write.csv 函数。这个函数有两个参数:数据框实例和 CSV 文件的名称:

write.csv(df, "iso_codes.csv")

这个函数会将数据框导出到当前目录中的 iso_codes.csv 文件。

如何使用 rvest 下载图像

使用 rvest 可以轻松下载图像。过程分三步:

  1. 下载页面;

  2. 找到包含所需图片的 URL 的元素,然后提取图片的 URL;

  3. 下载图像。 

我们首先导入数据包。

library(rvest)
library(dplyr)

在此示例中,我们将从维基百科页面下载第一张图片。使用 read_htmlI() 函数下载页面并找到包含所需图像的 <img> 标记。

url = "https://en.wikipedia.org/wiki/Eiffel_Tower"
page <- read_html(url)

可以使用 CSS 选择器 “.thumbborder” 来定位图像。

image_element <- page %>% html_element(.thumbborder")

下一步是获取图像的有效 URL,此 URL 嵌入在 src 属性中。在这里使用 rvest 函数 html_attr() 很方便。

image_url <- image_element %>% html_attr(“src")

这个 URL 是相对 URL。现在我们来将它转化为绝对 URL。使用一个 rvest 函数 url_absolute() 可以轻松处理,代码如下:

image_url <- url_absolute(image_url, url)

最后,使用另一个 rvest 函数 download() 来下载文件,代码如下:

download.file(image_url, destfile = basename("paris.jpg"))

网页抓取:rvest 还是 BeautifulSoup?

最常用的公共数据分析语言是 Python 和 R。要分析数据,首先我们需要收集公开可用的数据。收集公共数据最常用的技术是网络抓取。Python 和 R 是适用于网页抓取的语言,尤其是在需要对数据进行分析时,它们非常有用。

在本节中,我们将简单了解 rvest 与 beautifulsoup。

Python 中的 BeautifulSoup 库是最常用的网页抓取库之一,因为它为更复杂的库(如 lxml)提供了易于使用的包装器。Rvest 的灵感来自 BeautifulSoup。它也是更复杂的 R 库(如 xml2 和 httr)的包装器。

Rvest 和 BeautifulSoup 都可以通过 CSS 选择器查询 DOM 文档。 

Rvest 还具有其他功能,可以使用 BeautifulSoup 所缺乏的 XPath。但 BeautifulSoup 也可以使用自己的函数来弥补 XPath 的不足。注意,XPath 允许向上遍历到父节点,而 CSS 无法这样做。

BeautifulSoup 只是一个解析器。它有助于在页面上搜索元素但无法下载网页。为此您需要使用另一个库,例如 Requests。

另一方面,rvest 可以获取网页。

最终,使用 rvest 还是 BeautifulSoup,这取决于用户对编程语言的熟悉程度。如果掌握了 Python,可以选择 BeautifulSoup。如果懂 R,可以选择 rvest。

用 RSelenium 进行网页抓取

尽管 rvest 库适用于大多数静态网站,但有些动态网站使用 JavaScript 来呈现内容。对于这类网站,可以使用基于浏览器的渲染解决方案。

Selenium 是一种常用的基于浏览器的渲染解决方案,可以与 R 一起使用。Selenium 具有各种强大功能,包括截屏、向下滚动页面、单击特定链接或部分页面,以及将通过敲击键盘在页面的任何部分进行输入。Selenium 与常规网络抓取技术结合使用时,是最通用的。

RSelenium 库能够进行动态页面抓取。我们可以通过本文第一部分所述的 RStudio 用户界面安装 RSelenium,也可以通过以下命令安装它:

install.package("RSelenium")

安装数据包后,通过以下命令加载 RSelenium 库:

library(RSelenium)

下一步是启动 Selenium 服务器和浏览器。

启动 Selenium

启动 Selenium 服务器并获取客户端驱动程序实例的方法有两种。

第一种只用 RSelenium,而第二种方法通过 Docker 启动服务器,然后通过 RSelenium 连接服务器。我们来详细了解第一种方法。

通过 RSelenium 可以使用以下函数调用设置 Selenium 服务器和浏览器:

rD <- rsDriver(browser="chrome", port=9515L, verbose=FALSE)
remDr <- rD[["client"]]

这时会下载所需的二进制文件,启动服务器,并返回 Selenium 驱动程序的实例。

或者,可以通过 Docker 运行 Selenium 服务器并连接到此实例。

安装 Docker 并在终端上运行以下命令。

docker run -d -p 4445:4444 selenium/standalone-firefox

这时会下载最新的 Firefox 映像并启动容器。除了 Firefox,也可以使用 Chrome 和 PhantomJS。

服务器启动后,在 RStudio 中输入以下内容以连接到服务器并获取驱动程序的实例:

remDr <- remoteDriver(
  remoteServerAddr = "localhost",
  port = 4445L,
  browserName = "firefox"
)
remDr$open()

这些命令将连接到在 Docker 容器中运行的 Firefox,并返回远程驱动程序的实例。如果出现问题,请检查 Docker 日志和 RSelenium 错误消息。

使用 Selenium 中的元素

注意,在访问网站之后,可能需要等待相当长的时间,才能够使用解析功能。有可能数据还没有加载,整个解析算法就会崩溃。可以使用特定函数来等待特定 HTML 元素完全加载。

第一步是将浏览器导航到所需的页面。例如,我们将抓取科幻小说类型中的所有书籍的名称、价格和库存情况。这个目标网站是一个练习网页抓取的虚拟书店。

要访问这个 URL,可以使用 navigate 函数:

remDr$navigate("https://books.toscrape.com/catalogue/category/books/science-fiction_16")

要找到 HTML 元素,可以使用 findElements() 函数。这个函数很灵活,可以使用 CSS 选择器、XPath,甚至可以使用特定的属性,例如 id、名称、名称标签等。详细列表请查看官方文档

在本例中,我们将使用 XPath。

书名隐藏在缩略图的 alt属性中。

定位书名

这些图像标签的 XPath 将是 //article//img。以下这行代码可以提取所有这些元素:

titleElements <- remDr$findElements(using = "xpath", "//article//img")

要提取 alt 属性值,我们可以使用 getElementAttribute() 函数。但是,在这种特殊情况下,我们要处理一个元素列表。

要从列表的所有元素中提取属性,可以通过 R 的 sapply 函数使用自定义函数:

titles <- sapply(titleElements, function(x){x$getElementAttribute("alt")[[1]]})

请注意,此函数会将属性值作为列表返回。这就是我们要使用 [[1]] 仅提取第一个值的原因。

继续提取价格数据,以下是包含价格的 HTML 元素的 HTML 标记:

<p class="price_color">£37.59</p>

选择它的 XPath 将是 //*[@class='price_color']。而且,这次我们将使用 getElementText() 函数从 HTML 元素中提取文本。方法如下:

pricesElements <- remDr$findElements(using = "xpath", "//*[@class='price_color']")
prices <-  sapply(pricesElements, function(x){x$getElementText()[[1]]})

最后,提取库存情况的代码如下:

stockElements <- remDr$findElements(using = "xpath", "//*[@class='instock availability']")
stocks <-  sapply(stockElements, function(x){x$getElementText()[[1]]})

创建数据框

此时,有三个变量。每个变量都是一个包含所需数据点的列表。

数据点可用于创建数据框:

df <- data.frame(titles, prices, stocks)

创建数据框后,可用它来进一步分析。

此外,只需以下这行代码即可轻松将数据框导出为 CSV:

write.csv(df, "books.csv")

您可以点击这里找到这篇教程中用过的完整代码。

总结

如果您已经掌握 R 的复杂特性或一般的编程,那么使用 R 进行网页抓取相对来说简单直接。对于大多数静态网页,rvest 库提供了足够的功能,不至于太难。但如果有任何类型的动态元素,那么使用通常的 HTML 提取方法难以完成提取任务。如果是这样,通常情况下,可用 RSelenium 来解决复杂负载。

如果想进一步了解如何使用其他编程语言进行抓取,请阅读我们的以下贴文,例如 使用 C# 进行网页抓取, Python 网络爬虫教程使用 lxml 处理 XML 和 Web 抓取使用机器学习进行网络抓取等等。

关于作者

Augustas Pelakauskas

文案

Augustas Pelakauskas 在 Oxylabs 担任一名文案策划人。拥有艺术家庭背景,他全身心地投入到各种创意项目中 - 最近的他都在写作。验证了他在自由新闻领域的能力后,他转到了科技内容创作。闲暇时,他喜欢阳光明媚的户外活动和运动康乐。事实证明,自行车则是他的第三个好朋友。

Oxylabs博客上的所有信息均按“原样”提供,仅供参考。对于您使用Oxylabs博客中包含的任何信息或其中可能链接的任何第三方网站中包含的任何信息,我们不作任何陈述,亦不承担任何责任。在从事任何类型的抓取活动之前,请咨询您的法律顾问,并仔细阅读特定网站的服务条款或取得抓取许可。

在这篇文章


  • 安装要求

  • 用 rvest 进行网页抓取(rvest 爬虫)

  • 用 RSelenium 进行网页抓取

  • 总结

选择Oxylabs®,业务更上一层楼


隐私政策

oxylabs.cn© 2022 保留所有权利©