乐趣区

关于sf笔记备份及迁移

sf 笔记支持 Markdown 语法和常用编程语法,而且简约,个人感觉很好用,唯一缺少就是笔记分类归档。

sf 提供了编辑时笔记,访问路径:笔记 url+/raw

实现思路:

1. 使用爬虫获取全部笔记列表,获取 title 和 href。

2. 通过 https://segmentfault.com+href+/raw 获得全部笔记编辑时内容。(通过 https://segmentfault.com+href+/raw 获得全部笔记编辑时内容)

使用:

需要提供个人登录当前 cookie 修改 js 文件中 cook 变量

const cook =`PHPSESSID=web2~a……

自行安装依赖 express,superagent,cheerio

js:

const express = require('express');
const app = express();
const superagent= require('superagent');
const cheerio = require('cheerio');

const cook =`xxx`;

// 笔记列表
var page = 1;
var nots = []; // 最终返回数据
var errorStop = 0;
// 笔记详情
var nindex = 0; // 当前笔记页
var notsArr = [];
let getHotNews = (res) => {let $ = cheerio.load(res.text);
  let dom = $('.drafts-stream .title a');
  // 翻页数据停止
   errorStop = dom && dom.length ? 0 : 1;
   // 找到目标数据所在的页面元素,获取数据
  $('.drafts-stream .title a').each((idx, ele) => {let url =  $(ele).attr('href').indexOf('?')!=-1 ? $(ele).attr('href').split('?')[0]:$(ele).attr('href');
    let news = {title: $(ele).text(),        // 获取标题
     href:'https://segmentfault.com'+ url + '/raw'  // 获取链接
    };
    nots.push(news)              // 存入最终结果数组
    
  });
  page++;
};
// 获取笔记详情
function getNoteContent(endData){if( nindex+1 <= nots.length){console.log(nindex,nots[nindex].href)
        superagent.get(nots[nindex].href).set('Cookie',cook).end((err, res) => {if(!err){let $ = cheerio.load(res.text);
            
            notsArr.push({title:nots[nindex].title,content:res.text});// endData.send(notsArr)
            nindex++;
            getNoteContent(endData)
         }else{endData.send({data:notsArr});
         }
        
        });
    }else{endData.send({data:notsArr})
    }
}

// 获取笔记列表
function getNotes(req,res){superagent.get('https://segmentfault.com/user/note?page=' + page).set('Cookie',cook).end((err1, res1) => {if (!err1) {getHotNews(res1);
          if(!errorStop){getNotes(req,res)
          }else{
            // 如果无笔记则返回前端
            getNoteContent(res)  
          }
        
      } else {
         errorStop = 1;
         console.log(` 抓取失败 - ${err1}`) 
       }
    });
    
}
app.get('/', function (req, res) {res.header("Access-Control-Allow-Origin", "*");
    // 允许的 header 类型
    res.header("Access-Control-Allow-Headers", "content-type");
    // 跨域允许的请求方式 
    res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
    
    page = 1;
    nots = []; // 最终返回数据
    errorStop = 0;
    // 笔记详情
    nindex = 0; // 当前笔记页
    notsArr = [];
    
    getNotes(req, res);
});


let server = app.listen(5100, function () {let host = server.address().address;
  let port = server.address().port;
  console.log('Your App is running at http://%s:%s', host, port);
});

html:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script src="https://cdn.bootcss.com/axios/0.19.0/axios.js"></script>
    </head>
    <body>
        <div id="app">
            <ul id="ul"></ul>
        </div>
        <script type="text/javascript">
            function escape2Html(str) {var arrEntities={'lt':'<','gt':'>','nbsp':'','amp':'&','quot':'"'}; 
             return str.replace(/&(lt|gt|nbsp|amp|quot);/ig,function(all,t){return arrEntities[t];}); 
            }
            
            axios('http://127.0.0.1:5100').then((res)=>{
                let data ='';
                res.data.data.forEach((item,i)=>{data+="<li><h4>"+(i+1)+"."+ item.title +"</h4><div><pre><xmp>"+escape2Html(item.content)+"</xmp></pre></div></li>"
                })
                document.getElementById('ul').innerHTML = data;
            });
            
        </script>
    </body>
</html>

htm 暂时展示全部笔记内容,可根据接口备份到别的网站进行发布文章

退出移动版