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

tctcab 以前热衷于挖坟的时候我试过,遭遇统计之都瀑布流,不会扒,遂弃之。

晒泥版又升级了,添加了所有发帖回帖的作者统计数据。这导致数据量太大,载入需要花 10 秒 (为此特意加了个进度条随机来几句唐诗,免得没耐心等)。载入之后就好了。

R-devel 作者第一位是 Prof Brian Ripley,发了 4000 篇。前十里我只认识 Uwe Ligges 这个名字,发了将近 1000。

R-help 作者排第一的是 David Winsemius,居然写了 10000+ 多篇。Uwe Ligges 也发了 6000+。

    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 的话,可以先存到本地,每星期或者每月更新一次。