├── .gitignore ├── data └── tfl-lines.js ├── sentiment-analysis.js ├── package.json ├── fetch-tweets.js ├── index.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | keys.js 3 | .idea -------------------------------------------------------------------------------- /data/tfl-lines.js: -------------------------------------------------------------------------------- 1 | 2 | exports.lines = [ 3 | 'Circle', 4 | 'Hammersmith', 5 | 'Northen', 6 | 'Metropolitan', 7 | 'District', 8 | 'Jubile', 9 | 'Overground', 10 | 'Central', 11 | 'Bakerloo', 12 | 'Picadilly', 13 | 'Victoria', 14 | 'Waterloo', 15 | 'DLR' 16 | ]; -------------------------------------------------------------------------------- /sentiment-analysis.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Alicia on 21/06/2015. 3 | */ 4 | 5 | var request = require('request'); 6 | 7 | var host = 'https://api.idolondemand.com/1/api/sync/analyzesentiment/v1'; 8 | 9 | function fetchRoutes(text_body, api_key, callback) { 10 | 11 | var url = host +'?text=' + text_body +'&apikey=' + api_key; 12 | 13 | request({ 14 | url: url, 15 | json: true 16 | }, function (error, response, body) { 17 | if (!error && response.statusCode === 200) { 18 | callback(body); 19 | } 20 | }); 21 | } 22 | 23 | exports.fetchRoutes = fetchRoutes; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tfl-sentiment-analysis", 3 | "version": "1.0.0", 4 | "description": "A node modules that analyses recent Twitter feeds mentioning each London Underground line, and than uses HP IDOL OnDemand Sentiment Analysis to determine wheather overall each line is receiving positive or negetive tweets.", 5 | "main": "index.js", 6 | "dependencies": { 7 | "q": "^1.4.1", 8 | "request": "^2.58.0", 9 | "twitter": "^1.2.5" 10 | }, 11 | "devDependencies": {}, 12 | "scripts": { 13 | "test": "echo \"Error: no test specified\" && exit 1" 14 | }, 15 | "keywords": [ 16 | "tfl", 17 | "twitter", 18 | "hp", 19 | "sentiment", 20 | "analysis", 21 | "AI" 22 | ], 23 | "author": "aliciasykes.com", 24 | "license": "ISC" 25 | } 26 | -------------------------------------------------------------------------------- /fetch-tweets.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Alicia on 21/06/2015. 3 | */ 4 | 5 | var twitter = require('twitter'); 6 | 7 | function fetchTweets(keyword, keys, callback) { 8 | 9 | var client = new twitter({ 10 | consumer_key: keys.CONSUMER_KEY, 11 | consumer_secret: keys.CONSUMER_SECRET, 12 | access_token_key: keys.ACCESS_TOKEN_KEY, 13 | access_token_secret: keys.ACCESS_TOKEN_SECRET 14 | }); 15 | 16 | client.get('search/tweets', {q: keyword, /*geocode: '51.5286417,-0.1015987,50km',*/ count: 200}, function (error, tweets, response) { 17 | var results = ""; 18 | tweets.statuses.forEach(function(eachTweet){ 19 | results += eachTweet.text+" \n" 20 | }); 21 | if(results.length>500){results = results.substring(1, 500);} 22 | callback(results); 23 | }); 24 | 25 | } 26 | 27 | exports.fetchTweets = fetchTweets; -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by Alicia on 21/06/2015. 3 | */ 4 | 5 | var sentimentAnalysis = require('./sentiment-analysis'); 6 | var fetchTweets = require('./fetch-tweets'); 7 | var tflLines = require('./data/tfl-lines').lines; 8 | 9 | var results = []; 10 | 11 | function fetchTflSentiments(keys, callback){ 12 | var line = tflLines.pop(); // Get the next tfl line 13 | var tflKeywords = line + " line OR #" + line + "Line OR @" + line + "Line"; // create search string for tweets 14 | fetchTweets.fetchTweets(tflKeywords, keys.twitter, function (twitterResults) { 15 | twitterResults = twitterResults.replace(/[^a-zA-Z ]/g, ''); // Get rid of all non-alpha characters 16 | if(twitterResults == "" || twitterResults == undefined){ twitterResults = "neutral"} // get rid of blanks 17 | sentimentAnalysis.fetchRoutes(twitterResults, keys.HP_API_KEY, function (sentimentResults) { 18 | results.push({line: line, sentiments: sentimentResults.aggregate.sentiment, score: sentimentResults.aggregate.score}); 19 | if(tflLines.length>0) { fetchTflSentiments(keys, callback) } // Still lines left, recall method 20 | else { callback(results) } // All done, call callback 21 | }); 22 | }); 23 | } 24 | 25 | 26 | exports.fetchTflSentiments = fetchTflSentiments; 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TFL Twitter Sentiment Analysis 2 | A node modules that analyses recent Twitter feeds mentioning each London Underground line, and than uses HP IDOL OnDemand Sentiment Analysis to determine wheather overall each line is receiving positive or negetive tweets. 3 | 4 | 5 | 6 | ##Usage 7 | ###Inatall 8 | ``` 9 | npm install git://github.com/Lissy93/london-underground-live-sentiment-analysis.git 10 | ``` 11 | 12 | ### Include 13 | ``` 14 | var tflSentimentAnalysis = require('tfl-sentiment-analysis'); 15 | ``` 16 | 17 | ### Authenticating 18 | You will need to sign up for an API key at https://api-portal.tfl.gov.uk/signup, and also the HP OnDemand key at http://www.idolondemand.com/signup.html , both of which are free. 19 | Create a JSON similar to this: 20 | ``` 21 | exports.HP_API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; 22 | 23 | exports.TWITTER_API = { 24 | CONSUMER_KEY : "xxxxxxxxxxxxxxxxxxxxxxxxx", 25 | CONSUMER_SECRET : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 26 | ACCESS_TOKEN_KEY : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 27 | ACCESS_TOKEN_SECRET : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 28 | }; 29 | 30 | ``` 31 | You should put it in a seperate file along with your other API keys and add file to your .gitignore 32 | 33 | ### Make simple request 34 | ```javascript 35 | tflSentimentAnalysis.fetchTflSentiments(keys, function(results){ 36 | console.log(results); // Do whatever with the results 37 | }); 38 | ``` 39 | 40 | ### Example Output 41 | ``` 42 | [ { line: 'DLR', sentiments: 'neutral', score: 0 }, 43 | { line: 'WaterlooCity', sentiments: 'neutral', score: 0 }, 44 | { line: 'Victoria', 45 | sentiments: 'positive', 46 | score: 0.5685799620527161 }, 47 | { line: 'Picadilly', sentiments: 'neutral', score: 0 }, 48 | { line: 'Bakerloo', sentiments: 'neutral', score: 0 }, 49 | { line: 'Central', sentiments: 'neutral', score: 0 }, 50 | { line: 'Overground', sentiments: 'neutral', score: 0 }, 51 | { line: 'Jubile', sentiments: 'neutral', score: 0 }, 52 | { line: 'District', 53 | sentiments: 'negative', 54 | score: -0.8177321332492695 }, 55 | { line: 'Metropolitan', sentiments: 'neutral', score: 0 }, 56 | { line: 'Northen', sentiments: 'positive', score: 0.48272937292926293 }, 57 | { line: 'Hammersmith', sentiments: 'neutral', score: 0 }, 58 | { line: 'Circle', 59 | sentiments: 'negative', 60 | score: -0.44023113875144726 } ] 61 | ``` 62 | 63 | [TFL]:https://api-portal.tfl.gov.uk/signup 64 | [@lissy_sykes]:http://twitter.com/lissy_sykes 65 | 66 | --------------------------------------------------------------------------------