我正在尝试从相对较新的 nypdonline.org 网站获取各种警方统计数据的公共数据,该网站可以通过多种方式访问。通常查询此数据的主要方法是通过位于 https://nypdonline.org/link/2 的在线查找工具,或直接使用唯一的税号,例如:http://oip .nypdonline.org/view/1/@TAXID=938661.
理想情况下,我希望 R 脚本能够遍历税号列表(这是唯一标识符),以从网站中提取特定数据点 - 我目前正在查看“总逮捕数”,因为这将有助于充当控制在回归工作中,但如果我可以获得一个数据点,我应该能够获得所有数据点。
主要问题是该网站经历了查询第二个 URL 的过程,我认为它从中提取 JSON 数据。我的第一个努力是尝试使用 RVest 定位单个页面,并使用 html_nodes() 尝试选择 CSS 元素或 XPath 元素:
library(rvest)
library(dplyr)
url <- "http://oip.nypdonline.org/view/1/@TAXID=938661"
webpage <- read_html(url)
total_arrests <- webpage %>%
html_nodes("[various CSS / xpath elements attempted here]") %>%
html_text() %>%
as.numeric()
但这不会产生任何结果;检查 HTML,我可以看到嵌入的这些数字(参见图片一和代码中的数字 201),但我找不到实际数据抓取它们的方法,大概是因为此代码的排列方式它们的位置动态变化,或者因为部分他们的数据是一个随机标识符。
使用 Chrome 中的开发工具,我可以看到(图 2)该网站正在向辅助 URL 发送请求。我认为这是我真正需要查询 JSON 数据的 URL。
我的困惑可能只是具体如何执行此操作,特别是在一个似乎从 MSSQL 数据库查询 JSON 数据的网站的情况下 - 如果我直接访问以下网站,我可以看到似乎是 JSON 参数,包括我需要的唯一税号值的可能变量: http://oip.nypdonline.org/api/reports/
但这看起来只是数据的框架,我需要一个我找不到也不太明白的步骤来实际查询 API 来获取特定数据。我可以轻松地将上述 JSON 页面数据抓取到 R 中,但最终我得到的基本上是 JSON 框架,没有任何实际数据:
library(rvest)
library(jsonlite)
url <- "http://oip.nypdonline.org/api/reports/"
webpage <- read_html(url)
json_data <- html_text(html_nodes(webpage, "body"))
data_list <- fromJSON(json_data, flatten = TRUE)
View(data_list)
这对我提供了 JSON 类别非常有帮助,在其中我想要搜索的唯一税号 ID 值(也在上面的图像 3 JSON 中突出显示)可能类似于:
json[[1]][["DataSource"]][["Parameters"]][[1]][["Name"]]
但我不太清楚如何使用它来实际查询 API。很高兴能转向正确的方向,因为我认为有一个元素我只是不理解。
从 Google Chrome 开发者控制台,我发现了一个包含以下内容的 POST 网址
url <- "https://oip.nypdonline.org/api/reports/1/datasource/list"
payload <- '{filters: [{key: "@TAXID", label: "TAXID", values: ["938661"]}]}'
我使用了
httr::POST()
,然后使用 listviewer 包查看结果
response <- httr::POST(url, content_type("application/json"), body = payload)
json <- httr::content(response, as = "text")
listviewer::jsonedit(json)
可以使用
jsonlite::fromJSON()
将其提取为 R 对象,但我使用 CRAN 包 rjsoncons 将所有内容提取到 data.frame (tibble)
> rjsoncons::j_pivot(json, as = "tibble")
# A tibble: 1 × 6
Label ImageURL CodeTemplate Items Interactions RelatedItems
<chr> <chr> <chr> <list> <list> <list>
1 "HERNANDEZ, GREGORY D … https:/… "HERNANDEZ,… <list> <list [0]> <list [0]>
或者只是使用 JMESpath
的一部分> rjsoncons::j_pivot(json, "[0].Items", as = "tibble")
# A tibble: 6 × 9
Id Label Value CodeTemplate LabelAlignment LabelFont LabelColor
<chr> <chr> <chr> <chr> <chr> <chr> <list>
1 a2fded09-5439-4b… Rank: "POL… {Value} text-right 12px Ari… <chr [1]>
2 20e891ce-1dcf-4d… Appo… "7/1… {Value} text-right 12px Ari… <NULL>
3 1692f3bf-ed70-4b… Comm… "049… {Value} text-right 12px Ari… <chr [1]>
4 8a2bcb6f-e064-44… Assi… "7/5… {Value} text-right 12px Ari… <NULL>
5 0ec90f94-b636-47… Ethn… "HIS… {Value} text-right 12px Ari… <chr [1]>
6 42f74dfc-ee54-4b… Shie… "264… {Value} text-right 12px Ari… <NULL>
# ℹ 2 more variables: ValueAlignment <chr>, ValueFont <chr>
也许这会让你在路上走得更远?