使用 rvest 或 RSelenium 抓取 Table

Using rvest or RSelenium to Scrape Table

目标: 使用 R 从以下网站抓取 table。

网址: https://evanalytics.com/mlb/models/teams/advanced

我卡住了什么: 我使用 rvest 来自动化我的大部分数据收集过程,但这个特定站点似乎超出了 rvest 的工作范围(或者至少超出了我的经验水平)。不幸的是,它不会在页面打开时立即加载 table。我试图通过 RSelenium 提出一个解决方案,但未能找到 table 的正确路径(RSelenium 对我来说是全新的)。导航到页面并暂停一小段时间以允许 table 加载后,下一步是什么?

我目前有:

library("rvest")
library("RSelenium")

url <- "https://evanalytics.com/mlb/models/teams/advanced"

remDr <- remoteDriver(remoteServerAddr="192.168.99.100", port=4445L)
remDr$open()
remDr$navigate(url)
Sys.sleep(10)

任何帮助或指导将不胜感激。谢谢!

时间紧迫,所以只是指向 html 源代码,您可以从中提取 table with r vest。

  remDr$navigate(url)
  html <-remDr$getPageSource()
## this will get you html of the page, form here 
## just extract the table as you would with rvest

您可以在没有 Selenium 的情况下通过创建一个 html_session 来执行此操作,以便获取所需的 php session id 来传递 cookie。您还需要 user-agent header。在 session 到位后,您可以发出 POST xhr 请求以获取所有数据。您需要一个 json 解析器来处理响应 html.

中的 json 内容

您可以在其中一个脚本标签中看到参数信息:

function executeEnteredQuery() {
    var parameterArray = {
        mode: 'runTime',
        dataTable_id: 77
    };
    $.post('/admin/model/datatableQuery.php', {
            parameter: window.btoa(jQuery.param(parameterArray))
        },
        function(res) {
            processdataTableQueryResults(res);
        }, "json");
}

您可以自己为参数编码字符串:

base64_enc('mode=runTime&dataTable_id=77')

R:

require(httr)
require(rvest)
require(magrittr)
require(jsonlite)

headers = c('User-Agent' = 'Mozilla/5.0')
body = list('parameter' = 'bW9kZT1ydW5UaW1lJmRhdGFUYWJsZV9pZD03Nw==') # base64 encoded params for mode=runTime&dataTable_id=77
session <- html_session('https://evanalytics.com/mlb/models/teams/advanced', httr::add_headers(.headers=headers))

p <- session %>% rvest:::request_POST('https://evanalytics.com/admin/model/datatableQuery.php', body = body)%>%
  read_html() %>%
  html_node('p') %>% 
  html_text()

data <- jsonlite::fromJSON(p)
df <- data$dataRows$columns
print(df)

Py:

import requests
import pandas as pd
from bs4 import BeautifulSoup as bs

body = {'parameter': 'bW9kZT1ydW5UaW1lJmRhdGFUYWJsZV9pZD03Nw=='} # base64 encoded params for mode=runTime&dataTable_id=77

with requests.Session() as s:
    r = s.get('https://evanalytics.com/mlb/models/teams/advanced')
    r = s.post('https://evanalytics.com/admin/model/datatableQuery.php')
    data = r.json()
    cols = [th.text for th in bs(data['headerRow'], 'lxml').select('th')]
    rows = [[td.text for td in bs(row['dataRow'], 'lxml').select('td')] for row in data['dataRows']]
    df = pd.DataFrame(rows, columns = cols)
print(df)