基于node.js的一个小爬虫
程序员文章站
2022-06-30 19:54:29
...
昨天晚上写到一半就停就了,今天接着来.由于也是第一次写,所以跟着网上的一个教程来的.
思路:
- 目标:爬去北京大学某个学院的官网新闻,并将其照片和内容存至本地.
- 首先对其网页进行一定的分析http://www.ss.pku.edu.cn/index.php/newscenter/news/.记录内容及网页格式.(他的每篇文章中都有下一篇文章url的链接).
- 确定的做法是,给定一个初始的url,然后进行一次请求,爬去到下一篇文章的url.用新的url在继续请求,递归调用,直到遍历完所有的新闻网页.
-
通过一个变量i来控制爬去文章的数量.
开始做:
(我的环境是ubuntu+webstorm)
- 首先安装nodejs和js编辑器(当然,这是我之前就有的环境).
- 建立项目
1.进入终端:mkdir spider(创建项目文件夹)
2.cd spider 然后 npm init (初始化项目),会生成一个package.json文件.
3.安装包(first:cheerio包;second:request包)命令用npm install cheerio/request -save
注:为什么要安装cheerio包:
Cheerio 是一个Node.js的库, 它可以从html的片断中构建DOM结构,然后提供像jquery一样的css选择器查询.
- 在spider文件中建立子文件夹:cd spider然后 mkdir data 和mkdir image,用于存放爬取的文本内容和图片资源.
- cd spider 建立 spider.js文件.
- cd spider 创建一个.gitignore文件,用来吸收系统环境产生的文件.
- 文件目录如图:
网页代码分析:
<div class="item-page">
<div class=" article-title">
<a href="/index.php/research/cooperationnews/2114-剑桥大学教授alanbarrell在北大软微学院发表演讲-2"> 剑桥大学教授Alan
Barrell在北大软微学院发表演讲 </a>
</div>
<div class="article-info muted">
<a href="#" title="供稿">供稿:综合办公室 </a>
<a href="#" title="发布于 2014年12月22日"><i class="icon-calendar "></i> 发布于 2014年12月22日</a>
<br style="clear:both;"/>
</div>
<div class="article-content">
<p>`text`</p>
<p style="text-align: center;"><img src="/images/images/07_news/02_news/2014.12.22.jpg" alt="2014.12.22"
width="550" height="368"/></p>
<div class="attachmentsContainer">
<div class="attachmentsList" id="attachmentsList_com_content_default_2114"></div>
</div>
</div>
<ul class="pager pagenav">
<li class="previous">
<a href="/index.php/research/cooperationnews/2391-*实践大学陈振贵校长一行参访无锡校区" rel="prev">< 上页</a>
</li>
<li class="next">
<a href="/index.php/research/cooperationnews/2106-互联网联合创始人roberte-kahn成功访问北京大学" rel="next">下页 ></a>
</li>
</ul>
</div>
以上是我从网页源代码中提取出我们需要爬取的内容代码,以方便看.
爬虫重要代码展示:
- 引入所需模块,初始化url,分装一层函数.
var http=require('http');
var fs=require('fs');
var cheerio=require('cheerio');
var request=require('request');
var i=0;
var url='http://www.ss.pku.edu.cn/index.php/newscenter/news/2391';
function fetchPage(x) {
startRequest(x);
}
2.发起请求,获取网页内容(实现startRequest()函数)
function startRequest(x) {
http.get(x, function (res) {
var html = '';
var title = [];
res.setEncoding("utf-8");//防止中文乱码
//监听data事件
res.on('data', function (chunk) {
html += chunk;//??
});
//监听end事件,内容获取完毕,就执行回调函数
res.on('end', function () {
var $ = cheerio.load(html);//解析html
var time = $('.article-info a:first-child').next().text().trim();
//
var news_item = {
title: $('div.article-title a').text().trim(),
Time: time,
link: 'http://www.ss.pku.edu.cn' + $("div.article-title a").attr('href'),
author: $('[title=供稿]').text().trim(),
i: i = i + 1
};
console.log(news_item);
var news_title = $('div.article-title a ').text().trim();
//存储每篇文章的内容及文章标题
savedContent($, news_title);
//存储每篇文章的图片及图片标题
savedImg($, news_title);
//下一篇url
var nextLink = "http://www.ss.pku.edu.cn" + $("li.next a ").attr('href');
var str1 = nextLink.split('-');//去掉url后面的中文
var str = encodeURI(str1[0]);
//通过i控制爬取文章的篇数
if (i <= 30) {
fetchPage(str);
}
}).on('error', function (err) {
console.log(err);
});
});
}
3.实现savecontent函数:保存文章内容到本地
function savedContent($, news_title) {
$(".article-content p").each(function (index, item) {
var x = $(this).text();
var y = x.substring(0, 2).trim();
if (y === '') {
x = x + '\n';
fs.appendFile("./data/" + news_title + '.txt', x, 'utf-8', function (err) {
if (err) {
console.log(err);
}
});
}
});
}
4.实现saveImg函数:保存图片到本地
function savedImg($, news_title) {
$('.article-content img').each(function (index, item) {
var img_title = $(this).parent().next().text().trim();
if (img_title.length > 35 || img_title === '') {
img_title = 'Null';
}
var img_filename = img_title + ".jpg";
var img_src = 'http://www.ss.pku.edu.cn' + $(this).attr('src')
request.head(img_src, function (err, res, body) {
if (err) {
console.log(err);
}
});
request(img_src).pipe(fs.createWriteStream('./image/' + news_title + '---' + img_filename));
});
}
最后fetchPage(url);
此时我们在终端运行:node spider.js
结果:
ok,大功告成,我们可以返回去看data文件夹下和image文件夹下也有了内容.
已上传到的github地址