【问题标题】:rvest: html_table() only picks up header row. Table has 0 rowsrvest: html_table() 只获取标题行。表有 0 行
【发布时间】:2017-11-30 18:21:38
【问题描述】:

我正在学习如何使用rvest 进行网络抓取,但遇到了一些问题。具体来说,代码只是拾取标题行。

library(rvest)
library(XML)

URL1 <- "https://swishanalytics.com/optimus/nba/daily-fantasy-salary-changes?date=2017-11-25"
df <- URL1 %>% read_html() %>% html_node("#stat-table") %>% html_table()

调用 df 会生成一个包含 7 列和 0 行的 data.frame。我安装了检查器小工具,即使这告诉我id = #stat-table 是正确的。这个网站有什么独特之处是它不想拾取表格数据?

作为一个单独的问题,如果我“查看页面源代码”,我可以看到页面上的所有数据,并且我不必使用RSelenium 来翻阅 DK、FD 或 yahoo 工资。看起来有些键很容易找到(例如,查找“FD”> 查找所有“玩家名称:”并在之后拾取字符等),但我不知道处理该页面的库/进程来源。有这方面的资源吗?

谢谢。

【问题讨论】:

  • 这是由于该网站在该页面上嵌入了 javascript 中的数据并在页面加载后呈现它。
  • @hrbrmstr 啊我明白了。那么对于我的最后一段,是否有允许您从页面源中提取并解析的包或方法?因为看起来所有的数据都在幕后。我记得不久前使用 Python/beautiful-soup 从页面源中提取,但我更喜欢使用 R。

标签: r rvest


【解决方案1】:

理论上,您可以从&lt;script&gt; 标记中提取数据,然后使用V8 处理它,但使用splashrseleniumPipes 也很容易做到这一点。我写了splashr,所以我会证明:

library(splashr)
library(rvest)

start_splash()

pg <- render_html(url="https://swishanalytics.com/optimus/nba/daily-fantasy-salary-changes?date=2017-11-25")

html_node(pg, "table#stat-table") %>% 
  html_table() %>% 
  tibble::as_tibble() 
## # A tibble: 256 x 7
##    Position          Player Salary         Change `Proj Fantasy Pts` `Avg Fantasy Pts`   Diff
##       <chr>           <chr>  <chr>          <chr>              <dbl>             <chr>  <chr>
##  1       PF      Thon Maker $3,900  +$600 (18.2%)              12.88             13.24  -0.36
##  2       PG DeAndre Liggins $3,500  +$500 (16.7%)               9.68              7.80  +1.88
##  3       PG   Elfrid Payton $6,400  +$700 (12.3%)              32.77             28.63  +4.14
##  4        C   Jahlil Okafor $3,000 -$400 (-11.8%)               1.71             12.63 -10.92
##  5       PF    John Collins $5,200   +$400 (8.3%)              29.65             24.03  +5.63
##  6       SG     Buddy Hield $4,600  -$400 (-8.0%)              17.96             21.84  -3.88
##  7       SF    Aaron Gordon $7,000   +$500 (7.7%)              32.49             36.91  -4.42
##  8       PG    Kemba Walker $7,600  -$600 (-7.3%)              36.27             38.29  -2.02
##  9       PG    Lou Williams $6,600  -$500 (-7.0%)              34.28             30.09  +4.19
## 10       PG       Raul Neto $3,200   +$200 (6.7%)               6.81             10.57  -3.76
## # ... with 246 more rows

killall_splash()

BeautifulSoup 也不会读取此数据。好吧,你可以定位 &lt;script&gt; 以 JS 形式包含它的标签,并在 Python 上使用类似的 V8 引擎,但它不会比 rvest 更容易做到这一点。

对^^的进一步扩展:

大多数抓取指南告诉您执行“检查元素”以最终找到要定位的 XPath 或 CSS 选择器。检查该表的随机行显示:

对于“普通”网站,这通常有效。

带有 JS 渲染的 XHR 请求(或页面上的 JS+数据)的站点看起来像 ^^ 但您的定位不起作用 b/c read_html()(以及 BeautifulSoup 等效项)无法在页面上呈现 JavaScript没有一些渲染引擎的帮助。您可以尝试通过查看源代码和元素检查来判断这是否正在发生。这是该站点的查看源代码,裁剪为非常长的数据行 + JS + HTML,最终形成表格:

我已经发布了许多关于如何定位&lt;script&gt; 标签和使用V8 的答案。使用 splashrdecapitated 会更容易(如果它们已安装并正常工作)。

如果您不想使用 Docker 并使用最新版本的 Chrome,您也可以按照指导 here 进行无头工作并执行以下操作:

res <- system2("chrome", c("--headless", "--dump-dom", "https://swishanalytics.com/optimus/nba/daily-fantasy-salary-changes?date=2017-11-25"), stdout=TRUE)

res 然后变成纯 HTML,您可以使用 rvest 阅读并刮掉。

一个正在开发的包——decapitated——让^^不那么难看:

install_github("hrbrmstr/decapitated")
library(decapitated)
library(rvest)

chrome_version()
## Google Chrome 63.0.3239.59 beta

pg <- chrome_read_html("https://swishanalytics.com/optimus/nba/daily-fantasy-salary-changes?date=2017-11-25")

html_node(pg, "table#stat-table") %>% 
  html_table() %>% 
  tibble::as_tibble() 
## # A tibble: 256 x 7
##    Position          Player Salary         Change `Proj Fantasy Pts` `Avg Fantasy Pts`   Diff
##       <chr>           <chr>  <chr>          <chr>              <dbl>             <chr>  <chr>
##  1       PF      Thon Maker $3,900  +$600 (18.2%)              12.88             13.24  -0.36
##  2       PG DeAndre Liggins $3,500  +$500 (16.7%)               9.68              7.80  +1.88
##  3       PG   Elfrid Payton $6,400  +$700 (12.3%)              32.77             28.63  +4.14
##  4        C   Jahlil Okafor $3,000 -$400 (-11.8%)               1.71             12.63 -10.92
##  5       PF    John Collins $5,200   +$400 (8.3%)              29.65             24.03  +5.63
##  6       SG     Buddy Hield $4,600  -$400 (-8.0%)              17.96             21.84  -3.88
##  7       SF    Aaron Gordon $7,000   +$500 (7.7%)              32.49             36.91  -4.42
##  8       PG    Kemba Walker $7,600  -$600 (-7.3%)              36.27             38.29  -2.02
##  9       PG    Lou Williams $6,600  -$500 (-7.0%)              34.28             30.09  +4.19
## 10       PG       Raul Neto $3,200   +$200 (6.7%)               6.81             10.57  -3.76
## # ... with 246 more rows

注意:由于新权限和沙盒,Headless Chrome 在 High Sierra 上存在问题。它适用于较旧的 macOS 系统和 Windows/Linux。您只需要正确的版本和正确的环境变量集。

【讨论】:

  • 哇,这太棒了,谢谢!在高层次上,这就是我理解我的问题的方式:没有 SplashR,我的代码正在调用一个使用 JS 表的网站,并且它试图在 JS 加载之前进行抓取。使用 SplashR,它会等待表加载吗?此外,当页面加载时,它目前默认为 DraftKings 工资——有没有办法在 SplashR 中“点击”FanDuel?我以前成功使用过 Rselenium,但是很痛苦……
  • 更新了一些解释。 Chrome 路径 + dev decapitated pkg 是最简单的路径。 splashr 需要一个 Splash docker 映像,该映像需要 Docker,因此它像 Selenium 一样是重量级的。有些在线 API 服务(例如 ScrapingHub)的免费增值使用量有限。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-25
  • 1970-01-01
  • 2017-06-26
  • 1970-01-01
  • 2017-07-20
  • 2017-08-16
  • 2020-04-29
相关资源
最近更新 更多