【问题标题】:Scraping a table from a section in Wikipedia从 Wikipedia 的部分中抓取表格
【发布时间】:2016-08-01 00:07:54
【问题描述】:

我正在尝试想出一个可靠的方法来统计每个赛季 NFL 球队的最终排名;奇妙的是,a Wikipedia page 包含指向所有这些信息的链接。

不幸的是,最终排名表的存储方式/存储位置存在很多不一致(可能是意料之中,考虑到联赛结构的演变)。

可取之处应该是相关表格始终位于带有“Standings”一词的部分中。

有什么方法可以grep 一个部分名称,只提取table 那里的节点?

这里有一些示例页面来演示结构:

  • 1922 season - 只有一个部门,一个表;表格位于标题“Standings”下,具有 xpath //*[@id="mw-content-text"]/table[2] 和 CSS 选择器 #mw-content-text > table.wikitable

  • 1950 season - 两个部门,两个表;两者都在标题“最终排名”下找到。第一个有 xpath //*[@id="mw-content-text"]/div[2]/table / CSS #mw-content-text > div:nth-child(20) > table,第二个有 xpath //*[@id="mw-content-text"]/div[3]/table 和选择器#mw-content-text > div:nth-child(21) > table

  • 2000 season - 两个会议,6个部门,两个表;两者都在标题“常规赛季最终排名”下找到。第一个有 xpath //*[@id="mw-content-text"]/div[2]/table 和选择器#mw-content-text > div:nth-child(16) > table,第二个有 xpath //*[@id="mw-content-text"]/div[3]/table 和选择器#mw-content-text > div:nth-child(17) > table

总结:

# season |                                   xpath |                                          css
-------------------------------------------------------------------------------------------------
#   1922 |     //*[@id="mw-content-text"]/table[2] |           #mw-content-text > table.wikitable
#   1950 | //*[@id="mw-content-text"]/div[2]/table | #mw-content-text > div:nth-child(20) > table
#        | //*[@id="mw-content-text"]/div[3]/table | #mw-content-text > div:nth-child(21) > table
#   2000 | //*[@id="mw-content-text"]/div[2]/table | #mw-content-text > div:nth-child(16) > table
#        | //*[@id="mw-content-text"]/div[3]/table | #mw-content-text > div:nth-child(17) > table

刮擦,例如 1922 年很容易:

output <- read_html("https://en.wikipedia.org/wiki/1922_NFL_season") %>%
  html_node(xpath = '//*[@id="mw-content-text"]/table[2]') %>% whatever_else(...)

但我没有看到任何可以在 xpath 或 CSS 选择器中使用的模式来概括这一点,因此我不必进行 80 次单独的抓取练习。

是否有任何可靠的方法来尝试抓取所有这些表,特别是考虑到所有表都位于一个标题下方的关键洞察力,该标题将从grepl("standing", tolower(section_title)) 返回TRUE

【问题讨论】:

  • 如何使用tbls &lt;- read_html("https://en.wikipedia.org/wiki/1922_NFL_season") %&gt;% html_table(fill = T) 抓取页面上的所有表格,然后通过连续包含一个/部分/全部c("W", "L", "PCT", "PF", "PA") 的表格向下选择?
  • 不错,但不一定完美:'html_nodes(xpath = '(//abbr[@title="Winning percentage"]|//th[text()="PCT"])/ancestor::table')
  • @alistaire 哦,哇,我不知道 xpath 可以执行这样的技巧。你能推荐任何参考来学习基础知识吗?
  • 我一直在使用 W3Schools; Syntax 页面是一个很好的基线,AxesXSLT/XPath Functions 页面很有用。
  • ...您可以将其与/preceding::span[contains(@id,"tandings")] 匹配,但我不确定如何将其有效地融入逻辑。

标签: r xpath css-selectors rvest


【解决方案1】:

您可以通过使用 lapply 循环 URL 并使用精心挑选的 XPath 选择器拉出表格来一次抓取所有内容:

library(rvest)

lapply(paste0('https://en.wikipedia.org/wiki/', 1920:2015, '_NFL_season'), 
       function(url){ 
           url %>% read_html() %>% 
               html_nodes(xpath = '//span[contains(@id, "tandings")]/following::*[@title="Winning percentage" or text()="PCT"]/ancestor::table') %>% 
               html_table(fill = TRUE)
       })

XPath 选择器查找

  • //span[contains(@id, "tandings")]
    • 所有带有idtandingsspans(例如“排名”、“最终排名”)
  • /following::*[@title="Winning percentage" or text()="PCT"]
    • 在 HTML 中后面有一个节点
      • “获胜百分比”的title 属性
      • 或含有“PCT”
  • /ancestor::table
    • 并从该节点的树上选择table 节点。

【讨论】:

  • 谢谢!特别是让我意识到,如果我要更频繁地进行抓取,那么学习 xpath 语法绝对是值得的。强大的东西。
  • 还要注意这不是 完美 完美的,因为例如在 2015 年,它也会拉动conference table,但我认为这并不重要有了这个,这肯定回答了我提出的问题。
  • 是的。您可以在 XPath 中编写一些分割,或者稍后将它们删除。另外,我意识到 paste0 错过了 AFL 页面,如果你想要的话。
  • 我没有,我之前是grepping "NFL",再次感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-26
  • 1970-01-01
  • 1970-01-01
  • 2015-11-27
  • 2019-04-20
  • 1970-01-01
  • 2020-04-19
相关资源
最近更新 更多