新闻爬虫以及爬取结果查询网站搭建(二)

摘要

本章节将介绍爬虫的主要流程和代码实现。
爬虫流程如下:

  • 读取种子页面
  • 提取种子页面中包含的的新闻链接
  • 爬取新闻链接的内容(标题,发表时间,内容等等)
  • 将爬取后的内容整合成结构化的数据并存储到数据库中

在爬虫中首先构造模仿浏览器的request,通过header来防止网站屏蔽爬虫代码。request函数能够访问指定的url并且设置回调函数来处理得到的html页面。

var 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'
}
function request(url, callback) {
    var options = {
        url: url,
        encoding: null,
        headers: headers,
        timeout: 10000
    }
    myRequest(options, callback)
}

准备工作

数据库建表与连接

建表语句(news、keywords两张表):

CREATE TABLE news (
   id_news serial UNIQUE,
   url text DEFAULT NULL UNIQUE,
   source_name varchar(50) DEFAULT NULL,
   source_encoding varchar(45) DEFAULT NULL,
   title varchar(100) DEFAULT NULL,
   publish_date date DEFAULT CURRENT_TIMESTAMP,
   content text,
  PRIMARY KEY (id_news)
);

CREATE TABLE keywords (
   id_word serial UNIQUE,
   id_news int,
   word varchar(50) DEFAULT NULL
);

连接并配置数据库

本项目采用连接池的方法连接数据库。

建立数据库连接池的好处:

  1. 节约资源
  2. 用户访问高效
  • 首先安装数据库连接模版pg
npm install pg
  • 创建连接池
var pg = require('pg');

var config = {  
    host:"127.0.0.1",
    user:"root",
    database:"spider",
    password:"syz",
    port:5432,
    max:20, // 连接池最大连接数
    idleTimeoutMillis:3000, // 连接最大空闲时间 3s
}

var pool = new pg.Pool(config);

爬取网页(网易新闻、中新网财经频道、雪球网)

网易新闻网为例详细展开说明:网易新闻网

分析种子页面

在这里插入图片描述

从上图我们可以看出,中间新闻的url均在"div class="main_center_news"下面,在该种子页面中,需要爬取每一个新闻的url。具体代码如下:

var source_name = "网易新闻";
var myEncoding = "utf-8";
var seedURL = 'https://news.163.com/';
var seedURL_format = "$('a')";
var title_format = "$('title').text()";
var date_format = "$('html#ne_wrap').attr(\"data\-publishtime\")";//

var pgsql = require('../pg.js');
var Iconv = require('iconv-lite');
var myRequest = require('request');
var myCheerio = require('cheerio');
var url_reg = /\/(\d{2})\/(\d{4})\/(\d{2})\/([A-Z0-9]{16}).html/;
var regExp = /((\d{4}|\d{2})(\-|\/|\.)\d{1,2}\3\d{1,2})|(\d{4}年\d{1,2}月\d{1,2}日)/

var 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'
}

function request(url, callback) {//request module fetching url
    var options = {
        url: url,
        encoding: null,
        headers: headers,
        timeout: 10000
    }
    myRequest(options, callback)
}

request(seedURL, function (err, res, data) {
    var buf = Iconv.encode(data, 'utf-8');
    var html = Iconv.decode(buf, myEncoding);
    var $ = myCheerio.load(html, { decodeEntities: true });
    try {
        seedurl_news = eval(seedURL_format);
    } catch (e) {  };

    seedurl_news.each(function(){
        var myURL = "";
        try {
            var href = "";
                href = $(this).attr("href");
                if (href == undefined) return;
                if (href.toLowerCase().indexOf('https://') >= 0 || href.toLowerCase().indexOf('http://') >= 0) myURL = href;
                else if (href.startsWith('//')) myURL = 'http:' + href; 
                else myURL = seedURL.substr(0, seedURL.lastIndexOf('/') + 1) + href; 
        }catch (e) {
        
        }
        if (!url_reg.test(myURL)) return;
        var news = {};
        news.url = myURL;
        news.source_name = source_name;
        news.source_encoding = myEncoding;
        var news_url_Sql = 'select url from news where url= $1';
        var news_url_Sql_Params = [myURL];
        pgsql.query(news_url_Sql, news_url_Sql_Params, function(err, result) {
            if (err) {
                console.log(err)
            } else {               
                Detail(news, myURL);
            }
        });
    });
});

分析新闻页面

获取新闻页面后,调用Detail函数来爬取新闻标题、作者、发布时间以及具体内容。

function Detail(news, url) {
    request(url, function(err, res, data) {
        var $ = myCheerio.load(data, { decodeEntities: true});
        news.title = "";
        news.content = "";
        news.publish_date = new Date().toLocaleDateString().split('/').join('-');
        if (title_format == "") 
        news.title = ""
        else news.title = eval(title_format); 

        if(!isChinese(news.title[0]) && !isNumber(news.title[0]))
            return  ;
        if (date_format == "") news.publish_date = ""; 
        else news.publish_date = eval(date_format);
        if (news.publish_date) {
            news.publish_date = regExp.exec(news.publish_date)[0];
            news.publish_date = news.publish_date.replace('年', '-');
            news.publish_date = news.publish_date.replace('月', '-');
            news.publish_date = news.publish_date.replace('日', '');
        }

遇到的问题与解决方案

在爬取网页内容的过程中,遇到了title为乱码的情况。
解决方法如下:

  • 通过isChinese和isNumber函数判断title字符串首字符是否为中文字符或者是数字,若都不是则直接返回。
function isChinese(temp){
    var re=/[^\u4E00-\u9FA5]/;
    if (re.test(temp)) return false ;
    return true ;
}

//验证字符串是否是数字
function isNumber(theObj) {
    var reg = /^[0-9]+.?[0-9]*$/;
    if (reg.test(theObj)) {
        return true;
    }
    return false;
}

存储结果

如下图所示:
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值