• R语言
  • 一个爬网页的练习:看看 R 邮件列表中最热门的讨论是什么

dapengde @tctcab Cloud2016 @yihui
统计之都 (本坛子)也爬好了。从2006年建站开始截至到 2019-06-17 一共有28310篇帖子, 1422 页 (也就是说如果您想手动爬到底的话,要单击“载入更多” 1421 次。。。所以还是写个程序吧。), 第一篇帖子是: https://d.cosx.org/d/5-5 ,题目为”hehe 瞎提意见“, 这篇帖子是 2006-05-20T21:32:35+00:00 创立的。

  • 根据讨论回复数量的前十名:
    > everything_cos2_replies[1:10,]
       Comment_count Participant_count                        URL create_Date last_post_Date active_days
    1           1261              1184  https://d.cosx.org/d/1553  2006-09-03     2019-06-14        4667
    2            923               850 https://d.cosx.org/d/13775  2009-01-16     2017-12-03        3243
    3            802               714   https://d.cosx.org/d/818  2006-08-01     2019-04-27        4652
    4            796               589  https://d.cosx.org/d/7865  2007-09-14     2018-07-18        3960
    5            633               590  https://d.cosx.org/d/2013  2006-09-29     2010-09-21        1453
    6            533               289  https://d.cosx.org/d/9233  2007-12-29     2018-08-06        3873
    7            528               450  https://d.cosx.org/d/8949  2007-12-09     2018-11-18        3997
    8            520               424 https://d.cosx.org/d/14985  2009-04-22     2019-05-29        3689
    9            507               490 https://d.cosx.org/d/13875  2009-02-02     2017-12-01        3224
    10           359                25 https://d.cosx.org/d/14141  2009-02-28     2017-10-19        3155
  • 根据讨论参与人数的前十名帖子:
    > everything_cos2_participants[1:10,]
       Comment_count Participant_count                        URL create_Date last_post_Date active_days
    1           1261              1184  https://d.cosx.org/d/1553  2006-09-03     2019-06-14        4667
    2            923               850 https://d.cosx.org/d/13775  2009-01-16     2017-12-03        3243
    3            802               714   https://d.cosx.org/d/818  2006-08-01     2019-04-27        4652
    4            633               590  https://d.cosx.org/d/2013  2006-09-29     2010-09-21        1453
    5            796               589  https://d.cosx.org/d/7865  2007-09-14     2018-07-18        3960
    6            507               490 https://d.cosx.org/d/13875  2009-02-02     2017-12-01        3224
    7            528               450  https://d.cosx.org/d/8949  2007-12-09     2018-11-18        3997
    8            520               424 https://d.cosx.org/d/14985  2009-04-22     2019-05-29        3689
    9            344               293  https://d.cosx.org/d/2070  2006-10-05     2017-03-07        3806
    10           533               289  https://d.cosx.org/d/9233  2007-12-29     2018-08-06        3873
    *根据活动天数(最新的回复-初始贴的日期)最久的前十名:
    > everything_cos2_active_days[1:10,]
       Comment_count Participant_count                       URL create_Date last_post_Date active_days
    1            160               121   https://d.cosx.org/d/35  2006-05-25     2019-04-03        4696
    2           1261              1184 https://d.cosx.org/d/1553  2006-09-03     2019-06-14        4667
    3            802               714  https://d.cosx.org/d/818  2006-08-01     2019-04-27        4652
    4            205               160    https://d.cosx.org/d/1  2006-05-19     2018-10-24        4541
    5             34                31  https://d.cosx.org/d/464  2006-06-22     2018-10-19        4502
    6             24                19 https://d.cosx.org/d/2739  2006-11-30     2019-03-12        4485
    7             18                 7 https://d.cosx.org/d/3004  2006-12-15     2019-02-04        4434
    8             42                26 https://d.cosx.org/d/2963  2006-12-12     2019-01-14        4416
    9             44                30 https://d.cosx.org/d/6142  2007-05-01     2019-05-24        4406
    10            30                20   https://d.cosx.org/d/16  2006-05-23     2018-05-30        4390
  • csv 数据: https://github.com/jienagu/tidyverse_examples/blob/master/COS_raw_data.csv
  • 源代码: https://github.com/jienagu/tidyverse_examples/blob/master/Web_scraping_COS_Chinese.R

我目前用的是 window,跟中文八字不合,有兴趣的小伙伴们可以根据我贴的源代码加上中文标题,标题在 attributes 的列名就是title.

    dapengde

    以前热衷于挖坟的时候我试过,遭遇统计之都瀑布流

    嗯嗯,确实是需要一些剑走偏锋的方法来挖这部分的信息。。。

    Jiena

    手动查了一下,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>

      dapengde 这个 https 的打不开,上边 http 的可以。

      COS 的链接们打不开。

        dapengde
        继续提意见:首先我觉得三个不同页面放在不同tab下不大好,因为默认为rdev,即使只对cos感兴趣的用户,刷新一下页面就又跑去加载rdev了,还是用单独页面好一。

        其次,经常出现断开连接,在调整年限范围之后。

        再次,数据处理时间还是好慢,是不是可以考虑sql

          tctcab

          1. 你是说把他仨分成三个彼此独立的站点吗?那倒是容易,而且也快。
          2. 调整年限后断开连接的情况我还没遇见。一般情况下,用户几分钟没活动时就会自动断开,是为了节省 shinyapps.io 的机时。
          3. 确实慢,因为加载时要从 https://stat.ethz.ch/ 上读取最新的数据。等哪位把 trivis 弄好吧。此外,authors 统计数据载入得最慢,用处似乎不大,玩两天就删掉得了。

          tctcab
          嗯,好厉害,这样的确可以省很多! 太棒啦!

          dapengde
          太好啦,这样不仅可以一目了然了,而且可以用搜索栏搜感兴趣的题目了,太感谢啦!

            dapengde
            啊我以为使用的是抓取好的csv,没想到每打开一次还得在后台偷偷爬一次啊?

            甚至切换tab是不是也会重新爬?

            看你的已有代码里写的还是apply系,每次抓取可能会同时对数据源发出成百上千次访问这特喵是DDoS攻击了吧哈哈哈

              tctcab dapengde
              啊,原来是鲜榨数据呀,哈哈哈。对于 r-help 和 r-devel 可以用把历史数据存到本地,当前月份鲜榨。或者直接写是截至到某某日期的结果。 对于 COS 的话,可以先存到本地,每星期或者每月更新一次。

                tctcab Jiena

                r-devel 和 r-help 的历史数据是预先抓好的,只鲜榨最近一个月的数据。cos 目前没法鲜榨,原因是 shinyapps.io 好像不支持 jsonlite 包——这一点我没有找到依据,反正故障现象就是只要用这个包,那么布署到服务器端就出错,虽然本地运行完全没问题。

                初次切换 tab 时顿一下,并不是在重新抓取数据。可能是在渲染表格和图片吧,毕竟数据有几十万行。第二次切换就不顿了。把 COS 两万八千条文章全列在一张页面上只需几秒。

                我觉得目前速度还可以忍吧。随进度条玩一玩唐诗,经常出现惊艳的随机组合,我有时候甚至希望载入得更慢一点。

                不过,既然用户那么在乎速度,我另做了个轻便版,只载入预下载的历史数据,载入时会快一点,并且以 COS 为首页:

                  dapengde

                  哈哈这个好,速度满意,使用体验好很多。

                  看了一下cos排名前面的帖子,要么是资料下载要么是标了“回复可见”的水贴,要筛出值得一看的帖子看来还不能依赖回复量