一个爬网页的练习:看看 R 邮件列表中最热门的讨论是什么
手动查了一下,cos论坛基于flarum,查了一下是有REST api来提取讨论的,地址是
https://d.cosx.org/api/discussions?page[limit]=50
试了一下每个请求最大返回50串,
这个好处是不用20串一扒减少了三分之二对cos服务器的轰炸…(28310/50=568.6)
另外代码也可以精简很多,省去rvest的操作,直接jsonlite读数据, 甚至下一页的链接也可以在api返回的links里找到
最终代码:
firsturl = "https://d.cosx.org/api/discussions?page[limit]=50"
cos.li = list()
counter = 1
cos.li[[counter]] = jsonlite::fromJSON(firsturl)
# if the next link exists, scrape it.
while ("next" %in% names(cos.li[[counter]]$links)) {
counter = counter +1
cos.li[[counter]] = jsonlite::fromJSON(cos.li[[counter-1]]$links[['next']])
}
## combine all df
cos.all = do.call(rbind,
lapply(cos.li, function(l) {
df = l$data$attributes
df$link = paste0("https://d.cosx.org/d/", l$data$id)
return(df)
}))
不过碰到个问题,爬到“https://d.cosx.org/api/discussions?page[limit]=50?page[offset]=9550”
的时候出现http 500 内部错误,浏览器直接可以打开但是R里用上面jsonlite::fromJSON的话始终会出错,好奇怪
- 已编辑
tctcab 试了一下,我觉得是问题来自 9550 的下下一页:
<https://d.cosx.org/api/discussions?page%5Blimit%5D=50&page%5Boffset%5D=9650>
浏览器打开就是错误 500。
为了跳过这一页,我把楼上 Jiena tctcab 的方法柔在了一起:
# get the max page (1422 pages on 2019-06-18)
get_maxpage <- function(page_range = 1421:1500){
for (i in page_range) {
print(paste(Sys.time(), i))
COS_link <- xml2::read_html(paste0('https://d.cosx.org/all?page=', i))
url_vector= rvest::html_attr(rvest::html_nodes(COS_link, "a"), "href")
last_link = url_vector[length(url_vector)]
last_number <- as.numeric(gsub("[https://d.cosx.org/all?page=]", "",last_link) )
if(last_number <= i - 1){
message('There are ', i, ' pages with 20 posts on each.')
return(i)
}
}
}
# get json from cos
get_js <- function(url){
print(paste(Sys.time(), url))
mytry <- try(jsonlite::fromJSON(url))
if(class(mytry) == 'try-error') return(NULL)
jsonlite::fromJSON(url)
}
maxpage <- get_maxpage(1421:1500)
cos_url <- paste0('https://d.cosx.org/api/discussions?page%5Blimit%5D=50&page%5Boffset%5D=', seq(0, maxpage * 20, 50) + 50)
cos_js <- lapply(cos_url, get_js)
可以看到, 500 错误不仅出现在读 9550 时,还出现在多处,例如 10350 和 11650,因为他们的下下一页用浏览器打开就是 500 错误:
<https://d.cosx.org/api/discussions?page%5Blimit%5D=50&page%5Boffset%5D=10450>
<https://d.cosx.org/api/discussions?page%5Blimit%5D=50&page%5Boffset%5D=11750>
- 已编辑
晒泥版新增 COS 页面!中文标题加进来啦 Jiena
- 已编辑
- 你是说把他仨分成三个彼此独立的站点吗?那倒是容易,而且也快。
- 调整年限后断开连接的情况我还没遇见。一般情况下,用户几分钟没活动时就会自动断开,是为了节省 shinyapps.io 的机时。
- 确实慢,因为加载时要从 https://stat.ethz.ch/ 上读取最新的数据。等哪位把 trivis 弄好吧。此外,authors 统计数据载入得最慢,用处似乎不大,玩两天就删掉得了。
- 已编辑
Jiena 不客气。都是在你们的基础上完成的。这个 shiny 工具我们共同署名好不好?@tctcab @Cloud2016 @yihui
回头我打成个包,便于本地使用。
- 已编辑
r-devel 和 r-help 的历史数据是预先抓好的,只鲜榨最近一个月的数据。cos 目前没法鲜榨,原因是 shinyapps.io 好像不支持 jsonlite 包——这一点我没有找到依据,反正故障现象就是只要用这个包,那么布署到服务器端就出错,虽然本地运行完全没问题。
初次切换 tab 时顿一下,并不是在重新抓取数据。可能是在渲染表格和图片吧,毕竟数据有几十万行。第二次切换就不顿了。把 COS 两万八千条文章全列在一张页面上只需几秒。
我觉得目前速度还可以忍吧。随进度条玩一玩唐诗,经常出现惊艳的随机组合,我有时候甚至希望载入得更慢一点。
不过,既然用户那么在乎速度,我另做了个轻便版,只载入预下载的历史数据,载入时会快一点,并且以 COS 为首页: