• [js高手之路]Node.js+jade抓取博客所有文章生成静态html文件


    这个周末,恶补了一下jade模板引擎,就为生成静态html文件,这篇文章需要知道jade以及看过我的上篇文章,我先给出他们的参考链接:

    [js高手之路]Node.js模板引擎教程-jade速学与实战1-基本用法

    [js高手之路]Node.js模板引擎教程-jade速学与实战2-流程控制,转义与非转义

    [js高手之路]Node.js模板引擎教程-jade速学与实战3-mixin

    [js高手之路]Node.js模板引擎教程-jade速学与实战4-模板引用,继承,插件使用

    [js高手之路]Node.js实现简易的爬虫-抓取博客所有文章列表信息

    在上面分享的这篇文章中,我抓取了博客的所有文章列表. 并没有采集入库,也没有做别的处理。这篇文章,我们就把上文中采集到的所有文章列表的信息整理一下,开始采集文章并且生成静态html文件了.先看下我的采集效果,我的博客目前77篇文章,1分钟不到就全部采集生成完毕了,这里我截了部分的图片,文件名用文章的id生成的,生成的文章,我写了一个简单的静态模板,所有的文章都是根据这个模板生成的.

    项目结构:

     好了,接下来,我们就来讲解下,这篇文章主要实现的功能:

    1,抓取文章,主要抓取文章的标题,内容,超链接,文章id(用于生成静态html文件)

    2,根据jade模板生成html文件

    一、抓取文章如何实现?

    非常简单,跟上文抓取文章列表的实现差不多

     1 function crawlerArc( url ){
     2     var html = '';
     3     var str = '';
     4     var arcDetail = {};
     5     http.get(url, function (res) {
     6         res.on('data', function (chunk) {
     7             html += chunk;
     8         });
     9         res.on('end', function () {
    10             arcDetail = filterArticle( html );
    11             str = jade.renderFile('./views/layout.jade', arcDetail );
    12             fs.writeFile( './html/' + arcDetail['id'] + '.html', str, function( err ){
    13                 if( err ) {
    14                     console.log( err );
    15                 }
    16                 console.log( 'success:' + url );
    17                 if ( aUrl.length ) crawlerArc( aUrl.shift() );
    18             } );
    19         });
    20     });
    21 }

    参数url就是文章的地址,把文章的内容抓取完毕之后,调用filterArticle( html ) 过滤出需要的文章信息(id, 标题,超链接,内容),然后用jade的renderFile这个api,实现模板内容的替换,

    模板内容替换完之后,肯定就需要生成html文件了, 所以用writeFile写入文件,写入文件时候,用id作为html文件名称。这就是生成一篇静态html文件的实现,

    接下来就是循环生成静态html文件了, 就是下面这行:

    if ( aUrl.length ) crawlerArc( aUrl.shift() );
     
    aUrl保存的是我的博客所有文章的url, 每次采集完一篇文章之后,就把当前文章的url删除,让下一篇文章的url出来,继续采集
     

    完整的实现代码server.js:

      1 var fs = require( 'fs' );
      2 var http = require( 'http' );
      3 var cheerio = require( 'cheerio' );
      4 var jade = require( 'jade' );
      5 
      6 var aList = [];
      7 var aUrl = [];
      8 
      9 function filterArticle(html) {
     10     var $ = cheerio.load( html );
     11     var arcDetail = {};
     12     var title = $( "#cb_post_title_url" ).text();
     13     var href = $( "#cb_post_title_url" ).attr( "href" );
     14     var re = //(d+).html/;
     15     var id = href.match( re )[1];
     16     var body = $( "#cnblogs_post_body" ).html();
     17     return {
     18         id : id,
     19         title : title,
     20         href : href,
     21         body : body
     22     };
     23 }
     24 
     25 function crawlerArc( url ){
     26     var html = '';
     27     var str = '';
     28     var arcDetail = {};
     29     http.get(url, function (res) {
     30         res.on('data', function (chunk) {
     31             html += chunk;
     32         });
     33         res.on('end', function () {
     34             arcDetail = filterArticle( html );
     35             str = jade.renderFile('./views/layout.jade', arcDetail );
     36             fs.writeFile( './html/' + arcDetail['id'] + '.html', str, function( err ){
     37                 if( err ) {
     38                     console.log( err );
     39                 }
     40                 console.log( 'success:' + url );
     41                 if ( aUrl.length ) crawlerArc( aUrl.shift() );
     42             } );
     43         });
     44     });
     45 }
     46 
     47 function filterHtml(html) {
     48     var $ = cheerio.load(html);
     49     var arcList = [];
     50     var aPost = $("#content").find(".post-list-item");
     51     aPost.each(function () {
     52         var ele = $(this);
     53         var title = ele.find("h2 a").text();
     54         var url = ele.find("h2 a").attr("href");
     55         ele.find(".c_b_p_desc a").remove();
     56         var entry = ele.find(".c_b_p_desc").text();
     57         ele.find("small a").remove();
     58         var listTime = ele.find("small").text();
     59         var re = /d{4}-d{2}-d{2}s*d{2}[:]d{2}/;
     60         listTime = listTime.match(re)[0];
     61 
     62         arcList.push({
     63             title: title,
     64             url: url,
     65             entry: entry,
     66             listTime: listTime
     67         });
     68     });
     69     return arcList;
     70 }
     71 
     72 function nextPage( html ){
     73     var $ = cheerio.load(html);
     74     var nextUrl = $("#pager a:last-child").attr('href');
     75     if ( !nextUrl ) return getArcUrl( aList );
     76     var curPage = $("#pager .current").text();
     77     if( !curPage ) curPage = 1;
     78     var nextPage = nextUrl.substring( nextUrl.indexOf( '=' ) + 1 );
     79     if ( curPage < nextPage ) crawler( nextUrl );
     80 }
     81 
     82 function crawler(url) {
     83     http.get(url, function (res) {
     84         var html = '';
     85         res.on('data', function (chunk) {
     86             html += chunk;
     87         });
     88         res.on('end', function () {
     89             aList.push( filterHtml(html) );
     90             nextPage( html );
     91         });
     92     });
     93 }
     94 
     95 function getArcUrl( arcList ){
     96     for( var key in arcList ){
     97         for( var k in arcList[key] ){
     98             aUrl.push( arcList[key][k]['url'] );
     99         }
    100     }
    101     crawlerArc( aUrl.shift() );
    102 }
    103 
    104 var url = 'http://www.cnblogs.com/ghostwu/';
    105 crawler( url );

    layout.jade文件:

    doctype html
    html
        head
            meta(charset='utf-8')
            title jade+node.js express
            link(rel="stylesheet", href='./css/bower_components/bootstrap/dist/css/bootstrap.min.css')
        body
            block header
                div.container
                    div.well.well-lg
                        h3 ghostwu的博客
                        p js高手之路
            block container
                div.container
                    h3
                        a(href="#{href}") !{title}
                    p !{body}
            block footer
                div.container
                    footer 版权所有 - by ghostwu

    后续的打算:

    1,采用mongodb入库

    2,支持断点采集

    3,采集图片

    4,采集小说

    等等....

  • 相关阅读:
    正则表达式30分钟入门教程
    Python的神奇方法指南
    Python 2.7教程
    javaweb开发.常用的第三方包
    javaweb开发.页面中文乱码问题
    javaweb开发.eclipse使用小常识
    javaweb开发3.基于Servlet+JSP+JavaBean开发模式的用户登录注册
    ionic3使用第三方图标
    json-server使用及路由配置
    javaweb开发2.新建一个javaweb项目
  • 原文地址:https://www.cnblogs.com/ghostwu/p/7545495.html
Copyright © 2020-2023  润新知