Node.js实现网络新闻爬虫及搜索功能(三)

[Nodejs] Nodejs实现新闻爬虫及展示网站 文章目录1. `Node.js`爬取新闻网站1.1 用正则表达式判断新闻页面1.2 网易新闻页面结构分析2. 将爬取的信息存储于`mysql`数据库中.2.1 `Mysql`操作2.2 `Nodejs`操作3.利用`Nodejs`框架`Express`搭建基础的查询网站.3.1 `Express`框架生成搜索网站脚手架4 利用`css`, `html`, `js`等前端技术对网站进行功能扩充和美化.前端设计4.1 网站查询框美化4.2 网站图标网站`logo`4.3 网站导航栏4.4 网站图标展示栏4.5 阅读详情

Node.js实现网络新闻爬虫及搜索功能(三)

系列文章查看不到可能是优快云审核原因,可以在我的知乎专栏看到所有文章:https://www.zhihu.com/column/c_1370026160999415808

项目要求

一、爬虫部分
        1、完成目标网站的网页分析和爬虫设计。
        2、爬取不少于100条数据(每条数据包括7个字段,新闻关键词、新闻标题、新闻日期、新闻作者、新闻来源、新闻摘要、新闻内容),并存储在数据库中。

二、搜索网站部分
        1、完成对数据库中爬取新闻内容和标题的搜索功能,搜索结果以表格形式展示在前端页面中。
        2、完成对搜索内容的时间热度分析,使用表格展示爬取数据内容中每一天包含搜索内容的条数。

本文是该项目第三部分:改写爬虫为定时爬取

二、定时爬虫改写

        经过该系列文章(一)和(二),我们已经拥有了两个Node.js爬虫,因为新闻网站不断对新的新闻进行推送,所以我们需要设置一个定时函数,在每个指定时间调用爬虫,实现爬取的新闻更新。

1. 回顾已有代码

crawler_163.js

var crawler_request = require('request');
var crawler_iconv = require('iconv-lite');
var crawler_cheerio = require('cheerio');
require('date-utils');

// 连接数据库
var crawler_sql = require("./crawler_sql.js");
// var crawler_sql = require("mysql");
// var pool = crawler_sql.createPool({
//     host: '127.0.0.1',
//     user: 'root',
//     password: 'root',
//     database: 'crawl'
// });
// var query = function(sql, sqlparam, callback) {
//     pool.getConnection(function(err, conn) {
//         if (err) {
//             callback(err, null, null);
//         } else {
//             conn.query(sql, sqlparam, function(qerr, vals, fields) {
//                 conn.release(); //释放连接 
//                 callback(qerr, vals, fields); //事件驱动回调 
//             });
//         }
//     });
// };
// var query_noparam = function(sql, callback) {
//     pool.getConnection(function(err, conn) {
//         if (err) {
//             callback(err, null, null);
//         } else {
//             conn.query(sql, function(qerr, vals, fields) {
//                 conn.release(); //释放连接 
//                 callback(qerr, vals, fields); //事件驱动回调 
//             });
//         }
//     });
// };
// exports.query = query;
// exports.query_noparam = query_noparam;

// 爬取网页首页
function request(url, callback) {
    var options = {
        url: url,
        encoding: null,
        headers: {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36'
        },
        timeout: 10000
    }
    crawler_request(options, callback);
};

var crawler_url = 'https://news.163.com/';
crawler();

function crawler() {
    request(crawler_url, function(err, res, body) {
        // 网页解析
        try {
            // 编码转换
            var url_encoding = 'UTF-8';
            var url_html = crawler_iconv.decode(body, url_encoding);
            //解析网页
            var $ = crawler_cheerio.load(url_html, { decodeEntities: true });
        } catch (e) {
            console.log('页面解码错误:' + e);
        }
        // 判断网页是否存在超链接
        var url_hrefs;
        try {
            url_hrefs = eval("$('a')");
        } catch (e) {
            console.log('页面不存在超链接' + e);
        }
        // 遍历网页中所有超链接
        url_hrefs.each(function(i, e) {
            // 获取新闻
            var news_url = "";
            try {
                var url_href = "";
                url_href = $(e).attr("href");
                if (typeof(url_href) == "undefined") {
                    return true;
                }
                if (url_href.toLowerCase().indexOf('http://') >= 0 || url_href.toLowerCase().indexOf('https://') >= 0) {
                    news_url = url_href;
                } else if (url_href.startsWith('//')) {
                    news_url = 'https:' + url_href;
                } else {
                    news_url = crawler_url.substr(0, crawler_url.lastIndexOf('/') + 1) + url_href;
                }
            } catch (e) {
                console.log('获取新闻页面出错' + e);
            }
            // 检验新闻网页url是否符合url命名格式
            var news_reg = /\/news\/article\/([a-zA-Z0-9]{16}).html/;
            var news_reg_special = /\/news\/article\/([a-zA-Z0-9]{8})0001982T.html/;
            // 如:https://www.163.com/news/article/G8HQOAKE0001899O.html
            if (!news_reg.test(news_url) || news_reg_special.test(news_url)) {
                console.log('新闻链接不符合格式!');
                return;
            }
            // 爬取新闻页面
            var news_search_sql = 'select url from news where url=?';
            var news_search = [news_url];
            crawler_sql.query(news_search_sql, news_search, function(qerr, vals, fields) {
                if (vals.length > 0) {
                    console.log('该新闻页面已被爬取!')
                } else {
                    crawler_news_url(news_url);
                }
            });
        });
    });
}

// 爬取新闻链接
function crawler_news_url(news_url) {
    request(news_url, function(err, res, body) {
        // 网页解析
        try {
            // 编码转换
            var url_encoding = 'UTF-8';
            var url_html = crawler_iconv.decode(body, url_encoding);
            //解析网页
            var $ = crawler_cheerio.load(url_html, { decodeEntities: true });
        } catch (e) {
            console.log('页面解码错误:' + e);
        }
        // 定义新闻信息json
        var news = {};
        news.crawler_time = (new Date()).toFormat("YYYY-MM-DD HH:MM:SS.SSSS");
        news.url = news_url;
        news.url_encoding = 'UTF-8';
        news.keywords = '';
        news.title = '';
        news.date = new Date();
        news.author = '';
        news.source = '';
        news.summary = '';
        news.content = '';
        // 获取新闻关键词
        try {
            news.keywords = eval("$('meta[name=\"keywords\"]').eq(0).attr(\"content\")");
        } catch (e) {
            console.log('新闻关键词获取错误:' + e);
        }
        // 获取新闻标题
        try {
            news.title = eval("$('title').text()").replace(/[\r\n\s]/g, "");
        } catch (e) {
            console.log('新闻标题获取错误:' + e);
        }
        // 获取新闻时间
        try {
            news.date = eval("$('#ne_wrap').eq(0).attr(\"data-publishtime\")");
        } catch (e) {
            console.log('新闻日期获取错误:' + e);
        }
        // 获取新闻作者
        try {
            news.author = eval("$('.icon').eq(0).attr(\"alt\")");
            if (news.author == 'netease') {
                news.author = eval("$('.post_author').text()").replace(/[\r\n\s]/g, "").replace("本文来源:", "");
                var author_reg = /责任编辑:.+_/;
                news.author  = author_reg.exec(news.author).toString().replace("责任编辑:", "").replace("_", "");
            }
        } catch (e) {
            console.log('新闻作者获取错误:' + e);
        }
        // 获取新闻来源
        try {
            news.source = eval("$('.post_info').children(':first').text()").replace(/[\r\n\s]/g, "");
            if (news.source == '举报') {
                news.source = eval("$('.post_info').prop('firstChild').nodeValue").replace(/[\r\n\s]/g, "");
                var source_reg = /.+来源:/;
                var tmp = source_reg.exec(news.source).toString();
                news.source = news.source.replace(tmp, "");
            }
        } catch (e) {
            console.log('新闻来源获取错误:' + e);
        }
        // 获取新闻摘要
        try {
            news.summary = eval("$('meta[name=\"description\"]').eq(0).attr(\"content\")").replace(/[\r\n\s]/g, "");
        } catch (e) {
            console.log('新闻摘要获取错误:' + e);
        }
        // 获取新闻内容
        try {
            news.content = eval("$('.post_body').text()").replace(/[\r\n\s]/g, "");
        } catch (e) {
            console.log('新闻内容获取错误:' + e);
        }
        console.log(JSON.stringify(news));

        // 写入数据库
        if (news.content != '') {
            var news_add_sql = 'INSERT INTO news(url, source, url_encoding, title, keywords, author, date, crawler_time, summary, content) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
            var news_add = [news.url, news.source, news.url_encoding,
                news.title, news.keywords, news.author, news.date,
                news.crawler_time, news.summary, news.content
            ];
            crawler_sql.query(news_add_sql, news_add, function(qerr, vals, fields) {
                if (qerr) {
                    console.log(qerr);
                }
            });
        }
    });
}

crawler_sina.js

var crawler_request = require('request');
var crawler_iconv = require('iconv-lite');
var crawler_cheerio = require('cheerio');
require('date-utils');

// 连接数据库
var crawler_sql = require("./crawler_sql.js");

// 爬取网页首页
function request(url, callback) {
    var options = {
        url: url,
        encoding: null,
        headers: {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36'
        },
        timeout: 10000
    }
    crawler_request(options, callback);
};

var crawler_url = 'https://news.sina.com.cn/';
crawler();

function crawler() {
    request(crawler_url, function(err, res, body) {
        // 网页解析
        try {
            // 编码转换
            var url_encoding = 'UTF-8';
            var url_html = crawler_iconv.decode(body, url_encoding);
            //解析网页
            var $ = crawler_cheerio.load(url_html, { decodeEntities: true });
        } catch (e) {
            console.log('页面解码错误:' + e);
        }
        // 判断网页是否存在超链接
        var url_hrefs;
        try {
            url_hrefs = eval("$('a')");
        } catch (e) {
            console.log('页面不存在超链接' + e);
        }
        // 遍历网页中所有超链接
        url_hrefs.each(function(i, e) {
            // 获取新闻
            var news_url = "";
            try {
                var url_href = "";
                url_href = $(e).attr("href");
                if (typeof(url_href) == "undefined") {
                    return true;
                }
                if (url_href.toLowerCase().indexOf('http://') >= 0 || url_href.toLowerCase().indexOf('https://') >= 0) {
                    news_url = url_href;
                } else if (url_href.startsWith('//')) {
                    news_url = 'https:' + url_href;
                } else {
                    news_url = crawler_url.substr(0, crawler_url.lastIndexOf('/') + 1) + url_href;
                }
            } catch (e) {
                console.log('获取新闻页面出错' + e);
            }
            // 检验新闻网页url是否符合url命名格式
            var news_reg = /\/(\d{4})-(\d{2})-(\d{2})\/doc-([a-zA-Z0-9]{15}).shtml/;
            // 如:https://news.sina.com.cn/c/xl/2021-04-29/doc-ikmyaawc2421496.shtml
            if (!news_reg.test(news_url)) {
                console.log('新闻链接不符合格式!');
                return;
            }
            // 爬取新闻页面
            var news_search_sql = 'select url from news where url=?';
            var news_search = [news_url];
            crawler_sql.query(news_search_sql, news_search, function(qerr, vals, fields) {
                if (vals.length > 0) {
                    console.log('该新闻页面已被爬取!')
                } else {
                    crawler_news_url(news_url);
                }
            });
        });
    });
};

// 爬取新闻链接
function crawler_news_url(news_url) {
    request(news_url, function(err, res, body) {
        // 网页解析
        try {
            // 编码转换
            var url_encoding = 'UTF-8';
            var url_html = crawler_iconv.decode(body, url_encoding);
            //解析网页
            var $ = crawler_cheerio.load(url_html, { decodeEntities: true });
        } catch (e) {
            console.log('页面解码错误:' + e);
        }
        // 定义新闻信息json
        var news = {};
        news.crawler_time = (new Date()).toFormat("YYYY-MM-DD HH:MM:SS.SSSS");
        news.url = news_url;
        news.url_encoding = 'UTF-8';
        news.keywords = '';
        news.title = '';
        news.date = new Date();
        news.author = '';
        news.source = '';
        news.summary = '';
        news.content = '';
        // 获取新闻关键词
        try {
            news.keywords = eval("$('meta[name=\"keywords\"]').eq(0).attr(\"content\")");
        } catch (e) {
            console.log('新闻关键词获取错误:' + e);
        }
        // 获取新闻标题
        try {
            news.title = eval("$('title').text()").replace(/[\r\n\s]/g, "");
        } catch (e) {
            console.log('新闻标题获取错误:' + e);
        }
        // 获取新闻时间
        try {
            news.date = eval("$('.date').text()");
            news.date = news.date.replace('年', '-');
            news.date = news.date.replace('月', '-');
            news.date = news.date.replace('日', '');
        } catch (e) {
            console.log('新闻日期获取错误:' + e);
        }
        // 获取新闻作者
        try {
            news.author = eval("$('.show_author').text()").replace("责任编辑:", "");
        } catch (e) {
            console.log('新闻作者获取错误:' + e);
        }
        // 获取新闻来源
        try {
            news.source = eval("$('meta[name=\"mediaid\"]').eq(0).attr(\"content\")");
        } catch (e) {
            console.log('新闻来源获取错误:' + e);
        }
        // 获取新闻摘要
        try {
            news.summary = eval("$('meta[name=\"description\"]').eq(0).attr(\"content\")").replace(/[\r\n\s]/g, "");
            if (news.summary == "") {
                news.summary = eval("$('meta[property=\"og:description\"]').eq(0).attr(\"content\")").replace(/[\r\n\s]/g, "");
            }
        } catch (e) {
            console.log('新闻摘要获取错误:' + e);
        }
        // 获取新闻内容
        try {
            news.content = eval("$('.article').text()").replace(/[\r\n\s]/g, "");
            if (news.content == "") {
                news.content = eval("$('#article_content').text()").replace(/[\r\n\s]/g, "");
            }
        } catch (e) {
            console.log('新闻内容获取错误:' + e);
        }
        console.log(JSON.stringify(news));

        // 写入数据库
        if (news.author == '' || news.author == null) {
            news.author = news.source;
        }
        if (news.content != '' && news.source != '') {
            var news_add_sql = 'INSERT INTO news(url, source, url_encoding, title, keywords, author, date, crawler_time, summary, content) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
            var news_add = [news.url, news.source, news.url_encoding,
                news.title, news.keywords, news.author, news.date,
                news.crawler_time, news.summary, news.content
            ];
            crawler_sql.query(news_add_sql, news_add, function(qerr, vals, fields) {
                if (qerr) {
                    console.log(qerr);
                }
            });
        }
    });
}

2. 引入相关包

        新建crawler_schedule_163.js和crawler_schedule_sina.js文件。

这两个文件是对对应的crawler_163.js和crawler_sina.js文件分别进行同样的改写

        引入需要的相关包node-schedule:

// 定时执行
var crawler_schedule = require('node-schedule');

        建立定时规则:

var crawler_rule = new crawler_schedule.RecurrenceRule();
// crawler_rule.hour = [0, 12];
// crawler_rule.minute = 5;
crawler_rule.second = 0;

        其中,.hour方法是对设定的时刻调用爬虫,如此处的[0, 12]就是指0时和12时执行爬虫;.minute方法是对设定的分钟数调用爬虫,如此处的5就是指每小时的第5分钟执行爬虫;.second方法是对设定的秒数调用爬虫,如此处的0就是指每分钟的第0秒开始爬虫。
        将原来调用爬虫的主函数注释掉:

// crawler();

改为:

crawler_schedule.scheduleJob(crawler_rule, function() {
    crawler();
});

3. 定时爬虫代码

crawler_schedule_163.js

var crawler_request = require('request');
var crawler_iconv = require('iconv-lite');
var crawler_cheerio = require('cheerio');
require('date-utils');

// 连接数据库
var crawler_sql = require("./crawler_sql.js");

// 定时执行
var crawler_schedule = require('node-schedule');
var crawler_rule = new crawler_schedule.RecurrenceRule();
// crawler_rule.hour = [0, 12];
// crawler_rule.minute = 5;
crawler_rule.second = 0;
crawler_schedule.scheduleJob(crawler_rule, function() {
    crawler();
});

// 定时爬取网页首页
function request(url, callback) {
    var options = {
        url: url,
        encoding: null,
        headers: {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36'
        },
        timeout: 10000
    }
    crawler_request(options, callback);
};

var crawler_url = 'https://news.163.com/';

function crawler() {
    request(crawler_url, function(err, res, body) {
        // 网页解析
        try {
            // 编码转换
            var url_encoding = 'UTF-8';
            var url_html = crawler_iconv.decode(body, url_encoding);
            //解析网页
            var $ = crawler_cheerio.load(url_html, { decodeEntities: true });
        } catch (e) {
            console.log('页面解码错误:' + e);
        }
        // 判断网页是否存在超链接
        var url_hrefs;
        try {
            url_hrefs = eval("$('a')");
        } catch (e) {
            console.log('页面不存在超链接' + e);
        }
        // 遍历网页中所有超链接
        url_hrefs.each(function(i, e) {
            // 获取新闻
            var news_url = "";
            try {
                var url_href = "";
                url_href = $(e).attr("href");
                if (typeof(url_href) == "undefined") {
                    return true;
                }
                if (url_href.toLowerCase().indexOf('http://') >= 0 || url_href.toLowerCase().indexOf('https://') >= 0) {
                    news_url = url_href;
                } else if (url_href.startsWith('//')) {
                    news_url = 'https:' + url_href;
                } else {
                    news_url = crawler_url.substr(0, crawler_url.lastIndexOf('/') + 1) + url_href;
                }
            } catch (e) {
                console.log('获取新闻页面出错' + e);
            }
            // 检验新闻网页url是否符合url命名格式
            var news_reg = /\/news\/article\/([a-zA-Z0-9]{16}).html/;
            var news_reg_special = /\/news\/article\/([a-zA-Z0-9]{8})0001982T.html/
            // 如:https://www.163.com/news/article/G8HQOAKE0001899O.html
            if (!news_reg.test(news_url) || news_reg_special.test(news_url)) {
                console.log('新闻链接不符合格式!');
                return;
            }
            // 爬取新闻页面
            var news_search_sql = 'select url from news where url=?';
            var news_search = [news_url];
            crawler_sql.query(news_search_sql, news_search, function(qerr, vals, fields) {
                if (vals.length > 0) {
                    console.log('该新闻页面已被爬取!')
                } else {
                    crawler_news_url(news_url);
                }
            });
        });
    });
}

// 爬取新闻链接
function crawler_news_url(news_url) {
    request(news_url, function(err, res, body) {
        // 网页解析
        try {
            // 编码转换
            var url_encoding = 'UTF-8';
            var url_html = crawler_iconv.decode(body, url_encoding);
            //解析网页
            var $ = crawler_cheerio.load(url_html, { decodeEntities: true });
        } catch (e) {
            console.log('页面解码错误:' + e);
        }
        // 定义新闻信息json
        var news = {};
        news.crawler_time = (new Date()).toFormat("YYYY-MM-DD HH:MM:SS.SSSS");
        news.url = news_url;
        news.url_encoding = 'UTF-8';
        news.keywords = '';
        news.title = '';
        news.date = new Date();
        news.author = '';
        news.source = '';
        news.summary = '';
        news.content = '';
        // 获取新闻关键词
        try {
            news.keywords = eval("$('meta[name=\"keywords\"]').eq(0).attr(\"content\")");
        } catch (e) {
            console.log('新闻关键词获取错误:' + e);
        }
        // 获取新闻标题
        try {
            news.title = eval("$('title').text()").replace(/[\r\n\s]/g, "");
        } catch (e) {
            console.log('新闻标题获取错误:' + e);
        }
        // 获取新闻时间
        try {
            news.date = eval("$('#ne_wrap').eq(0).attr(\"data-publishtime\")");
        } catch (e) {
            console.log('新闻日期获取错误:' + e);
        }
        // 获取新闻作者
        try {
            news.author = eval("$('.icon').eq(0).attr(\"alt\")");
            if (news.author == 'netease') {
                news.author = eval("$('.post_author').text()").replace(/[\r\n\s]/g, "").replace("本文来源:", "");
                var author_reg = /责任编辑:.+_/;
                news.author  = author_reg.exec(news.author).toString().replace("责任编辑:", "").replace("_", "");
            }
        } catch (e) {
            console.log('新闻作者获取错误:' + e);
        }
        // 获取新闻来源
        try {
            news.source = eval("$('.post_info').children(':first').text()").replace(/[\r\n\s]/g, "");
            if (news.source == '举报') {
                news.source = eval("$('.post_info').prop('firstChild').nodeValue").replace(/[\r\n\s]/g, "");
                var source_reg = /.+来源:/;
                var tmp = source_reg.exec(news.source).toString();
                news.source = news.source.replace(tmp, "");
            }
        } catch (e) {
            console.log('新闻来源获取错误:' + e);
        }
        // 获取新闻摘要
        try {
            news.summary = eval("$('meta[name=\"description\"]').eq(0).attr(\"content\")").replace(/[\r\n\s]/g, "");
        } catch (e) {
            console.log('新闻摘要获取错误:' + e);
        }
        // 获取新闻内容
        try {
            news.content = eval("$('.post_body').text()").replace(/[\r\n\s]/g, "");
        } catch (e) {
            console.log('新闻内容获取错误:' + e);
        }
        console.log(JSON.stringify(news));

        // 写入数据库
        if (news.content != '') {
            var news_add_sql = 'INSERT INTO news(url, source, url_encoding, title, keywords, author, date, crawler_time, summary, content) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
            var news_add = [news.url, news.source, news.url_encoding,
                news.title, news.keywords, news.author, news.date,
                news.crawler_time, news.summary, news.content
            ];
            crawler_sql.query(news_add_sql, news_add, function(qerr, vals, fields) {
                if (qerr) {
                    console.log(qerr);
                }
            });
        }
    });
}

crawler_schedule_sina.js

var crawler_request = require('request');
var crawler_iconv = require('iconv-lite');
var crawler_cheerio = require('cheerio');
require('date-utils');

// 连接数据库
var crawler_sql = require("./crawler_sql.js");

// 定时执行
var crawler_schedule = require('node-schedule');
var crawler_rule = new crawler_schedule.RecurrenceRule();
// crawler_rule.hour = [0, 12];
// crawler_rule.minute = 5;
crawler_rule.second = 0;
crawler_schedule.scheduleJob(crawler_rule, function() {
    crawler();
});

// 定时爬取网页首页
function request(url, callback) {
    var options = {
        url: url,
        encoding: null,
        headers: {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36'
        },
        timeout: 10000
    }
    crawler_request(options, callback);
};

var crawler_url = 'https://news.sina.com.cn/';

function crawler() {
    request(crawler_url, function(err, res, body) {
        // 网页解析
        try {
            // 编码转换
            var url_encoding = 'UTF-8';
            var url_html = crawler_iconv.decode(body, url_encoding);
            //解析网页
            var $ = crawler_cheerio.load(url_html, { decodeEntities: true });
        } catch (e) {
            console.log('页面解码错误:' + e);
        }
        // 判断网页是否存在超链接
        var url_hrefs;
        try {
            url_hrefs = eval("$('a')");
        } catch (e) {
            console.log('页面不存在超链接' + e);
        }
        // 遍历网页中所有超链接
        url_hrefs.each(function(i, e) {
            // 获取新闻
            var news_url = "";
            try {
                var url_href = "";
                url_href = $(e).attr("href");
                if (typeof(url_href) == "undefined") {
                    return true;
                }
                if (url_href.toLowerCase().indexOf('http://') >= 0 || url_href.toLowerCase().indexOf('https://') >= 0) {
                    news_url = url_href;
                } else if (url_href.startsWith('//')) {
                    news_url = 'https:' + url_href;
                } else {
                    news_url = crawler_url.substr(0, crawler_url.lastIndexOf('/') + 1) + url_href;
                }
            } catch (e) {
                console.log('获取新闻页面出错' + e);
            }
            // 检验新闻网页url是否符合url命名格式
            var news_reg = /\/(\d{4})-(\d{2})-(\d{2})\/doc-([a-zA-Z0-9]{15}).shtml/;
            // 如:https://news.sina.com.cn/c/xl/2021-04-29/doc-ikmyaawc2421496.shtml
            if (!news_reg.test(news_url)) {
                console.log('新闻链接不符合格式!');
                return;
            }
            // 爬取新闻页面
            var news_search_sql = 'select url from news where url=?';
            var news_search = [news_url];
            crawler_sql.query(news_search_sql, news_search, function(qerr, vals, fields) {
                if (vals.length > 0) {
                    console.log('该新闻页面已被爬取!')
                } else {
                    crawler_news_url(news_url);
                }
            });
        });
    });
}

// 爬取新闻链接
function crawler_news_url(news_url) {
    request(news_url, function(err, res, body) {
        // 网页解析
        try {
            // 编码转换
            var url_encoding = 'UTF-8';
            var url_html = crawler_iconv.decode(body, url_encoding);
            //解析网页
            var $ = crawler_cheerio.load(url_html, { decodeEntities: true });
        } catch (e) {
            console.log('页面解码错误:' + e);
        }
        // 定义新闻信息json
        var news = {};
        news.crawler_time = (new Date()).toFormat("YYYY-MM-DD HH:MM:SS.SSSS");
        news.url = news_url;
        news.url_encoding = 'UTF-8';
        news.keywords = '';
        news.title = '';
        news.date = new Date();
        news.author = '';
        news.source = '';
        news.summary = '';
        news.content = '';
        // 获取新闻关键词
        try {
            news.keywords = eval("$('meta[name=\"keywords\"]').eq(0).attr(\"content\")");
        } catch (e) {
            console.log('新闻关键词获取错误:' + e);
        }
        // 获取新闻标题
        try {
            news.title = eval("$('title').text()").replace(/[\r\n\s]/g, "");
        } catch (e) {
            console.log('新闻标题获取错误:' + e);
        }
        // 获取新闻时间
        try {
            news.date = eval("$('.date').text()");
            news.date = news.date.replace('年', '-');
            news.date = news.date.replace('月', '-');
            news.date = news.date.replace('日', '');
        } catch (e) {
            console.log('新闻日期获取错误:' + e);
        }
        // 获取新闻作者
        try {
            news.author = eval("$('.show_author').text()").replace("责任编辑:", "");
        } catch (e) {
            console.log('新闻作者获取错误:' + e);
        }
        // 获取新闻来源
        try {
            news.source = eval("$('meta[name=\"mediaid\"]').eq(0).attr(\"content\")");
        } catch (e) {
            console.log('新闻来源获取错误:' + e);
        }
        // 获取新闻摘要
        try {
            news.summary = eval("$('meta[name=\"description\"]').eq(0).attr(\"content\")").replace(/[\r\n\s]/g, "");
            if (news.summary == "") {
                news.summary = eval("$('meta[property=\"og:description\"]').eq(0).attr(\"content\")").replace(/[\r\n\s]/g, "");
            }
        } catch (e) {
            console.log('新闻摘要获取错误:' + e);
        }
        // 获取新闻内容
        try {
            news.content = eval("$('.article').text()").replace(/[\r\n\s]/g, "");
            if (news.content == "") {
                news.content = eval("$('#article_content').text()").replace(/[\r\n\s]/g, "");
            }
        } catch (e) {
            console.log('新闻内容获取错误:' + e);
        }
        console.log(JSON.stringify(news));

        // 写入数据库
        if (news.author == '' || news.author == null) {
            news.author = news.source;
        }
        if (news.content != '' && news.source != '') {
            var news_add_sql = 'INSERT INTO news(url, source, url_encoding, title, keywords, author, date, crawler_time, summary, content) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
            var news_add = [news.url, news.source, news.url_encoding,
                news.title, news.keywords, news.author, news.date,
                news.crawler_time, news.summary, news.content
            ];
            crawler_sql.query(news_add_sql, news_add, function(qerr, vals, fields) {
                if (qerr) {
                    console.log(qerr);
                }
            });
        }
    });
}
node.js新闻爬虫、新闻正文抓取,项目效果图 项目详细介绍请参考博客 :http://blog.csdn.net/kissliux/article/details/19560603 项目源码开源在github:https://github.com/kissliux/rssSpider   项目旨在提供免费的新闻列表和新闻正文服务,目前没有找到合适的服务器。 哪位大神有服务器可以放一个node.js应用程序的 请联系我,跪谢 阅读详情

相关推荐

Node.js爬取新闻数据

使用Node.js8.60编写的爬虫程序,爬取新浪网站NBA新闻数据,保证正确无误,欢迎下载!

node.js实现简单爬虫(一)

写在前面 最近项目上不是很忙,在摸鱼群里看到水友分享爬虫方面的知识,就查些资料,自己摸索着也做了一个简单的爬虫,但其实在node和爬虫方面我还是一个小白,这篇文章主要是想和大家分享一下node和爬虫方面的基本知识,希望对大家有帮助,也想和大家一起交流,一起学习 一个简单的百度新闻爬虫 爬取对象 百度新闻 (http://news.baidu.com) 一. 初始化项目 新建项目目录 mkdir baiduNews 初始化package.json cd baiduNews npm ini

bighead的博客 592

浅谈天线 - - - GNSS/BT/4G/2.4G

全球定位导航系统,最成熟的就是美利坚,我大中华,俄罗斯,还有就是欧洲的一个(太次不谈)所以我们在项目调试的时候,小尺寸的陶瓷天线上一般兼容2个频段,体积大一点的可以兼容三个频段,采用组合的形式 GPS+BD GPS+GLONASS GLONASS+BD 或者是单频段的定位天线陶瓷PATC陶瓷片:陶瓷片面积越大,介电常数越大,其共振频率越高,接收效果越高,这就是为什么都推荐使用大一点的陶瓷天线的原因银层:陶瓷天线表面的银层可以影响天线的共振频率,理想的GNSS陶瓷片频点准确落在1575.42MH

BLACKHOLE6的博客 1万+

Node.js实现网络新闻爬虫及搜索功能(一)

Node.js实现网络新闻爬虫及搜索功能(一)Node.js实现网络新闻爬虫及搜索功能(一)项目要求一、爬虫部分1. 引入相关包2. 建立数据库连接3. 爬取并解析网页首页4. 爬取并解析新闻URL Node.js实现网络新闻爬虫及搜索功能(一) 项目要求 一、爬虫部分         1、完成目标网站的网页分析和爬虫设计。         2、爬取

WORLDLOGIC的博客 1050

01 AUTOSAR CP标准文档阅读指南

01 AUTOSAR CP标准文档阅读指南

汽车软件工程师 | 好奇博主 | 处女座 1134

RK3588 MPP视频编码实战:从环境搭建到高效封装

本文详细介绍了在RK3588平台上利用MPP(Media Process Platform)进行硬件视频编码的完整实战流程。从MPP库的环境搭建、编译安装,到核心编码参数(如码率控制、GOP、图像对齐)的深入解析,并提供了一个可复用的C++编码器类封装方案,帮助开发者快速实现高效的H.264/H.265视频编码,显著降低CPU占用。

weixin_29192211的博客 348

Node实战——搜索框进行模糊查询

一、需求 点击导航栏中的搜索图,出现搜索框,从而进行文章的模糊查询 二、建表 blog表 添加外键: nav表 type表 user表 三、页面及样式 like.ejs: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <...

小葵坤_易安的博客 2411

PaddleOCR实战指南:从环境搭建到自定义模型训练

本文提供了PaddleOCR从环境搭建到自定义模型训练的完整实战指南。详细介绍了使用Anaconda或Docker搭建稳定开发环境、准备与标注数据集、进行文本检测与识别模型训练的核心步骤与参数调优技巧,并分享了数据增强、模型微调及解决实际项目难题的实用方法,帮助开发者高效掌握PaddleOCR应用。

gold的博客 644

Node.js实现网络新闻爬虫及搜索功能(四)

Node.js实现网络新闻爬虫及搜索功能(四)Node.js实现网络新闻爬虫及搜索功能(四)项目要求二、搜索网站部分1. 建立前端网页2. 建立后端路由 Node.js实现网络新闻爬虫及搜索功能(四) 项目要求 一、爬虫部分         1、完成目标网站的网页分析和爬虫设计。         2、爬取不少于100条数据(每条数据包括7个字段,新闻

WORLDLOGIC的博客 646

基于SpringBoot+SpringCloud+Vue前后端分离项目实战 --开篇

如何高效学习Java? 毕业设计项目应该怎么做?入门实战项目应该怎么做? 做Java开发都应该学习哪些框架技术? 我想来跟你聊聊为什么要学习此专栏?我们经常说,看一个事儿千万不要直接陷入细节里,你应该先鸟瞰其全貌,这样能够帮助你从高维度理解问题。同样,当你迷茫想努力没有方向时,最事半功倍的方法是:找人带你! 因为过来人,更懂得如何学、如何做、如何少走弯路! 那今天就给大家带来一门专栏课程,由 天罡gg 和 经海路大白狗 两位实力大牛合力打造的一款专栏,可以让你从0到1快速拥有企业级规范的项目实战经验!

天罡gg的专栏 2万+

第95章 安全工程师:Shell 脚本实现安全扫描、漏洞检测、日志审计

随着网络安全威胁日益复杂,传统的手动安全管理已无法满足现代企业的安全需求。Shell 脚本为安全工程师提供了强大的自动化能力,能够实现 7×24 小时的安全监控、快速漏洞扫描、智能日志分析和实时威胁响应。本章将系统介绍如何使用 Shell 脚本构建完整的安全防护体系,从基线检查到实时监控,帮助你打造自动化的安全运维能力。

猪猪侠 90

Node.js实现网络新闻爬虫及搜索增加功能(二):可视化及查询优化

Node.js实现网络新闻爬虫及搜索增加功能(二):可视化及查询优化Node.js实现网络新闻爬虫及搜索增加功能(二):可视化及查询优化项目要求二、支持分词查询、查询结果排序和分页及网站数据可视化1. 网站数据可视化2. 支持中文分词查询3. 支持查询结果排序4. 支持查询结果分页 Node.js实现网络新闻爬虫及搜索增加功能(二):可视化及查询优化 系列文章查看不到可能是优快云审核原因,可以在我的知乎专栏看到所有文章:https://www.zhihu.com/column/c_137002616099

WORLDLOGIC的博客 395

OPTEE v4.4.0 qemu_v8环境搭建(支持Hafnium)

一、前提条件 二、拉取代码 三、下载工具链 四、修改代码 五、编译 六、运行

AI-安全-功耗 889

Node.js实现网络新闻爬虫及搜索增加功能(一):用户功能

Node.js实现网络新闻爬虫及搜索增加功能(一):用户功能Node.js实现网络新闻爬虫及搜索增加功能(一):用户功能项目要求一、用户注册、登录、修改密码及用户管理、查看用户操作日志1. 数据库2. 添加前端页面路由3. 登录功能实现4. 注册功能实现5. 修改密码功能实现6. 用户管理功能实现 Node.js实现网络新闻爬虫及搜索增加功能(一):用户功能 系列文章查看不到可能是优快云审核原因,可以在我的知乎专栏看到所有文章:https://www.zhihu.com/column/c_13700261

WORLDLOGIC的博客 381

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Node.js 博客实例(十一)文章检索功能

原教程 https://github.com/nswbmw/N-blog/wiki/_pages的第一章,由于版本等的原因,在原教程基础上稍加改动即可实现。        现在我们来给博客增加文章检索功能,即根据关键字模糊查询文章标题,且字母不区分大小写。 首先,我们修改 header.ejs ,在 前添加一行代码: 在 style.css 中添加一行样式: .search{bord

SS 2581

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

node js 中 启动以后自动打开浏览器

新建 openUrl .js // 可以使用exec 来执行系统的默认命令;child_process为内置模块 const {exec} = require("child_process"); //传入url module.exports=function (url) { // 拿到当前系统的参数 switch (process.platform) { //...

wangrong111222的博客 7796

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

用jq实现仿百度搜索框

百度搜索框看似简单,但是涉及到了数据交互,如果能用vue来实现的话会简单很多,现在用jq模仿了一下,写的代码不是一般的多啊! 当然头部要引入jq了html部分 <input type="text" id="txt" /> <input type="button" id="btn" value="百度一下"/> <div class="box" id="

luckylqh的博客 1万+

Node爬虫,爬取传播客新闻列表

因为它是前后端分离网页。所以需要在Network里面找到请求数据进行爬取 const http=require('http') //http://itcast.cn/newsvideo/newslist.html let url='http://www.itcast.cn/news/json/f1f5ccee-1158-49a6-b7c4-f0bf40d5161a.json' let req=http.request(url,res => { let chunks=[] res.on('da

qq_41960265的博客 301

零基础用node.js写爬虫爬取校园新闻数据并存入mysql

      最近老师布置了个作业,要我们用爬虫爬取新闻并展示出来,因为我不会Python,网上查阅资料发现nodejs做的爬虫也不差,所以就用自己顺手的js来写一个乞丐版的爬虫吧...,我打算爬一下隔壁学校的新闻网页作为案例,网站地址为:http://www.dgut.edu.cn/dgut/ggyw/news_list.shtml 安装环境 1.在本机上运行nodejs需要安装nodejs环...

MT_su的博客 3230

nodejs爬虫,一个简单的爬起新浪,NBA的新闻

只需要 一个http 模块 和一个cheerio的npm包,代码如下,使用了回调函数处理

qq_42217228的博客 686

nodejs实现新闻爬虫

nodejs实现新闻爬虫 作为费德勒的铁杆粉丝,每天早上都会在新浪体育里面的网球频道浏览费德勒新闻。由于只关注费德勒的新闻,所以每次都要在网页中大量的新闻中筛选相关信息,感觉效率好低,所以用node写了一个简单的爬虫程序通过每天定时发送邮件的方式来通知。 这个需求仔细看有3个功能点,信息爬虫,定时发送,邮件通知 信息爬虫 信息爬虫建立在对页面结构的分析,从页面内容中抽取符合我们需要的信息,所以我们在获得网页信息后,需要对dom结构进行分析,获得相关信息,组装成数据。 Axios(https://github

qq_45371853的博客 404

node+vue实现搜索效果

node+vue实现搜索效果

qq_60976312的博客 578

Web 版翻译者资料库

本项目是桌面版《翻译者资料库》的 Web 移植版,基于 Spring Boot 3.3、Thymeleaf、Bootstrap 5.3 与 MySQL 8.0 构建。它面向翻译写作提供资料、词汇、句库、文本工具、对照制作、查找、备份恢复及旧库迁移等功能,完整继承桌面版核心业务规则,支持一键启动与离线访问。

howard2005的专栏 142

V8 机制、手写核心函数与 TypeScript 类型体操

或固定初始化(如数组先定长、对象先给全字段)保持类型与形状稳定;这些都比"换框架"更基础。只能处理纯数据(丢函数、Date、RegExp、循环引用报错)。生产级深拷贝要处理:原始值短路、循环引用、V8(Chrome / Node 的 JS 引擎)不是"解释一行跑一行"那么简单,它用。图:V8 执行流程——解释执行 + 热点优化,优化失败会 Deopt 回退。JS 内存自动管理,但"自动"不等于"不会漏"。是"固定间隔最多执行一次"。手写 Promise 是"懂异步"的试金石。是"停下后才执行最后一次",

qq_38468358的博客 346
下一篇: Node.js实现网络新闻爬虫及搜索功能(四)
WORLDLOGIC
博客等级 码龄8年 3粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值