新闻网站爬虫及结果查询

(一)nodejs+express搭建服务器

1.安装node.js

Node.js 安装包及源码下载地址为:https://nodejs.org/en/download/

2.全局安装express-generator

npm install express --save -g
npm install express-generator --save -g

3.初始化项目

express project1 //构建这个应用的目录结构
cd project1
npm install //安装依赖
npm start //启动项目

项目目录结构:

bin: 启动目录 里面包含了一个启动文件 www ,默认监听端口是3000

node_modules: 所有安装的依赖模块都在这个文件夹里面

public: 所有的前端静态资源 css image js

routes: 放的是路由文件

路由主要定义 url 和资源的映射关系 ( 一一对应关系 )

主要用来接收前端发送的请求响应数据给前端

views: 主要放置 ejs 后端模板文件

app.js: 入口文件(主文件) 总路由 (其他的路由要由它来分配)

package.json: 描述文件,最重要的是依赖的模板列表 dependencies

依赖列表里面的所有模板可以通过 npm i 一次性全部安装

4.添加依赖

在package.json文件里添加需要的依赖,如:request,Cheerio,pg等,再次安装依赖。

(二)连接数据库

1.连接池创建

在代码中引入pg模块,并编写数据库配置:

var pg = require('pg');
var config = {  user:"postgres",database:"spider",password:"postgres",port:5432,// 扩展属性max:20, // 连接池最大连接数idleTimeoutMillis:3000, // 连接最大空闲时间 3s
}
var pool = new pg.Pool(config);

2.编写操作数据库的函数

有参数和无参数,该函数实现连接数据库并执行SQL语句

var query = function(sql, sqlparam, callback) {pool.connect(function(err, conn, done) {if (err) {console.log(err)callback(err, null, null);} else {conn.query(sql, sqlparam, function(err, result) {//conn.release(); //释放连接 done();callback(err, result); //事件驱动回调 });}});
};
var query_noparam = function(sql, callback) {pool.connect(function(err, conn, done) {if (err) {callback(err, null, null);} else {conn.query(sql, function(err, result) {conn.release(); //释放连接 callback(err, result); //事件驱动回调 });}});
};

3.新闻表和关键词表的设计

新闻表:
id_news是每个新闻的id,设为UNIQUE属性唯一标识新闻数据
url是新闻链接
source_name是新闻的来源网站名
source_encoding是新闻的编码方式
title是新闻标题
publish_date是新闻的发表日期
content是新闻内容
关键词表:
id_word是关键词id,唯一标识该关键词
id_news是该关键词所属的新闻id,用于两表的连接
word是关键词

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 splitwords (id_word serial UNIQUE, id_news int, //两表的连接word varchar(50) DEFAULT NULL
);

(三)爬虫

爬取了三个网站:雪球网、中国财经网、网易新闻网。
每一个爬虫的大致步骤都是:
1、读取种子页面
2、分析出种子页面里的所有新闻链接,并爬取内容,解析成结构化数据
3、将结构化数据存储到数据库中
下面以中国财经网为例

1.读取种子页面

引入需要的包

var pgsql = require('../pg.js');
var myIconv = require('iconv-lite');
var myRequest = require('request');
var myCheerio = require('cheerio');

构造模仿浏览器的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) {//request module fetching urlvar options = {url: url,encoding: null,headers: headers,timeout: 10000}myRequest(options, callback)
}

爬取种子页面,并且获取其中每一个新闻对应的链接,其对应的代码如下:
其中seedurl_news对应的页面上所有新闻,使用seedurl_news.each()对每一块新闻获取其具体url,并且检查了url是否在数据库中已经存储过了,避免重复插入数据

var seedURL = 'http://www.chinanews.com/finance/';
request(seedURL, function(err, res, body) { //读取种子页面//用iconv转换编码var html = myIconv.decode(body, myEncoding);//console.log(html);//准备用cheerio解析htmlvar $ = myCheerio.load(html, { decodeEntities: true });var seedurl_news;try {seedurl_news = $('a');//console.log(seedurl_news);} catch (e) { console.log('url列表所处的html块识别出错:' + e) }seedurl_news.each(function(){try {var href = "";href = $(this).attr('href');}catch(e) {console.log('get the seed url err' + e);}//if (href.startsWith('//')) href = 'http:' + href;if (!url_reg.test(href)) {console.log(href + " not match the url_reg");return;}href = String(href);if (href.indexOf("//www.chinanews.com/cj") != 0) {// console.log(href + " not match the right url");return ;}href = 'http:' + href;console.log("crawler " + href);// not try to crawl the repeat pagevar fetch_url_Sql = 'select url from news where url= $1';var fetch_url_Sql_Params = [href];pgsql.query(fetch_url_Sql, fetch_url_Sql_Params, function(err, result) {if (err) {console.log(err)} else { // a new pageif(result) {console.log("URL " + href + " repeat");} else {newsGet(href);}}});})
});

2.爬取新闻链接内容

在获取了新闻详情页面后,调用newsGet函数,爬取所需要的内容。
爬取的信息包括:新闻标题、内容、来源、发表时间,并对内容、发表时间等内容的格式进行了处理

request(myURL, function(err, res, body) { //读取新闻页面try {var html_news = myIconv.decode(body, myEncoding); //用iconv转换编码//console.log(html_news);//准备用cheerio解析html_newsvar $ = myCheerio.load(html_news, { decodeEntities: true });myhtml = html_news;} catch (e) {    console.log('读新闻页面并转码出错:' + e);};console.log("转码读取成功:" + myURL);//动态执行format字符串,构建json对象准备写入文件或数据库var fetch = {};fetch.title = "";fetch.content = "";fetch.publish_date = (new Date()).toFormat("YYYY-MM-DD");//fetch.html = myhtml;fetch.url = myURL;fetch.source_name = source_name;fetch.source_encoding = myEncoding; //编码if (title_format == "") fetch.title = ""else fetch.title = eval(title_format); //标题if (date_format != "") fetch.publish_date = eval(date_format); //$('.article-meta').children().eq(1).text(); //刊登日期   console.log(fetch.publish_date);fetch.publish_date = fetch.publish_date.split(" ")[0];console.log('date: ' + fetch.publish_date);fetch.publish_date = fetch.publish_date.replace('年', '-')fetch.publish_date = fetch.publish_date.replace('月', '-')fetch.publish_date = fetch.publish_date.replace('日', '')fetch.publish_date = new Date(fetch.publish_date).toFormat("YYYY-MM-DD");if (content_format == "") fetch.content = "";else fetch.content = eval(content_format).replace('\n', "").replace(" ", ""); //内容,是否要去掉作者信息自行决定//console.log(fetch.content);}});

3.存储结构化数据

执行SQL语句把新闻数据插入news表

// save the result in postgresqlvar fetchAddSql = 'INSERT INTO news (url, source_name, source_encoding, title, publish_date, content)' + 'VALUES ($1, $2,$3,$4,$5, $6)';var fetchAddSql_Params = [fetch.url, fetch.source, fetch.source_encoding,fetch.title, fetch.publish_date, fetch.content];//执行sql,数据库中fetch表里的url属性是unique的,不会把重复的url内容写入数据库pgsql.query(fetchAddSql, fetchAddSql_Params, function(err, result) {if(err) {console.log(err);}});

4.关键词表数据的插入

利用nodejieba.extract()方法,提取新闻内容中的关键词,并剔除停用词。

var fetchAddSql = 'select id_news, content from news';
pgsql.query_noparam(fetchAddSql, function(err, result) {for(var i = 0; i < result.rows.length; i++) {var words = nodejieba.extract(result.rows[i].content,30);var id_news = result.rows[i].id_news;var insert_word_Sql;var insert_word_Params;for(var j = 0; j < words.length; j++) {if(!stop_words.has(words[j].word)) {insert_word_Sql = 'insert into splitwords(id_news, word)' + ' VALUES ($1, $2)';insert_word_Params = [id_news, words[j].word];  // console.log(words[j]);pgsql.query(insert_word_Sql, insert_word_Params, function(err, result) {if(err) {console.log(err);}});}}}});

数据库显示:
news表:

关键词表:

(四)结果查询网站的搭建

1.用pgsql查询已爬取的数据(按时间顺序)

构建sql查询语句并且调用pgsql.query_noparam进行查询即可,且对标题、关键词、源网站的查询都是按照时间降序排列,最新的新闻排在旧的新闻前面呈现。

router.get('/get_title', function (req, res) {res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' }); // console.log(req.query.title);var fetchSql = "select url,source_name,title,publish_date " +"from news where title like '%" + req.query.title + "%' Order By publish_date desc" ;pgsql.query_noparam(fetchSql, function(err, result, fields) {// console.log(result.rows);res.end(JSON.stringify(result.rows));// console.log(res);});
});

2、用网页发送请求到后端查询

前端采用文本框样式,获取输入的查询词,并提交给后端
每个文本框及按钮绑定不同的id,便于访问不同的路由

<title>新闻信息检索</title>
<h1>输入新闻标题并搜索:</h1><input type="text" name="title" id="title_text">
<input type="button" value="搜索" id="title_button"><h1>输入源网站名并搜索:</h1><input type="text" name="source_name" id="source_name_text">
<input type="button" value="搜索" id="source_name_button"><h1>输入新闻关键词并搜索:</h1><input type="text" name="keyword" id="keyword_text">
<input type="button" value="搜索" id="keyword_button">

网页显示:

3.用表格显示查询结果

采用现有的css框架bootstrapTable呈现查询结果

$('#title_table').bootstrapTable({url:params,method:'GET',pagination:true,sidePagination:'client',pageSize:5,striped : true,sortable : true,sortOrder:"asc",showRefresh:true,search:true,showToggle: true,toolbar: '#toolbar',showColumns : true,columns:[{field :'url',title : 'url',sortable : true}, {field:'title',title:'title'}, {field:'source_name',title:'source_name',sortable : true},{field:'publish_date',title:'publish_date',sortable : true}]})

表格显示:

4.关键词的时间热度分析

从数据库的新闻信息中统计每天包括该关键词的新闻数量,按照时间顺序降序排列

router.get('/order_keyword', function (req, res) {res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' }); // console.log(req.query.keyword);var fetchSql = "SELECT publish_date,count(*) as Num FROM news WHERE content like '%" + req.query.keyword + "%' group by publish_date order by publish_date desc;";pgsql.query_noparam(fetchSql, function(err, result, fields) {// console.log(result.rows);res.end(JSON.stringify(result));// console.log(res);});
});

结果展示:

图表形式更加直观:
引入echarts.js库,绘制动态柱状图

var myChart = echarts.init(document.getElementById('chart'));// 指定图表的配置项和数据var option = {title: {text: '关键词时间热度图'},tooltip: {},legend: {data:['新闻数量']},xAxis: {data: dates},yAxis: {},series: [{name: '新闻数量',type: 'bar',data: nums}]};// 使用刚指定的配置项和数据显示图表。myChart.setOption(option);});

5.网站展示

为了美化前端界面,加入了背景图片以及鼠标跟随特效

新闻网站爬虫及结果查询相关推荐

  1. 新闻网站爬虫及一个简单爬取结果的查询网站的实现

    1.新闻网站爬虫的实现 以新浪新闻为例,新闻的html按照下图的格式编码 'use strict'; var fs = require('fs'); var myRequest = require(' ...

  2. python小爬虫之天气查询

    python小爬虫之天气查询 刚开始研究爬虫,这个小程序通过抓取网页源代码,使用json解析实现了天气的查询. 1.需求分析 该博客实现了简单的天气查询功能,输入城市名称后可以查询出该城市的天气情况. ...

  3. b站爬虫,用于查询主播舰队用户等级构成

    b站爬虫,用于查询主播舰队用户等级构成: 话不多说直接上代码 import urllib.request import re import os import timeclass marine:tot ...

  4. 新闻网站爬虫及爬取结果的查询网站

    实验要求 核心需求: 1.选取3-5个代表性的新闻网站(比如新浪新闻.网易新闻等,或者某个垂直领域权威性的网站比如经济领域的雪球财经.东方财富等,或者体育领域的腾讯体育.虎扑体育等等)建立爬虫,针对不 ...

  5. Python 爬虫实现天气查询(可视化界面版)

    github项目地址:StarMan Python 实现天气查询的程序早已完成,近日开学无课,昨晚心血来潮想做一个较为友好的界面版本,便匆忙行动了起来. 在之前已有的程序的基础上使用Tkinter 模 ...

  6. echarts 词云_python Flask+爬虫制作股票查询、历史数据、股评词云网页

    自学python的数据分析,爬虫后,花了几天时间看视频学习Flask做了一个简单的股票查询网页.本来还想着加入一些其他功能,比如财务指标分析,舆情分析,最完美的想法是做成一个股票评分系统,输入股票代码 ...

  7. 腾讯、网易、新浪新闻网站爬虫编写记录及评论格式分析

    0 前言 先说说看这篇博客你能知道什么:1 腾讯.网易.新浪不同新闻的地址格式以及评论内容的地址格式(返回数据为json的异步接口):2 一些比较通用的设计方法,对软件设计的菜鸟可能有帮助: 之前也说 ...

  8. [简单的python爬虫实战] ,查询亚马逊产品的关键词排名 [日本站]

    今天回顾了一下定向爬虫的编写,想起以前的工作需求,有感而发写了一个简单的爬虫 爬虫功能: 这个爬虫脚本是根据之前在做亚马逊销售的时候的工作需要,从而编写的代码.用以检查产品的关键词排名,从而判断是否需 ...

  9. 基于Python的新闻网站爬虫及其可视化设计

    这是最近做的一个毕业设计 采用了前后端分离的方法来实现.前端使用VUE来完成,后端使用了基于Python的Django 踩了一些坑,主要有CORS跨域请求的问题.两个不同的端口也属于跨域的情况.还有就 ...

最新文章

  1. 来啦!机器学习画图神器来啦!
  2. Test_data detection-Illumination
  3. GitHub的初次使用记录
  4. LeetCode 1427. 字符串的左右移
  5. 典型海洋环境观测数据产品应用现状及对我国的启示
  6. COJS 1752. [BOI2007]摩基亚Mokia
  7. 为什么 Kubernetes 是微服务发展的必然产物?
  8. 如何以编程方式确定Java中的操作系统?
  9. 英特尔nuc能代替主机吗_拆了拆了!Intel NUC装机!小机箱退烧器啊!主机显示器合体...
  10. 酒柜设计也可以很“特色”
  11. android模拟器访问电脑本机
  12. mac外接显示器 竖屏 黑苹果_mac外接显示器 竖屏 黑苹果_Mac 外接显示器转自定义HiDPI分辨率教程...
  13. 用python的turtle画圆 转角度前进_使用python实现画出一段给定角度的近似圆弧
  14. 【程序人生】2020 年度总结
  15. BEN的IT英语训练营第22天 - IT ABC 20
  16. Android studio 解决运行按钮灰色/禁用状态
  17. IObitUninstaler官网最新下载 中文,绿色版IObitUninstaler下载
  18. STM32 串口3 总是进入接收中断
  19. 模拟产生modbus数据工具
  20. 基于文本服务框架的拼音输入法研究与实现

热门文章

  1. 学习JAVA的随性笔记-权限修饰符
  2. eclipse如何导入jdk包
  3. ImageNet图像库1000个类别名称(中文注释不断更新)
  4. 职场中你是“麦克利兰激励需要理论”中的哪类人
  5. 完美的Windows Server 2008 R2 SP1 模板
  6. 宽度优先搜索python_宽的解释|宽的意思|汉典“宽”字的基本解释
  7. 孤独真的能毁掉一个人吗?
  8. reactos操作系统实现(47)
  9. 设计模式之模板方法模式在kafka DelayedOperation中的应用
  10. LAmbda表达式 C#版