├── .gitignore ├── package.json ├── .jshintrc ├── README.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.json 2 | !package.json 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "github-contributions-scraper", 3 | "version": "1.0.0", 4 | "description": "Scrapes the GitHub contributions graph SVG and outputs JSON.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Don McCurdy ", 10 | "license": "MIT", 11 | "dependencies": { 12 | "node-fetch": "^1.6.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": {}, 3 | "bitwise": false, 4 | "browser": false, 5 | "eqeqeq": true, 6 | "esnext": true, 7 | "expr": true, 8 | "forin": true, 9 | "immed": true, 10 | "latedef": "nofunc", 11 | "laxbreak": true, 12 | "maxlen": 100, 13 | "newcap": true, 14 | "noarg": true, 15 | "node": true, 16 | "noempty": true, 17 | "noyield": true, 18 | "quotmark": "single", 19 | "smarttabs": false, 20 | "trailing": true, 21 | "undef": true, 22 | "unused": true, 23 | "white": false 24 | } 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitHub Contributions Scraper 2 | 3 | Scrapes the GitHub contributions graph SVG and outputs JSON. 4 | 5 | *** 6 | 7 | Converts this... 8 | 9 | ![contributions graph image](https://cloud.githubusercontent.com/assets/1848368/17843037/724ca8b0-67f7-11e6-9b59-c7eae0024578.png) 10 | 11 | ...to this: 12 | 13 | ```javascript 14 | [ 15 | { 16 | "count": 1, 17 | "date": "2015-08-16" 18 | }, 19 | { 20 | "count": 3, 21 | "date": "2015-08-17" 22 | }, 23 | { 24 | "count": 2, 25 | "date": "2015-08-18" 26 | }, 27 | { 28 | "count": 1, 29 | "date": "2015-08-19" 30 | }, 31 | 32 | // ... 33 | 34 | ] 35 | ``` 36 | 37 | 38 | 39 | ## Usage 40 | 41 | ```javascript 42 | node index.js $USER output.json 43 | ``` 44 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var fetch = require('node-fetch'), 2 | assert = require('assert'), 3 | fs = require('fs'); 4 | 5 | var user = process.argv[2], 6 | file = process.argv[3]; 7 | 8 | assert.ok(user && file, 'Usage: node github-contributions-scraper.js '); 9 | 10 | fetch('https://github.com/users/{user}/contributions'.replace('{user}', user)) 11 | .then((res) => res.text()) 12 | .then(loadGraph); 13 | 14 | function loadGraph (text) { 15 | var data, 16 | re = /(data-count="\d".*data-date="\d{4}-\d{2}-\d{2}")/g, 17 | matches = text.match(re); 18 | data = matches.map(function (match) { 19 | return { 20 | count: +match.match(/data-count="(\d)"/)[1], 21 | date: match.match(/data-date="(\d{4}-\d{2}-\d{2})"/)[1] 22 | }; 23 | }); 24 | fs.writeFile(file, JSON.stringify(data, null, 2), function (err) { 25 | if (err) console.error(err); 26 | else console.info('Exported %d days\' events', data.length); 27 | }); 28 | } 29 | --------------------------------------------------------------------------------