概要
本节将介绍爬虫的主要流程以及具体介绍三个爬虫的代码实现。
每一个爬虫的大致步骤都是:
1、读取种子页面
2、分析出种子页面里的所有新闻链接
3、爬取所有新闻链接的内容
4、分析新闻页面内容,解析出结构化数据
5、将结构化数据存储到数据库中
在每个爬虫中,都引用了以下几个包:
其中pg.js是之前介绍的postgreSQL的连接池,iconv-lite是用来编码转换,request和cheerio在前面一章进行了介绍。
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 url
var options = {
url: url,
encoding: null,
headers: headers,
timeout: 10000
}
myRequest(options, callback)
}
雪球网
网页链接: 雪球网首页
分析种子页面
下图是雪球网种子界面的图,可以看出来,在雪球网热帖中,每一个新闻在div class="AnonymousHome_home__timeline__item_3vU"下面,在该种子界面,需要爬取的是每一个新闻的url以及下面的其对应的时间。
爬取种子页面,并且获取其中每一个新闻对应的链接以及时间,其对应的代码如下:
其中seedurl_news对应的页面上所有新闻,使用seedurl_news.each()对每一块新闻获取其具体url和发布时间,并且对url和时间进行了处理。
并且检查了url是否在数据库中已经存储过了。(前一节介绍过)
var seedURL = 'https://xueqiu.com/';
request(seedURL, function (err, res, body) {
var html = myIconv.decode(body, myEncoding);
var $ = myCheerio.load(html, {
decodeEntities: true });
try {
seedurl_news = $('.AnonymousHome_home__timeline__item_3vU');
} catch (e) {
console.log('url列表所处的html块识别出错:' + e) };
seedurl_news.each(function(){
try {
var url = seedURL.substr(0, seedURL.lastIndexOf('/')) + $(this).find('.AnonymousHome_a__placeholder_3RZ').attr("href");
//时间
time = $(this).find('.AnonymousHome_auchor_1RR').children().last().text();
time = time.split(/\s+/)[0];
time = '2020-' + time;
console.log("time " + time)
}catch (e) {
console.log('识别种子页面中的新闻链接出错:' + e)
}
var fetch = {
};
fetch.url = url;
fetch.source_name = source_name;
fetch.source_encoding = myEncoding; //编码
fetch.publish_date = time;
// not try to crawl the repeat page
var fetch_url_Sql = 'select url from fetches where url= $1';
var fetch_url_Sql_Params = [url];
pgsql.query(fetch_url_Sql, fetch_url_Sql_Params, function(err, result) {
if (err) {
console.log(err)
} else {
// a new page
if(result.rows[0] != null) {
console.log(result.rows[0]);
console.log("URL " + url + " repeat");
} else {
getDetail(fetch, url);
}
}
});
});
});
分析新闻页面
在获取了新闻详情页面后,调用getDetail函数,爬取所需要的内容。
以该页面为例:新闻界面
爬取的信息包括:新闻标题、作者、具体内容。
新闻详情页如图:
在获取新闻内容时,是在类名为article__bd__detail下的除了第一段的所有内容,因此对类下所有内容进行遍历,追加到content中。
具体对应的代码如下,其中fetch中存储的是在之前爬取信息的结构化存储。在文中注释部分代码是将爬取内容存到本地json文件。
var author_format = "$('.name').text()";
var title_format = "$('.article__bd__title').text()";
function getDetail(fetch, url) {
//request module fetching url
request(url, function(err, res, body) {
var html_news = myIconv.decode(body, myEncoding);
var $ = myCheerio.load(html_news, {
decodeEntities: