java 统计阅读量_帮你统计阅读量
又是一个简单的爬虫

我坚信编程既能提供实用性又能带来乐趣,在github平台上有众多令人称奇的小项目。可以说,在github上的小项目中,爬虫技术无疑是其中最为引人入胜的一个领域。
此前我曾尝试从阮大master的《ECMAScript 6 入门》源代码中提取内容并保存至一个单独的文件中。编写完成后发现该作品已将该作品开源至GitHub上,徒劳无获。然而尽管如此但内心深处仍保留着些许技术热情于是萌生了撰写一篇用于统计文章阅读量的小工具的想法。
实际上,在之前的开发中,在网页浏览器上实现了某个功能,并没有达到爬虫级别的复杂性。这个程序仅包含四行代码片段。作为网页浏览器运行的程序存在一些局限性——例如它仅能获取自身相关信息,并且必须进行身份认证流程。或许从中可以看出一些道理。
统计访问量的几种方法:
浏览其他人的博客可以看到,很多个人的博客首页都安装了这样一套用于追踪流量的小程序界面。
像我这样的

高级一点的:

包括cnzz站长统计,
其原理相同,在访客到来之时(因为包含了来自统计网站的资源)在请求过程中(统计网站完成计数加一),然而地来说(这会导致总访问量上升),页面刷新或翻页时(从而进一步增加了总次数),因此总次数并不等同于阅读次数。
知识点
promise的应用
http模块发起请求
cheerio可选
正则表达式的应用
步骤
了解博客园的url结构。
这一操作相对简单。通过访问自己的博客网站即可观察到,在执行页面翻转操作时(即进行页面导航),会修改使用的查询参数。因此,在发送请求的过程中(即发起网络请求),我们采用动态修改查询参数的方式来统计每一页的阅读次数。
先统计一页的总阅读量
为了获取目标URL的HTML内容,我们会使用HTTP模块向其发送请求.在获取到HTML内容之后,通过应用正则表达式来提取所需信息
var http=require('http'),
root='http://www.cnblogs.com/imgss/';
http.get(root +'?page=1', (res) => {
var status = res.statusCode;
var html = '';
if(status == "200") {
res.on('data', (data) => {
html += data;
});
res.on('end', () => {
var $ = cheerio.load(html);
countStr = $('.postDesc').text();
console.log(countStr);
console.log('-----------------------------------------------')
var re = /阅读(\d+)/g;
if(!countStr) {
return false;
}
while(true) {
var match = re.exec(countStr); //匹配阅读量数据
if(match)
total += +match[1];//将匹配到的数据加到total里面
else
break;
}
console.log('page1的阅读量是', total);
})
}
})
其中, countStr = $('postDesc').text();这部分代码用于先通过Cheerio筛选HTML元素,并提取所有.postDesc类元素中的文本内容。接着, 使用正则表达式进一步处理这些文本数据以计算用户的阅读量数值。
在处理过程中,采用正则表达式匹配HTML内容也是有效的。
只要摘要部分不包含与"阅读"相关的内容即可
3 用promise管理并发请求。
首先,我们把上面写的代码封装成一个模块。以便后面调用:
var cheerio = require('cheerio'),
http = require('http');
module.exports = function(root, page) {//该函数需接收两个必要参数:
其中一个为root,代表用于获取资源的根目录路径;
另一个为page,属于number类型,用数字标识请求的第一页.}
return new Promise(function(resolve, reject) {//返回一个promise实例。
var total = 0;
http.get(root + /default.html?page=${page}, (res) => {
var status = res.statusCode;
var html = '';
if(status == "200") {
res.on('data', (data) => {
html += data;
});
res.on('end', () => {
if(!/class="day"/.test(html)) {
console.log(页面${page}没有内容);
resolve(0);
return;
}
var $ = cheerio.load(html);
countStr = $('.postDesc').text();
var re = /阅读/g;
if(!countStr) {
resolve(0);//页面没有数据时,返回0
}
while(true) {
var match = re.exec(html); //匹配阅读量数据
if(match)
total += +match[1];//对当前页面的阅读量求和
else
break;
}
console.log(page${page}的阅读量是, total);
resolve(total);
})
}
})
})
}
说明
var onepage = require('./onepage');//引入上面的模块;
var promiseArr = [],
host = 'http://www.cnblogs.com/';
host将被赋值为process.argv[2](或无值时设置为'imgss')加上'/';//该脚本可接收来自命令行输入的参数;例如node index artech
for(let i = 1; i < 10; i++) {
promiseArr.push(onepage(host, i));//将promise实例放到一个数组里。
}
promises = Promise.all(promiseArr); promises.then((data) => { // data 是存放 reslove() 返回值的数组。})
let sum = 0;
for(d of data) {
sum += d;
}
console.log(sum);
})
Promise.all 方法类似于一个控制点的作用,在 promiseArr 中的实例依次形成一个序列。当这些实例都被成功解决时,在 Promise.all 就会被认为是完成任务的状态。随后会触发后面的 then 方法。
4-19更新
上面的方法的缺陷在于:
没有控制并发,把i写成20,就会同时发起20个请求
没有自动结束的功能,就是即使后面的页面是空的,也会继续请求。
改进方法是用异步函数:像下面这样:
var onepage = require('./onepage');
var promiseArr = [],
host = 'http://www.cnblogs.com/';
host += process.argv[2] ? process.argv[2] : 'imgss' + '/';
let i=1,sum=0;
(async function getAll(){
while(true){
let num= await onepage(host , i++);
if(num){
sum += num;
}else{
break;
}
}
console.log('总阅读量:',sum);
})();
效果:

ps:很高兴自己有一篇博客破千了😆
promise讲解;
