返回博客
指南
拉卢卡·彭丘克2022年10月19日阅读时间:9分钟

用 R 进行网络抓取如何让数据科学变得有趣

用 R 进行网络抓取如何让数据科学变得有趣

R 简介

R 是S 编程语言的开源版本,结合了Scheme 的语义。它于 1993 年中期首次出现,1995 年成为开源语言,2000 年发布了第一个稳定的测试版。

一幅将 R 和 S Scheme 进行对比的漫画梗图,配文表达了困惑

罗斯-伊哈卡(Ross Ihaka)和罗伯特-温特曼(Robert Gentleman)设计 R 的目的是 "快速、忠实地将想法转化为软件"。

R 是一种函数式编程语言,在数据科学家中享有盛誉。它最受欢迎的使用案例包括

  • 银行业务
  • 财政;
  • 电子商务;
  • 机器学习;
  • 任何其他使用大量数据的部门。

与 SAS 和 SPSS 相比,R 是世界上使用最多的分析工具。其活跃的支持性社区拥有近 200 万用户。

如果我们看一看一些将 R 技术融入其业务的公司以及它们是如何做到这一点的,我们就会发现: :

  • Facebook:更新状态及其社交网络图;
  • 谷歌:预测经济活动,提高在线广告效率;
  • Foursquare:因为它的推荐引擎;
  • Trulia:预测房价和当地犯罪率。

然而,与其他语言相比,R 语言与 Python 的竞争并不激烈。这两种语言都提供网络搜索工具,并拥有活跃的社区。

当我们看一下目标受众时,差异就显现出来了。Python 的语法非常容易上手,而且有很多高级功能。这使它对初学者和非技术用户更有吸引力。

R 最初看起来有点吓人,但它更侧重于统计分析。它提供了更多的内置数据分析和数据可视化工具。因此,对于需要处理大量数据的项目(如网络搜索)来说,R 是一个更好的选择。

关于 rvest

Rvest 是 R 语言中最常用的网络搜刮软件包之一,具有强大而简单的解析功能。Python 的 BeautifulSoup 是它的灵感来源,也是tidyverse套件的一部分。

很酷,但既然 R 原生库可以完成同样的工作,为什么还要使用 rvest 呢?第一个很好的理由是,rvest 是httrxml2包的封装器。这意味着它同时处理 GET 请求和 HTML 解析。

这样,您只需使用一个库而非两个库,代码也会更加简洁。不仅如此,rvest 还可以接收字符串作为输入,并处理 XML 解析和文件下载。

然而,我们应该考虑到,网站有更多动态生成的内容。原因多种多样:性能、用户体验等等。Rvest 无法处理 JavaScript 的执行,因此您应该寻找一种替代方案。

使用 R 进行搜索

好了,理论讲得够多了。让我们看看 R 在实际应用中的表现。在本教程中,我选择了一本非常有名的书的 Goodreads 页面:乔治-奥威尔的《1984》。您可以在这里找到该网站:https://www.goodreads.com/book/show/61439040-1984。

我想看看这本书的受欢迎程度在过去几年中是如何演变的。为此,我将抓取评论列表,提取每篇评论的日期和评分。最后一步,我将把数据保存到一个外部文件中,以便以后用其他程序处理。

设置环境

但首先,您必须确保拥有编写代码所需的一切。

CRAN 页面提供了适用于 Linux、macOS 和 Windows 的 R 安装下载链接

关于集成开发环境,您有两个选择:

  • 为 Visual Studio Code 安装R 插件
  • 下载 RStudio,它可让您毫不费力地使用 R 进行编码。

在本教程中,我将使用后者。您可以在这里下载:https://www.rstudio.com/products/rstudio/download/。

RStudio 价格对比表,其中指出 RStudio Desktop 可免费下载

RStudio Desktop 的免费版本足以让你轻松掌握基础知识。和以前一样,请按照安装说明进行操作。

打开 RStudio,新建一个空目录。我将在名为"goodreads-rvest.r "的新文件中编写代码。

呈现浏览器

现在,在提取数据之前,您必须确认您想要什么数据。Rvest 可以处理 CSS 和 XPath 选择器,所以请选择你的战斗机。 

如果您打算开始更复杂的搜索项目,我建议您掌握 HTML 和 CSS 的基本知识。这里有一个很好的入门平台。

如果您不熟悉 HTML,也有一些非技术性的选择。例如,Chrome 浏览器提供了浏览器扩展SelectorGadget。它允许你点击页面上的任意位置,并显示获取数据的 CSS 选择器。

然而,并非每个网站都像 Goodreads 一样简单。我会选择使用通过手动检查 HTML 找到的 CSS 选择器来检索数据。

在浏览器中导航到我们的目标 URL,向下滚动到 "社区评论 "部分。然后右键单击,选择 "检查",打开 "开发工具"。

Goodreads 书籍页面,使用浏览器开发者工具检查社区评论部分

带有 "other_reviews"id 的容器是我要关注的重点。现在,你可以使用 "检查 "按钮找到评论日期和评分的 CSS 选择器。

Goodreads 书评页面,开发者工具已突出显示评论日期和星级评分元素

所以,你可以注意到以下几点:

  • 每个评论都是一个带有 "评论"类的div 容器;
  • 评论的日期是一个单一的元素,带有 "reviewDate"类;
  • 评论的评级是一个带有 "staticStars"类的span 元素。它有五个 span 元素作为子元素,即用户可以设置的星星数量。我们将查看带有 "p10"类的彩色元素。

提取评论

检查完所有前提条件后,您就可以开始编写代码了。

install.packages('rvest')

将光标放在该行末尾,然后按下代码编辑器上方的 "运行 "按钮。你将在控制台中看到软件包的安装进度。

安装只进行一次,因此现在可以注释或删除前一行:

#install.packages('rvest')

现在,您必须加载(或导入)程序库:

library(rvest)

我将使用read_html函数向目标网站发送 GET 请求,下载所需的 HTML 文档。这样我就能下载所需的 HTML 文档了:

book_html <- read_html("https://www.goodreads.com/book/show/61439040-1984")

现在,结果存储在 book_html 变量中,你只需在控制台中输入即可看到:

RStudio 控制台输出显示在加载页面后输出的 HTML 文档对象

如果您需要随时查看要使用的函数的官方文档,请在控制台中键入:

help(function_name) 

RStudio 将打开一个 HTTP 服务器,并直接链接到文档。对于 read_html,输出将是

RStudio 帮助窗格中显示了 read_html 和 read_xml 函数的文档

要获取评论列表,我将使用 html_elements 函数。它将接收我之前找到的 CSS 选择器作为输入:

reviews <- book_html %>% html_elements('div.review')

结果将是一个 XML 节点列表,我将遍历该列表以获取每个单独元素的日期和评级:

RStudio 控制台输出显示从 HTML 文档中抓取的评论节点列表

R 程序员使用管道运算符"%>%"使编码更加灵活。它的作用是将左操作数的值作为参数传递给右操作数。

您可以对操作数进行链式处理(本指南稍后将介绍),因此它可以帮助您减少大量局部变量。如果不使用管道操作符,上一行代码将如下所示:

reviews <- html_elements(book_html, 'div.review')

为了收集数据,我将在循环外初始化两个向量。通过快速浏览网站,我可以保证两个向量的长度相同。

dates <- vector()
ratings <- vector()

现在,在遍历评论列表时,我会查找两个值:日期和评分。如前所述,日期是一个具有reviewDate 类的锚元素。

评级是一个带有staticStars 类的 span 元素,每个星级包含五个 span 元素。如果用户给了一颗星,那么该 span 元素将使用p10 类名,而其余的将使用p0 类名。

代码将如下所示:

for (review in reviews) {
  review_date = review %>% html_element('a.reviewDate') %>% html_text()
  dates <- c(dates, review_date)
 
  review_rating_element = review %>% html_element('span.staticStars')
  valid_stars = review_rating_element %>% html_elements('span.p10')
  review_rating = length(valid_stars)
  ratings <- c(ratings, review_rating)
}

请注意html_element函数,它不是一个错别字。当您想提取 XML 节点列表时,可以使用html_elements,而提取单个节点时,则可以使用html_element

在本例中,我将后者应用于 HTML 文档的一个较小部分(评论)。我还使用了html_text函数来帮助我获取所找到元素的文本内容。 

最后,我将把这两个向量合并到一个数据框中,以集中数据:

result = data.frame(date = dates, rating = ratings)

最终结果将是这样的

R 控制台输出显示的包含评审日期和数值评分的表格

保存结果

我们都知道,如果不将结果存储在某个地方,刮擦就毫无用处。在 R 语言中,将结果写入 CSV 也不过如此:

write.csv(result, "reviews.csv")

结果必须是矩阵或数据帧(已经是矩阵或数据帧),否则会尝试转换。运行代码并检查项目目录。你会发现可以用文本编辑器、Excel 文档等打开前一个表格。

结果必须是矩阵或数据帧(已经是矩阵或数据帧),否则会尝试转换。运行代码并检查项目目录。你会发现可以用文本编辑器、Excel 文档等打开前一个表格。

不用说,我们的数据列表只有 30 个条目。该网站显示有超过 9 万条评论和 300 多万个评分。到底发生了什么?嗯,分页。

不仅如此,请返回浏览器并点击第二页。你会发现列表会改变,但 URL 不会改变。这说明它们使用了一种状态来动态加载列表的另一部分。

在这种情况下,rvest 可能无济于事。相反,自动浏览器可以帮助模仿点击行为来加载列表的其余部分。RSelenium 就是这种库的一个例子,但我将把这个主题留作后续练习。

结论

我希望本教程能为你使用 R 进行网络搜索打下坚实的基础。现在,你可以更轻松地决定下一个项目的技术栈了。

但请注意,本文并未涵盖网络搜索的诸多挑战。你可以在这本不言自明的指南中找到更详细的概念。

关于作者
Raluca Penciuc,WebScrapingAPI 全栈开发工程师
Raluca Penciuc全栈开发工程师

Raluca Penciuc 是 WebScrapingAPI 的全栈开发工程师,主要负责开发爬虫、优化规避机制,并探索可靠的方法以降低在目标网站上的被检测概率。

开始构建

准备好扩展您的数据收集规模了吗?

加入2,000多家企业,使用WebScrapingAPI在无需任何基础设施开销的情况下,以企业级规模提取网页数据。