By jmoses
我最近一直在使用nodejs,我跟我的小伙伴们一直在讨论nodejs是否会最终取代Ruby。我认为评价一门语言的是否流行最重要的指标就是使用这门语言和框架开始新的项目的数量。
我认为一张基于gems的发布项目数量的图表可以很好的解决我的问题。rubygems首页上的就有最新的流行数据显示,但是我对最近的一些数据非常地感兴趣。我认为如果开发者向gems(不同版本)贡献的代码缓慢下降,那么这就表明了这门语言的就不怎么流行了。
拿数据说话
在简单的搜索之后,我无法找到适合的数据去做成一张图表。不过我抓取了一些网站并发现一些有意思的数据。我使用的是nodejs cheerio库。gem的可执行文件给了我们一张清单,它告诉我们都有谁在跑gem。幸运的是每一个gem的主页都是一个很漂亮的地址(url),比如:Rails的主页是:http://rubygems.org/gems/rails
下面是我抓取用的源代码:
var request = require('request'), cheerio = require('cheerio'), bytes = require('bytes'), sys = require('sys'), fs = require('fs'), exec = require('child_process').exec; console.log('program begin: ' + new Date()); fs.openSync('out.csv', 'w'); exec("gem list --remote", { maxBuffer: 20000*1024 }, processGems); function processGems(error, stdout, stderr){ var gems = stdout.split("\n"); console.info('total gems parsed: ' + gems.length); gems.forEach(function(gem){ gem = gem.substring(0, gem.indexOf(' ')); console.info('crawling gem: ' + gem); request({ uri: 'https://rubygems.org/gems/' + gem, }, getContent); }); } function parseSize(size){ size = size.replace(' ', ''); size = size.replace(/\)|\(/g, ''); size = size.toLowerCase(); try{ size = bytes(size); } catch(e){ console.error('unable to parse :' + size); } return size; } function escape(s){ if (s.indexOf('"') != -1) { s = s.replace(/"/g, '""'); } if (s.match(/"|,/)) { s = '"' + s + '"'; } return s; } function getContent(error, response, body){ if (error && response.statusCode != 200) { console.error(error); console.error(response); return; } console.info(response.request.href + ' complete, status: ' + response.statusCode); var $ = cheerio.load(body), gem = $('div.title h2 a').text(), latest = $('div.versions ol li').last(), version = $(latest).children('a').text(), date = $(latest).children('small').text(), size = $(latest).children('span.size').text(), line; line = escape(gem) + ',' + escape(version) + ',' + escape(date) + ',' + parseSize(size) + '\n'; fs.appendFile('out.csv', line); }
整理数据
结果文件有2.7Mb,可以在这里下载,这不是可以做成图表的数据源。我希望我的图表y轴显示当天发布程序的数量,x轴显示发布日期。下面的一段nodejs可以整理之前的csv(数据)文件成我想要的格式。
var __ = require('lodash'), moment = require('moment'), csv = require('csv'), fs = require('fs'); fs.openSync('releasedate.csv', 'w'); csv() .from.path(__dirname+'/gems.csv', { delimiter: ',', escape: '"' }) .to.array( function(data){ var csv = ''; var grouped = __.groupBy(data, function(gem) { return gem[2]; }); var array = [] for(var gem in grouped) { array.push({ date: escape(gem), unixtime: moment(gem, 'MMM D, YYYY').valueOf(), released: grouped[gem].length }); } arraySorted = __.sortBy(array, 'unixtime'); arraySorted.forEach(function(gem){ csv += gem.date + ',' + gem.released + '\n'; }); fs.appendFile('releasedate.csv', csv); } ); function escape(s){ if (s.indexOf('"') != -1) { s = s.replace(/"/g, '""'); } if (s.match(/"|,/)) { s = '"' + s + '"'; } return s; }
用R绘制图表
非常完美。现在开始绘图了。我刚开始想用Excel,但是我发现我只能在一张图上面创建255个点。这对于65K的数据文件来说是远远不够的,所以我最终使用了R。下面的两行代码解释了我为什么喜欢用R的原因:
data<-read.csv('releasedate.csv')
plot(zoo(data$Released,as.Date(data$Date,"%m/%d/%y")),xlab="Release Date",ylab="Releases",main="RubyGems Release Date Trend")
最终结果是我期望看到的一条曲线:
起我初惊呆了。这结果跟我之前预想的不太一样,这张图表显示越来越多的开发者正在使用gems,我从这张图表上面得到了三个结论:
1.Rubby的meetup组织有一大群虔诚的追随者,并且有很强的领导力。
2.网上有非常多的关于Ruby的学习资源。
3.使用Rails创建网站非常非常容易。
写给 Node.js 学徒的 7 个建议