[译]Node Crawler:强大的Node开源爬虫
自从Node横空出世后,很快有人就用它来开发爬虫,网上也常见Node爬虫教程。然而,很难看到一个通用的、功能丰富的爬虫开源项目,到Github上找了一下找到这个,算是目前能找到的最好的了侍山友。
这里将它的文档翻译一下,期待更多的实用案例。
目标打造成Node社区最强大和流行的爬虫/内容抽取工具库,且支持生产环境。
特性:
更新日志:
当你在流量网站时,使用 rateLimit 控制间隔时间。
你可以将这些配置发给唯颂 Crawler() 构造器,让它们成为全局配置,或者自定义 queue() 的请求已覆盖全局配置。
这个配置列表在mikeal的 request项目配置 的基础上做了扩展,并且会直接发送给 request() 方法。
基本请求配置项:
回调:
计划任务选项:
重试选项:
服务端DOM配置:
字符集编码:
缓存:
其它:
当一个任务被加到计划时触发.
当limiter改变时触发.
当爬虫准备好发送请求时触发.
如果你想在发出请求之前的最后阶段改变配置,可以监听这个事件。
当队列为空时触发。
将任务加入队列并等待执行。
队列数量,该属性为只读。
使用limiter控制爬取频率。所有提交到limiter的任务都需要遵守 rateLimit 和 maxConnections 的限制。 rateLimit 是两个任务之间的最小间隔, maxConnections 是最大的并发数。limiters之间是互相独立的。一个通常的用例是为不同的代理设置不同的limiter。另外值得一提的是,当 rateLimit 设置为非0的值时, maxConnections 的值将被强制为1.
爬虫默认使用 Cheerio ,并将 JSDOM 作为可选的替代。JSDOM更稳定,如果你想使用JSDOM,你需要引入该依赖 require('jsdom') ,并配置爬虫。
这些解析配置从 htmlparser2 里继承而来。你可以使用所有可用的配置。默认的配置为:
需要所老槐有的配置项和它们的效果,查看 这里 以及
htmlparser2的配置项 。 来源
要使用JSDOM,你需要先在项目目录下 npm install jsdom ,然后配置爬虫。
爬虫使用本地的httpbin来测试。你可以从PyPI安装httpbin并将其作为WSGI应用来允许。比如,使用Gunicorn:
在安装 Docker 之后, 你可以执行:
在node中如何实现http小爬虫
//HTTP小爬虫 2 //×××××类似 $.AJAX×××××× 3 4 5 var http = require('http'); //加载http模块 6 7 var cheerio = require('cheerio');//加载第三方孝碰模块 cheerio 类似JQuery 8 9 /败胡/ 安装方法 npm install cheerio10 11 12 function printCourseInfo(courseData) {//打印函数 传入获取数据13 courseData.forEach(function(item) {//循环打印14 var chapterTitle = item.chapterTitle;15 16 console.log(chapterTitle + '\n');17 18 item.videos.forEach(function(video) {19 console.log('[' + video.id + ']' + video.title + '\n');20 })21 })22 }23 24 25 function fliterChapters(html) {//数据筛选函数26 27 var $ = cheerio.load(html);28 29 var chapters = $('.chapter')//获取元素30 31 32 //目标数据结构33 /* [{34 capterTitle:'',35 videos:'',36 id:''37 }]*/38 39 var courseData = [];//存放数组40 41 42 chapters.each(function(item) {43 var chapters = $(this);44 45 var chapterTitle = chapters.find('strong').text();46 47 48 var videos = chapters.find('.video').children('li');49 50 var chapterData = {51 chapterTitle: chapterTitle,52 videos: []53 }54 55 videos.each(function(item) {56 var video = $(this).find('.J-media-item');57 var videoTitle = video.text();58 var id = video.attr('href').split('video/')[1]59 60 61 chapterData.videos.push({62 title: videoTitle,63 id: id64 })65 })66 67 68 courseData.push(chapterData);69 })70 71 return courseData//数据拼接完成并返回72 73 }74 75 //目标url76 var url = '';//慕课网77 78 79 80 //使用get方法81 http.get(url, function(res) {//get方法爬取代码82 var html = '';83 84 res.on('data', function(data) {//获取数据事件85 html += data;86 })87 88 res.on('end'察慎拦, function() {//获取结束事件89 var courseData = fliterChapters(html);90 91 printCourseInfo(courseData);92 })93 94 }).on('error', function() {95 console.log('获取错误!');//报错96 })
2018-10-11 nodejs设置延时后再执行下一步操作--ES7 async/await version of setTimeout
这样我们就把原来setTimeout函数的第一个扰好参数(回调函数)解放出来了。
我们嫌橘可以延迟500毫秒然后再查询转化缓者铅日志 :
如何用nodejs开发爬虫程序?
安装必要的模块:
Express
基于 Node.js 平台,快速、开放、极简的 web 开发框架。它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用。
Request
简化HTTP请求的处理,支持OAuth的签名请求,很好很强大。
Cheerio
为服务器特别定制的,快速、灵活、实施的jQuery核心实现,像操作dom一样操作抓取文本。
mysql
node下的mysql数据库连接模块,存储抓取数据。
核心逻辑:
app.get('/', function (req, res, next) {
// 用 superagent 去抓取 的内容
superagent.get('')
.end(function (err, sres) {
// 常规的错误处理
if (err) {
return next(err);
}
// sres.text 里面存储着网页的 html 内容,将它传给 cheerio.load 之后
祥铅岩 // 就可以得到一个实现了 jquery 接口的变量,我们习惯性地将它命名为 `$`
// 剩下就都是 jquery 的内容了
var $ = cheerio.load(sres.text);
var items = [];
$('#topic_list .topic_title').each(function (idx, element) {
激或var $element = $(element);
items.push({
title: $element.attr('title'),
href: $element.attr('href'谨御)
});
});
res.send(items);
});
});
demo:
程序员做一个爬虫脚本每天定时给多个女友发微信提醒,女友:滚
很多女孩子都认为程序猿太过老实,一点都不懂得浪漫,但事实是程序猿浪漫起来真没别的男生的指拆事
如果一个女生每天早上醒来,都能收到男朋友发来的暖心问候,会不会觉得一天心情都美美的呢?就和下图一样:
其实这张图就是程序员用Node + EJS写的一个爬虫脚本—— wechatBot
创建者通过使用到superagent和cheerio组合来实现爬虫,从而获取指定网页的所有DOM,天气预报等讯息
然后,通过EJS模版引擎生成HTML,最后通过node-schedule这个定时任务发生器腔逗辩定时,node-schedule可以定时每个月、每个礼拜,甚至是每天具体什么时候执行任务。
是不是觉得有点意思呢?
于是,有开发者看到这个项目后灵感乍现,心想为什么不用伍缺Python实现呢?于是就有了第二个项目—— EverydayWechat
这个项目就更厉害了,这名程序员觉得有些优(作)秀(死)的人表示女朋友不止一个,于是添加了一个多人信息的功能。可以定时每天给多个“女友”发暖心话
该项目用到的库如下:
itchat - 微信个人号接口
requests - 网络请求库
beautifulsoup4 - 解析网页
APScheduler - 定时任务
实现的效果如下:
正愁不知道怎么哄小女朋友的赶紧拿去用吧,或者学习一下这两位程序员是如何写的。很多女孩子都认为程序猿太过老实,一点都不懂得浪漫,但事实是程序猿浪漫起来真没别的男生的事
如果一个女生每天早上醒来,都能收到男朋友发来的暖心问候,会不会觉得一天心情都美美的呢?就和下图一样:
其实这张图就是程序员用Node + EJS写的一个爬虫脚本—— wechatBot
创建者通过使用到superagent和cheerio组合来实现爬虫,从而获取指定网页的所有DOM,天气预报等讯息
然后,通过EJS模版引擎生成HTML,最后通过node-schedule这个定时任务发生器定时,node-schedule可以定时每个月、每个礼拜,甚至是每天具体什么时候执行任务。
是不是觉得有点意思呢?
于是,有开发者看到这个项目后灵感乍现,心想为什么不用Python实现呢?于是就有了第二个项目—— EverydayWechat
这个项目就更厉害了,这名程序员觉得有些优(作)秀(死)的人表示女朋友不止一个,于是添加了一个多人信息的功能。可以定时每天给多个“女友”发暖心话
该项目用到的库如下:
itchat - 微信个人号接口
requests - 网络请求库
beautifulsoup4 - 解析网页
APScheduler - 定时任务
实现的效果如下:
正愁不知道怎么哄小女朋友的赶紧拿去用吧,或者学习一下这两位程序员是如何写的。
如何使用nodejs做爬虫程序
.
var request = require('request');
var cheerio = require('cheerio');
var URL = require('url-parse');
var START_URL = "";
var SEARCH_WORD = "stemming";
var MAX_PAGES_TO_VISIT = 10;
var pagesVisited = {};
var numPagesVisited = 0;
var pagesToVisit = [];
var url = new URL(START_URL);
var baseUrl = url.protocol + "//" + url.hostname;
pagesToVisit.push(START_URL);
crawl();
function crawl() {
if(numPagesVisited = MAX_PAGES_TO_VISIT) {
console.log("Reached max limit of number of pages to visit.");
return;
}
var nextPage = pagesToVisit.pop();
if (nextPage in pagesVisited) {
// We've already visited this page, so repeat the crawl
crawl();
} else {
// New page we haven't visited
visitPage(nextPage, crawl);
}
}
function visitPage(url, callback) {
// Add page to our set
pagesVisited[url] = true;
numPagesVisited++;
// Make the request
兆历 console.log("Visiting page " + url);
念猜带request(url, function(error, response, body) {
// Check status code (200 is HTTP OK)
console.log("Status code: " + response.statusCode);
if(response.statusCode !== 200) {
callback();
return;
}
// Parse the document body
var $ = cheerio.load(body);
var isWordFound = searchForWord($, SEARCH_WORD);
if(isWordFound) {
console.log('Word ' + SEARCH_WORD + ' found at page ' + url);
} else {
collectInternalLinks($);
// In this short program, our callback is just calling crawl()
仔芦 callback();
}
});
}
function searchForWord($, word) {
var bodyText = $('html body').text().toLowerCase();
return(bodyText.indexOf(word.toLowerCase()) !== -1);
}
function collectInternalLinks($) {
var relativeLinks = $("a[href^='/']");
console.log("Found " + relativeLinks.length + " relative links on page");
relativeLinks.each(function() {
pagesToVisit.push(baseUrl + $(this).attr('href'));
});
}