博客全站下载备份(含评论)

以前我写过一篇题为在 Kindle 上读博客 的帖子,讲的是如何把一些独立博客全站的博文扒下来,整理后放到 Kindle 上阅读的方法。用这个方法,我扒下来好几个精彩的独立博客,在 Kindle 上着实过了一把博客瘾。然而,过完瘾后发现了一个问题:别人的可以,自己的博客反倒是扒不下来了。而本文介绍的方法,可以通杀全部含有归档页的网络日志。

仔细研究了一下,原来,能扒下来的博客,归档的帖子地址都有规律可循,比如土木坛子和博士牌民工的归档地址规律都是 http://yourdomain.com/archives/i,其中i是个自然数。这是博主在wordpress后台这样设置的。因此,用 wget 下载时设置个循环让 i 递增就可以了。而我的博客,归档地址是按帖子标题来的,比如 “http://dapengde.com/2013-04-02-深情相拥(吉他谱)”这个帖子,地址中的汉字被自动转换成了乱七八糟的字符:

http://dapengde.com/2013-04-02-%e6%b7%b1%e6%83%85%e7%9b%b8%e6%8b%a5%ef%bc%88%e5%90%89%e4%bb%96%e8%b0%b1%ef%bc%89/

难怪扒不下来啊!如果别人的博客也是这样,那该怎么下载呢?

在万能的R面前,这是小菜一碟。思路跟前两天写的<批量下载网页上的图片>一文完全相同:从博客的归档页中获取全部博文的链接,对这些链接的文本进行处理,删除冗余信息,下载所需的博文。

博客一般都有个归档页,显示了全部博文的目录。“大鹏志”的归档页地址是http://dapengde.com/contents,所有带链接的博文都在这里。在 R 中利用 readLines() 函数读取这个页面。查看得到的文本,发现里边链接很多,要下载链接的文本行其规律是以“\t\t\t<li>”开头的。这就好办了,只要用正则表达式挑出这些链接就行了。这一步很关键。后面的步骤就容易了。

下载备份“大鹏志”全部博文(含评论)到本地 e:\dapengde 文件夹的 R 代码如下:

dir.create('d:\\dapengde')
setwd('d:\\dapengde')
aa <- readLines('http://dapengde.com/contents/', encoding='UTF-8') # 读取网页
for (i in 1:length(aa)) # 逐行处理
{
print(i)
  if (regexpr('\t\t\t<li>', aa[i])[1] == 1) # 挑出需要的链接行
  {
    link <- substring(aa[i], regexpr("http", aa[i])[1], regexpr("\" >", aa[i])[1]-2) # 获取链接
    output <- paste(i, ".html", sep = "") # 指定文件名
    download.file(link, output) # 下载网页
  }
}

如果会使用 vim 编辑器,那么不必用 R, 只需将网页源码在 vim 中用正则表达式处理一下,修改成 wget 命令下载网页的批处理文件,也可以得到同样的效果。

利用这种方法,可以通吃所有含有归档页的博客,将其全文和评论下载备份到本地电脑中。

注:本文写于2014-01-01。不知怎的,忘在了草稿箱里,今天才发现,略作改动后发表。

博客全站下载备份(含评论)》上有23条评论

    1. 大鹏 文章作者

      这条评论的自我优越感跃然纸上。要是没有后面那个括号就更好了。

      回复
  1. acheng99

    大鹏,R中怎么根据两列数据的关系进行插值?
    spline和approx不好用,他们都只能处理等长的两个向量,而且只能根据给出的n来确定插值的个数。
    我想根据两个数据框中指定的某一列的关系来线性插值
    具体算法大概是这样的http://zh.wikipedia.org/wiki/%E7%BA%BF%E6%80%A7%E6%8F%92%E5%80%BC

    回复
    1. 大鹏 文章作者

      我都是用approx。没看懂你的需求。举个具体的例子吧。

      回复
      1. acheng99

        恩,就是不太好说明清楚

        第一个数据框:
        a1,b1

        a2,b2

        a3,b3

        …..
        第2个数据框:
        c1,d1

        c2,d2

        c3,d3

        ….

        那么,存在一个ci,刚好小于aj,而ci的下一行刚好大于aj

        假如aj是a1,ci是c1,ci的下一行是c2

        我要处理成:

        a1,b1,(a1-c1)*(d2-d1)/(c2-c1)

        a2,b2,。。。。。

        我用了两个巨傻的for循环加一个if循环实现了功能,就是跑得太慢太慢。。。。

        回复
        1. 大鹏 文章作者

          其实只要达到目的就行了,不嫌慢。这个需求好独特,我觉得R可能没有现成的内置函数来完成,得自定义一个函数。你给的例子还是太抽象,比如b是有什么用呢?不妨把你的数据和慢代码发来我试试。

        2. 大鹏 文章作者

          收到,可是代码运行的结果不对啊,得到的返回值是NULL。

          tmp=NULL
          ###插值
          interpolation <- function(x, y) {
            #以x的depth为标尺来插值
            for (i in 1:length(x[, 1])) {
              for (j in 1:length(y[, 1])) {
                if (x[i,1] > y[j, 1] & x[i,1] < y[j + 1,1]) {
                  tmp_y <- y[j, ] + (y[j + 1, ] - y[j,]) * ((x[i, 1] - y[j, 1])/(y[j +1, 1] - y[j, 1]))
                  tmp <- rbind(tmp, cbind(x[i,1], tmp_y))
                }
              }
            }
            return(tmp)
          }    
          
          x <- read.delim('e:\\Temp\\ach\\x.txt')
          y <- read.delim('e:\\Temp\\ach\\y.txt')
          interpolation(x,y)
          
        3. 大鹏 文章作者

          我想我终于弄明白你的意图了。你想为每个a值找到相邻的两行c,使这个a值大小在这两个c之间;找到之后,进行相应的运算。是这样吧?从你给的数据看,c是递增的,这样找到的两行c就是唯一的,对吗?如果是这样,你就不用对c从头检查到尾,而是只需要找到第一个大于a的值就行了。

        4. acheng99

          嗯,是这个意思,如果不用for循环,怎么快速找到第一个符合要求的数呢?

        5. acheng99

          评论太长了,直接扰乱大鹏志的社会秩序,我想了个临时办法,先不在这回了,有问题我email骚扰你,感谢大鹏的耐心帮助

        6. 大鹏 文章作者

          貌似这事儿在这儿说不清楚。email吧。

    1. 大鹏 文章作者

      他们说上一张太嫩,跟我的经历不符,所以我换个老相点的。

      回复
      1. 方室网志

        脸黑点就是成熟吗?要成熟,眼神要深邃,还好,大鹏直接就闭眼了!哈哈
        话说结果还是那些html的形式吗?快倒是快。

        回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax