【问题标题】:Loop to scrape data from Wikipedia in R循环从 R 中的维基百科抓取数据
【发布时间】:2016-10-24 21:27:41
【问题描述】:

我正在尝试提取有关名人/著名死亡事件的数据以进行分析。维基百科的 html 路径结构非常规则,涉及著名的死亡日期。它看起来像:

https://en.wikipedia.org/wiki/Deaths_in_"MONTH"_"YEAR"

例如,此链接导致 2014 年 3 月的重大死亡事件。

https://en.wikipedia.org/wiki/Deaths_in_March_2014

我已经找到了我需要的列表的 CSS 位置“”#mw-content-text h3+ ul li”并成功地将其提取到特定链接。现在我正在尝试编写一个循环来通过我选择的月份和任何年份。我认为这是一个非常简单的嵌套循环,但我在 2015 年测试时遇到了错误。

library(rvest)
data = data.frame()
 mlist = c("January","February","March","April","May","June","July","August",
              "September","October","November","December")

for (y in 2015:2015){
  for (m in 1:12){
    site = read_html(paste("https://en.wikipedia.org/wiki/Deaths_in_",mlist[m],
           "_",y,collapse=""))
    fnames = html_nodes(site,"#mw-content-text h3+ ul li")
    text = html_text(fnames)
    data = rbind(data,text,stringsAsFactors=FALSE)
      }
 }

当我注释掉这一行时:

data = rbind(data,text,stringsAsFactors=FALSE)

没有返回错误,因此它显然与该位有关。我也在为其他 cmets 发布我的整个代码。这里的目标是循环多年,然后专注于多年来和几个月的分布。为此,我只需要保留死亡的年龄、月份和年份。

谢谢!

编辑:对不起,它们是技术上的警告,而不是错误。我得到了超过 50 个,当我尝试查看“数据”时,它是一团糟。

当我在一个特定 URL 上不作为循环运行此代码时,它可以正常工作并返回可读的输出。

site = read_html("https://en.wikipedia.org/wiki/Deaths_in_January_2015")
fnames = html_nodes(site,"#mw-content-text h3+ ul li")
text = html_text(fnames)

以下是该数据集中的几行:

text[1:5]
[1] "Barbara Atkinson, 88, British actress (Z-Cars).[1]"                                         
[2] "Staryl C. Austin, 94, American air force brigadier general.[2]"                             
[3] "Ulrich Beck, 70, German sociologist, heart attack.[3]"                                      
[4] "Fiona Cumming, 77, British television director (Doctor Who).[4]"                            
[5] "Eric Cunningham, 65, Canadian politician, Ontario MPP for Wentworth North (1975–1984).[5]"

【问题讨论】:

  • 我没有收到任何错误消息。你得到了什么错误?输出数据集应该是什么样子?
  • 请张贴您正在使用的软件包的名称,以便人们可以轻松地重现您的错误。
  • 我编辑了帖子以包含使用此模板和我正在使用的库 rvest 成功抓取的示例。

标签: r loops web-scraping rvest


【解决方案1】:

html_text(fnames) 返回一个数组。您的问题是尝试将数组附加到数据帧上。
尝试在附加之前将您的变量 text 转换为数据框:

for (y in 2015:2015){
  for (m in 1:12){
    site = read_html(paste("https://en.wikipedia.org/wiki/Deaths_in_",mlist[m],
           "_",y,collapse=""))
    fnames = html_nodes(site,"#mw-content-text h3+ ul li")
    text = html_text(fnames)

    temp<-data.frame(text, stringsAsFactors = FALSE)

    data = rbind(data,temp)
    }
 } 

出于性能原因,这不是最佳技术。每次通过循环时,都会重新分配数据帧的内存,这会降低性能,这是一次性事件,并且在这种情况下它应该是可管理的限制数量的请求。

【讨论】:

  • 自发布以来,我看到 rbind 由于“文本”的结构而导致问题。我使用了一种可以工作的“as.matrix”转换,但它创建了一个具有 6k 个因子级别的数据框。您的代码解决了这个问题!
【解决方案2】:

我无法得到与您相同的错误,但我想我知道您想要做什么。

我感觉这与每个月的死亡人数不相等有关。

我建议这样做

mlist = c("January","February","March","April","May","June","July","August",
      "September","October","November","December")

for (y in 2015:2015){
  for (m in 1:12){
    site = read_html(paste("https://en.wikipedia.org/wiki/Deaths_in_",mlist[m],
                       "_",y,collapse=""))
    fnames = html_nodes(site,"#mw-content-text h3+ ul li")
    text = html_text(fnames)
    assign(mlist[m],text)
  }
}

这将为每个月的死亡创建一个字符列表。

另一种选择(以便稍后在循环中加入它们)是使用列表:

data = vector("list",12)
mlist = c("January","February","March","April","May","June","July","August",
      "September","October","November","December")

for (y in 2015:2015){
  for (m in 1:12){
    site = read_html(paste("https://en.wikipedia.org/wiki/Deaths_in_",mlist[m],
                       "_",y,collapse=""))
    fnames = html_nodes(site,"#mw-content-text h3+ ul li")
    text = html_text(fnames)
    data[[m]] = text
  }
}

就个人而言,我不喜欢在 R 中处理列表。但这似乎是最好的解决方法。

【讨论】:

  • 有意思,谢谢!我最终希望将 y 更改为循环多年,因此我需要对其进行调整以便能够添加更多行,但这对我来说运行没有错误。
猜你喜欢
  • 1970-01-01
  • 2019-07-20
  • 2019-05-24
  • 1970-01-01
  • 2020-07-20
  • 1970-01-01
  • 2017-04-30
  • 1970-01-01
  • 2016-09-08
相关资源
最近更新 更多