如何用R脚本批量从nypdonline.org API爬取警方统计数据?
解决NYPD Online API数据爬取问题
核心问题分析
你遇到的问题是直接访问http://oip.nypdonline.org/api/reports/只能拿到参数框架,因为这个API需要POST请求并携带完整参数才能返回实际数据,而非简单的GET请求。通过Chrome开发者工具可以捕获页面加载时发送的真实请求结构。
步骤1:捕获真实API请求参数
- 打开Chrome开发者工具(F12),切换到Network标签页,筛选XHR请求
- 访问示例页面
http://oip.nypdonline.org/view/1/@TAXID=938661,找到名称为reports的POST请求 - 查看Payload标签,复制完整请求参数(包含
taxId、reportId等关键字段);同时记录Headers中的Content-Type和Cookie(若需会话验证)
步骤2:R脚本实现API调用
使用httr包发送POST请求,携带正确参数获取数据,示例代码如下:
library(httr) library(jsonlite) # API端点 api_url <- "http://oip.nypdonline.org/api/reports/" # 待遍历的Tax ID列表 tax_ids <- c("938661", "替换为其他Tax ID") # 存储结果的容器 results <- list() # 遍历Tax ID for (tax_id in tax_ids) { # 构造请求参数(需与开发者工具捕获的Payload完全匹配) payload <- list( taxId = tax_id, reportId = 1, # 对应view路径后的数字,示例为1 filters = list(), groupBy = "" # 其他参数从Payload中复制补充 ) # 发送POST请求 response <- POST( url = api_url, body = payload, encode = "json", add_headers( "Content-Type" = "application/json" # 若需Cookie验证,添加此行:"Cookie" = "你的Cookie内容" ) ) # 解析JSON响应 data <- fromJSON(content(response, "text")) # 提取Total Arrests数据(根据实际JSON结构调整路径) total_arrests <- data$results[[1]]$`Total Arrests` # 保存结果 results[[tax_id]] <- list( tax_id = tax_id, total_arrests = total_arrests ) } # 转换为数据框用于回归分析 final_data <- do.call(rbind, lapply(results, as.data.frame)) print(final_data)
关键注意事项
- 参数完全匹配:必须严格复制开发者工具中捕获的Payload参数,包括
reportId、filters等,否则API仅返回框架 - 会话验证:若网站需要登录状态,需在请求中携带登录后的Cookie
- JSON路径调整:使用
str(data)查看响应结构,调整提取Total Arrests的路径
替代方案(API验证复杂时)
若API参数频繁变化,可使用RSelenium模拟浏览器加载页面后提取数据:
library(RSelenium) library(rvest) # 启动Chrome浏览器 driver <- rsDriver(browser = "chrome") remDr <- driver$client # 遍历Tax ID for (tax_id in tax_ids) { url <- paste0("http://oip.nypdonline.org/view/1/@TAXID=", tax_id) remDr$navigate(url) # 等待页面动态加载完成 Sys.sleep(3) # 提取页面数据 page_source <- remDr$getPageSource()[[1]] html <- read_html(page_source) total_arrests <- html_element(html, xpath = "//*[text()='Total Arrests']/following-sibling::*") %>% html_text() # 保存结果 results[[tax_id]] <- list(tax_id = tax_id, total_arrests = total_arrests) } # 关闭浏览器 remDr$close() driver$server$stop()
内容的提问来源于stack exchange,提问作者ThoureaulyRekt
相关产品推荐
相关产品推荐

