你應該見過很多對GitHub上等等開源項目進行的分析文章。聽說國外甚至有人靠分析Github上的項目解決了畢業論文……(要是個人畢業論文也能這麼解決就行了XD) 藉助於Google Big Query和來自於GitHub Archive的數據歸檔,對GitHub上的項目進行簡單的數據分析並不困難。下文我將試圖分析2015年GitHub上被收藏(starred)最多的5000個項目,進而求出2015年最受矚目的編程語言排行。javascript
GitHub Archive這個網站經過GitHub的API,按期抓取GitHub的事件數據,並上傳到Google Big Query,供熱心羣衆分析。它在官網上介紹了如何用Google Big Query來分析數據。前端
Google Big Query容許用戶建立項目,上傳數據歸檔,並經過SQL來查詢這些數據。下圖就是GitHub Archive在Big Query上,存儲着2016-02-01這一天數據的項目。java
咱們能夠看到它的schema定義,基本上相似於GitHub事件API返回的數據格式。其中一些重要的字段以下:react
type 事件類型。好比jeresig建立了項目processing-js,那麼這個事件的類型就是CreateEvent。你能夠上GitHub事件相關的文檔裏查到各類事件對應的類型。git
repo.name 項目名,在上面例子中,是jeresig/processing-jsgithub
actor.login 該事件的主人公,在上面例子中,是jeresiggolang
因而咱們小試牛刀,運行下面的Query,查詢jeresig去年一年push的次數:(這裏用TABLE_DATE_RANGE
函數用於匹配從githubarchive:day.events_20150101
到githubarchive:day.evnets_20151231
全部的表)編程
SELECT COUNT(*) FROM TABLE_DATE_RANGE([githubarchive:day.events_], TIMESTAMP('2015-01-01'), TIMESTAMP('2015-12-31')) WHERE type = 'PushEvent' and actor.login = 'jeresig'
得出的結果爲json
稍微複雜點,運行下面的Query,查詢jeresig去年一年內提了Pull Request的項目和各自提的次數:bootstrap
SELECT COUNT(*) AS num, repo.name FROM TABLE_DATE_RANGE([githubarchive:day.events_], TIMESTAMP('2015-01-01'), TIMESTAMP('2015-12-31')) WHERE type = 'PullRequestEvent' and actor.login = 'jeresig' GROUP BY repo.name ORDER BY num DESC
把關注點從人轉向項目,讓咱們迴歸主題,查詢去年一年間最受矚目的那些項目們,並粗略地分析下它們。經過查GitHub的API文檔,咱們知道用戶star一個項目時會觸發一個WatchEvent(對的,就是WatchEvent)。因此咱們能夠遍歷下去年全部的WatchEvent事件,按repo_name進行分組,計算每組的數目,並截取前5000名。寫出來的Query以下:
SELECT COUNT(*) AS star, repo.name FROM TABLE_DATE_RANGE([githubarchive:day.events_], TIMESTAMP('2015-01-01'), TIMESTAMP('2015-12-31')) WHERE type = 'WatchEvent' GROUP BY repo.name ORDER BY star DESC LIMIT 5000
我把Big Query查詢到的數據保存成github-star-2015.csv
,分享到百度網盤上,有須要的人能夠下載:http://pan.baidu.com/s/1dElWKHr
如今,我宣佈,2015年最受矚目的項目前十的名單新鮮出爐啦!(請腦補最應景的BGM)
~/doc head -11 github-star-2015.csv star,repo_name 38318,FreeCodeCamp/FreeCodeCamp 25861,facebook/react-native 25479,apple/swift 24344,sindresorhus/awesome 22917,facebook/react 22093,jlevy/the-art-of-command-line 20401,NARKOZ/hacker-scripts 19736,twbs/bootstrap 17885,google/material-design-lite 17568,airbnb/javascript
初看這份名單,你會發現去年是React年。前十的名單裏,React就佔了兩。你也許會想起,swift在這一年裏開源了(果粉的力量真強大,一樣也是去年搬到GitHub的golang就擠不進前十名~)。仔細分析下各個項目,你會發現,漲star最快的項目有很多是代碼無關的項目。好比第一名FreeCodeCamp,第四名awesome,第六名the-art-of-command-life,第十名airbnb/javascript(airbnb內部的javascript編程規範)等等,都是如此。另外,一個顯著的發現是,前十名中,前端的項目佔了三個,這還不計算半個前端項目的react-native和前端編碼規範的airbnb/javascript。前端項目三分天下有其一,準確來說,已經接近撐起半邊天了。若是說前幾年的GitHub是Ruby開發者的GitHub,那麼現在的GitHub無疑是前端的GitHub。
藉助GitHub的API,咱們來看看前5000名項目的編程語言使用狀況。題外話,若是GitHub提供了項目全部者能夠給本身的項目打標籤,那麼咱們除了分析下編程語言,還能夠分析下更多方面的內容,好比去年哪一方面的項目最受矚目。要是有機會給GitHub產品部門提意見,我必定會寫上這一點。不過目前就只能分析分析下編程語言了。
因爲GitHub設置了API調用限制,咱們須要先註冊應用,獲取對應的client_id
和client_secret
,纔能有足夠的調用數量。註冊地址見 https://github.com/settings/applications/new,裏面的數據不須要審覈,我當時是亂填一通的=_=
GitHub提供了查詢某個項目的編程語言使用狀況的API,藉此寫出了下面的腳本,統計前5000個項目中編程語言的佔比:
#!/usr/bin/env ruby # encoding: UTF-8 require 'json' require 'net/http' require 'set' def get_language_ingredient(repo) url = "https://api.github.com/repos/#{repo}/languages" # 請改爲你本身的 client_id 和 client_secret client_id = '05500dd030f3a5690d8e' client_secret = 'b8ba63550e07dd3bf7b5b467824ee9ced1c61192' url += "?client_id=#{client_id}&client_secret=#{client_secret}" res = Net::HTTP.get_response(URI(url)) if res.code == '200' JSON.parse(res.body) else puts res.msg {} end end def sum_star_number_per_language(result, repo, star) ingredient = get_language_ingredient(repo) puts "The language ingredient of #{repo}: #{ingredient}" return if ingredient.length == 0 sum = ingredient.reduce(0){|total, pair| total += pair[1]} # 去掉佔比不到1%的語言 ingredient.reject!{|_, bytes| bytes < sum * 0.01} # 若是剩下的語言正好是 JavaScript/CSS/HTML, # 則表示它極可能是代碼無關的項目,直接忽略掉 if Set.new(ingredient.keys) == Set.new(['JavaScript', 'CSS', 'HTML']) # CSS框架除外。考慮到有些靜態網站也是CSS比JS多,這裏要求CSS比JS和HTML多得多。 # 下面的公式隨手寫的,沒有什麼特殊意義,只是強調CSS必定要佔大多數。 unless ingredient['CSS'] > 2 * ingredient['JavaScript'] + ingredient['HTML'] return end end # 剩下的按比例分了star數 sum = ingredient.reduce(0){|total, pair| total += pair[1]} ingredient.each_pair do |language, bytes| result[language] = result.fetch(language, 0) + (bytes.fdiv(sum) * star).round end end def output_star_number_per_language(result) sum = result.reduce(0){|total, pair| total += pair[1]} output = '' result.sort {|a, b| b[1] <=> a[1]}.each_with_index do |e, idx| output += format("%-4d %-40s %.2f%\n", idx+1, e[0], e[1].fdiv(sum).round(4) * 100) end output + "\n" end result = {} output = {} checkpoints = [50, 100, 200, 500, 1000, 2000, 5000] f = File.new('github-star-2015.csv').each f.next f.each_with_index do |line, idx| step = idx + 1 star, repo = line[0...-1].split(',') star = star.to_i puts format("%-4d %-40s %d", step, repo, star) sum_star_number_per_language(result, repo, star) puts "The result after #{repo}: #{result}\n\n" if checkpoints.include?(step) output[step] = output_star_number_per_language(result) puts "first #{step}" puts output[step] end end puts '' output.each_pair do |step, rank| puts "first #{step}" puts rank end
注意兩點:
獲取了每一個項目的語言成分後,去掉佔比不到1%的語言,剩下的語言按比例分掉star數。之因此不直接把star分到佔比最大的語言,是由於有些項目用到多種語言且比例至關,如facebook/react-native.
去掉1%以後,若是剩下的語言正好是JavaScript,CSS和HTML,那麼該項目極可能是代碼無關的(好比一個收集各種資料的靜態網站)。顯然你們關注它的緣故跟任何一門編程語言無關,因此不列入統計之中。可是考慮到CSS框架也正好會有這三門語言,因此當CSS佔比較高時能夠豁免。
下面是最終的結果:
... first 5000 1 JavaScript 26.38% 2 Java 13.33% 3 Objective-C 8.21% 4 Python 8.09% 5 Go 5.44% 6 Swift 4.63% 7 C 3.88% 8 HTML 3.84% 9 C++ 3.82% 10 Ruby 3.60% 11 CSS 3.28% 12 PHP 2.99% 13 Shell 2.67% 14 CoffeeScript 1.51% 15 C# 1.19% 16 VimL 0.90% 17 TypeScript 0.63% 18 Scala 0.59% 19 Lua 0.46% 20 Clojure 0.44% 21 Rust 0.39% 22 Haskell 0.28% 23 Makefile 0.22% 24 Objective-C++ 0.21% 25 Emacs Lisp 0.21% 26 Jupyter Notebook 0.21% 27 Perl 0.20% 28 TeX 0.17% 29 Elixir 0.16% 30 Groff 0.16% 31 Groovy 0.14% 32 R 0.12% 33 OCaml 0.11% 34 PowerShell 0.10% 35 Batchfile 0.10% 36 ApacheConf 0.08% 37 Erlang 0.08% 38 Cucumber 0.08% 39 Assembly 0.07% 40 Crystal 0.06% 41 PureBasic 0.05% 42 QML 0.05% 43 Visual Basic 0.04% 44 PLpgSQL 0.04% 45 Tcl 0.04% 46 Dart 0.04% 47 Vue 0.04% 48 CMake 0.03% 49 PLSQL 0.03% 50 XSLT 0.03% ...
一個顯而易見的結論:GitHub上不小一部分的熱門項目,是由JavaScript寫的。JavaScript一門語言的佔比,比第二名和第三名加起來還多出個第六名。這還不包括第十四名的CoffeeScript和第十七名的TypeScript(它們能夠編譯成JavaScript,嚴格來講也是JavaScript你們族的一員)。
另外從每一個checkpoint時輸出的數據可見,排名靠前的項目中,JavaScript佔的比例要比所有項目中的高。若是咱們選擇的樣本變小,JavaScript的佔比還會升高(都穩拿第一名,排名就不可能升高了)。
另外一個結論是,Go(第五名)和Swift(第六名)這兩門語言正處於快速發展的時期。雖然實際應用的狀況不如前十名中其它語言普遍,可是從star數中可見,開發者們很是看好這兩門語言,關注了許多這方面的項目,同時用這兩門語言編寫的高質量項目也愈來愈多。
前十名中其它語言的排名卻是一點也不出乎意料。Java和Objective-C分居榜眼和探花。剩下幾位天然包括了C/C++/Python等等。使人意外的是,C#(第十五名)竟然沒能排進前十名。按理說,C#的使用量確定能排在前十。也許C#生態圈裏面主要使用的都是微軟的商業產品?
最後,我想感謝GitHub Archieve提供的數據歸檔,沒有這些數據就沒有本篇分析。