网页新闻抓取( 网易新闻网为例的主要流程和代码实现(爬虫为例) )
优采云 发布时间: 2022-03-14 00:01网页新闻抓取(
网易新闻网为例的主要流程和代码实现(爬虫为例)
)
新闻爬虫和爬取结果查询网站 build(二)
概括
本章将介绍爬虫的主要流程和代码实现。
爬虫流程如下:
在爬虫中,首先构造一个模仿浏览器的请求,并使用header来防止网站屏蔽爬虫代码。请求函数可以访问指定的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)
}
数据库建表和连接的准备工作
创建表语句(新闻、关键字两个表):
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
);
连接并配置数据库
本项目使用连接池方式连接数据库。
建立数据库连接池的好处:
节省资源和高效的用户访问
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”下。在这个*敏*感*词*页中,需要爬取每条新闻的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('日', '');
}
遇到的问题和解决方法
在抓取网页内容的过程中,遇到了标题乱码的情况。
解决方法如下:
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;
}
存储结果
如下所示: