On Github anthill / training
par ants / @beingAnts
Vous rendre organisés, armés et autonomes pour apprendre de la data-science par la pratique.
Git: gestionnaire de version (sur votre ordinateur)
GitHub: plateforme de collaboration (sur le cloud)
Git évite de dupliquer du code pour le versioner, permet de revenir en arrière et surtout permet de toujours savoir où on en est.
Outils indispensable pour organiser son travail sur un gros projet.
GitHub permet de s'échanger du code, de travailler à plusieurs sur un même projet et de communiquer sur les problèmes.
GitHub permet en outre de déployer des services et de recruter.
// dans le cas où vous êtes derrière un proxy git config --global http.proxy http://proxyuser:proxypwd@proxy.server.com:8080 git config --global https.proxy https://proxyuser:proxypwd@proxy.server.com:8080 // si vous ne l'avez jamais fait auparavant git config --global user.name "Your Name" git config --global user.email "your_email@whatever.com" // pour windows git config --global core.autocrlf true git config --global core.safecrlf true
// créer un dossier mkdir testgit // s'y déplacer cd testgit // initialison git git init
ce qui crée un dossier `.git` contenant tout ce qui concerne git. C'est léger.
git status
donne:
On branch master Initial commit nothing to commit (create/copy files and use "git add" to track)
touch testFile.txt
après ce fichier crée, status donne:
Untracked files: (use "git add <file>..." to include in what will be committed) testFile.txt
git add testFile.txt
indique a git qu'on veut le versioner
Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: testFile.txt
git commit
ouvre un éditeur (vim, nano) pour nommer le commit.
Une alternative rapide:
git commit -m"added empty file to project"
faites un status pour voir...
On itère au fur et a mesure des changements qu'on veut persister :
// on ajoute une ligne au fichier (normalement utiliser l'éditeur) echo "hello" > testFile.txt git status git commit -am"added hello to the file"
faites une modification
git diff
indique les changements par rapport au dernier commit
-hello +bonjour
Chaque commit permet de poser une bouée pour repérer un état du code.
Pour avoir une vue de l'histoire
git log
commit 5bf345af8448979acd16ec07621561f8628211fa Author: vallettea <vallettea@gmail.com> Date: Mon Jan 11 19:53:32 2016 +0100 changed hello in bonjour commit 2dc24bc314fc92fcbf20261ef80ec203088044d9 Author: vallettea <vallettea@gmail.com> Date: Mon Jan 11 19:32:26 2016 +0100 added hello to the file commit c04b81108300ebbe9d367d21c603ae9e3089d55e Author: vallettea <vallettea@gmail.com> Date: Mon Jan 11 19:22:51 2016 +0100 added empty file to project
Pour se déplacer dans l'histoire
git checkout 2dc24bc314f
Si vous regardez votre fichier, vous verrez qu'il est revenu à l'état où il y avait hello. Pour revenir au dernier état
git checkout master
Attention: pour se déplacer dans l'histoire, il faut être "clean", c'est-à-dire ne pas avoir de modifications non-commitées.
Pour revenir au dernier commit
git checkout testFile.txt
va remmetre le fichier tel qu'il était au dernier commit. Pour faire la même chose avec tous les fichiers à la fois (dans le cas d'un projet complet):
git checkout --hard HEAD
On utilise log et checkout pour naviguer dans l'histoire des commits
Pour créer une branche quand on est clean:
git branch newVersion
Lister les branches
git branch
se mettre sur la branche
git checkout newVersion
ou, si on a déjà fait des modifications, qu'elles parraissent importantes et qu'on veut les séparer sur une nouvelle branche
git checkout -b newVersion
Pour voir où on en est:
git log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short --all
(se faire un alias) donne:
* ae5830b 2016-01-11 | added a third file (HEAD -> newVersion) [vallettea] | * 58f41af 2016-01-11 | added a second file (master) [vallettea] |/ * 5bf345a 2016-01-11 | changed hello in bonjour [vallettea] * 2dc24bc 2016-01-11 | added hello to the file [vallettea] * c04b811 2016-01-11 | added empty file to project [vallettea]
Les branches permettent d'organiser ses modifications
Remettons nous sur master
git checkout master
et apportons tous les changements fait sur newVersion sur master :
git merge newVersion
Pour voir où on en est:
git log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short --all
(se faire un alias) donne:
* 867fdd6 2016-01-11 | Merge branch 'newVersion' (HEAD -> master) [vallettea] |\ | * ae5830b 2016-01-11 | added a third file (newVersion) [vallettea] * | 58f41af 2016-01-11 | added a second file [vallettea] |/ * 5bf345a 2016-01-11 | changed hello in bonjour [vallettea] * 2dc24bc 2016-01-11 | added hello to the file [vallettea] * c04b811 2016-01-11 | added empty file to project [vallettea]
Merger sert a faire converger les modifications crées sur les branches vers une version finale.
Remote indique le chemin entre ce repo vers un dépot github :
git remote add anthill https://github.com/anthill/training.git git push -u anthill master
où anthill est le nom du dépot. Un repo peut avoir plusieur remote (voir fork).
Pour synchroniser un repo local avec un remote, on utilise d'une part :
git push -u anthill master
où master est le nom de la branche qu'on veut synchroniser.
push s'utilise lorsque le repo local est en avance sur le remote.
Counting objects: 101, done. Delta compression using up to 4 threads. Compressing objects: 100% (93/93), done. Writing objects: 100% (101/101), 1.46 MiB | 145.00 KiB/s, done. Total 101 (delta 17), reused 0 (delta 0)
Si le remote est en avance sur le repo local (quelqu'un a ajouté du code) on utilise :
git pull anthill master
où master est le nom de la branche qu'on veut synchroniser.
Avec remote, push et pull vous pouvez synchoniser votre code dans le cloud (sauvegarde)
Un autre dévelopeur veut travailler sur votre code :
git clone https://github.com/anthill/training.git
va crée une copie locale de votre remote.
(que donne git remote -v ?)
Au lieu de créer une copie de votre remote sur son local, il vaut mieux que le contributeur fasse une copie de votre remote sur un remote à lui. C'est la combinaison fork/clone.
(que donne git remote -v ?)
Lorsqu'un contributeur estime que les modification de son code devraient être incorporées à la version principale, il met synchronise son remote et crée un pull request
Les pull request de forks permettent d'intégrer les contributions:
Toutes les zones de texte de github permettent d'écrire en markdown
Les elements d'une page sont représenté par une balise :
<element attribut="valeur" ...>contenu</element>
Certains éléments sont solitaires d'autres s'associent.
se placent dans l'en-tête de la page :
<meta name="description" content="The slides used to teach companies how to code like hackers."> <link rel="stylesheet" href="css/reveal.css">
Ils servent à charger des ressources extérieures (css, javascript, données ...)
un type de balise = un rôle sémantique
les balises servent à structurer l'information pour que les machines (navigateur, moteur de recherche ...) puissent la comprendre
Par exemple, h (header) peut avoir différents poids :
<h1>Titre très important</h1> <h2>Titre important</h2> <h3>Titre moins important</h3> ...
<table> <thead> <tr> <th>Header content 1</th> <th>Header content 2</th> </tr> </thead> <tfoot> <tr> <td>Footer content 1</td> <td>Footer content 2</td> </tr> </tfoot> <tbody> <tr> <td>Body content 1</td> <td>Body content 2</td> </tr> </tbody> </table>
Le code précédent donne :
Header content 1 Header content 2 Footer content 1 Footer content 2 Body content 1 Body content 2<form action=""> <label for="GET-name">Nom :</label> <input id="GET-name" type="text"> <input type="submit" value="Save"> </form> <!-- Simple form which will send a POST request --> <form action="" method="post"> <label for="POST-name">Prénom :</label> <input id="POST-name" type="text"> <input type="submit" value="Save"> </form>
Le code précédent donne :
Nom : Prénom:Tous les éléments html ont un style par défaut, le CSS sert à personaliser le style de chaque élément.
Anatomie d'un élément (box model) :
// dans l'élément <element style="..."> // dans un bloc style <style type="text/css"> // dans une stylesheet <link rel="stylesheet" href="main.css">
p {...} /* sélécteur d'élement */ .class {...} /* sélécteur de classe */ #id {...} /* sélécteur d'identifiant */ [attr] {...} /* sélécteur d'attribut */
div * {...} div p a {...} div.maClasse {...} div a#monId {...} ul > li {...} // all li directly children of ul div[class=”maClasse”] {...} // all div that only have this class div + span {...} // span that is adjacent to div a[class~=”plop”] {...} // all div that have at least this class
a:link {...} a:visited {...} a:hover {...} div:only-child {...} div:first-child {...} div:last-child {...} div:nth-child(an+b) {...} div:nth-last-child(an+b) {...} ...
p::first-line // first line of the paragraph even in responsive mode p::first-letter // first letter: usefull for typography of the first letter p::before // add content inside the p before p's content p::after // add content inside the p after p's content
Les éléments avec display: block forcent les éléménts suivant à aller à la ligne suivante. On peut choisir leur width et height
Les éléments avec display: inline subissent le flux du texte (et vont à la ligne quand il n'y a plus de place sur la ligne actuelle)
Les éléments avec display: inline-block agissent comme des inline à l'extérieur et block à l'intérieur
site/ css/ main.css myTheme.css fonts/ js/ img/ index.html
Dans tous les cas :
<meta name="viewport" content="width=device-width, initial-scale=1.0">
puis des media-queries :
@media only screen and (min-width: 480px) {...}
Javascript est le langage de programmation des pages web.
Un seul type de nombre (pas de distinction int/float/double)
parseInt("123", 10); // 123 parseInt("010"); // 8 Number.isNaN(NaN); // true 1 / 0; // Infinity Math.sin(3.5); var aire = Math.PI * r * r;
"bonjour".length; // 7 "bonjour".charAt(0); // "b" "coucou monde".replace("coucou", "bonjour"); // "bonjour monde" "bonjour".toUpperCase(); // "BONJOUR"
false, 0, la chaîne vide (""), NaN, null et undefined deviennent toutes false
Boolean(""); // false Boolean(234); // true
123 == "123"; // true 1 == true; // true 123 === "123"; //false true === true; // true
var nom = "des chatons"; if (nom == "des chiots") { nom += " !"; } else if (nom == "des chatons") { nom += " !!"; } else { nom = " !" + nom; }
les opérateurs logiques :
if (nom === "toto" && prenom === "alex") if (nom === "toto" || prenom === "alex") var permis = (age > 18) ? "oui" : "non";
switch(action) { case 'dessiner': dessine(); break; case 'manger': mange(); break; default: neRienFaire(); }
sans break l'execution se poursuit au block suivant.
for (var i = 0; i < 5; i++) { // Sera exécutée cinq fois }
var a = new Array(); a[0] = "chien"; a[1] = "chat"; a[2] = "poule"; a.length; // 3 var a = ["chien", "chat", "poule"]; a.push("vache"); a.join(", "); // "chien, chat, poule" a.slice(1, 3); // ["chat", "poule"] a.pop(); // "poule"
["a", "b", "c"].forEach(function(element){ console.log(element) }); var numbers = ["1", "2", "3"].map(function(element){ return parseInt(element, 10) });
Les objets javascript sont similaires au dictionnaires en python et plus généralement aux hashmap
var obj = new Object(); var obj = {}; obj["prenom"] = "Simon"; obj["nom"] = "Dupont"; println(obj["nom"])
Les objets peuvent avoir plusieurs niveaux:
var obj = { nom: "Dupont", prenom: "Simon", associes: ["A", "B"] preferences: { couleur: "orange", chiffre: 8 } }
on accède aux champs par enchainement :
obj.preferences.couleur; // orange obj["preferences"]["chiffre"]; // 8
Les objets peuvent être serialisés en json :
var objectString = JSON.stringify(object); var object = JSON.parse(objectString);
function ajoute(x, y) { var total = x + y; return total; }
Le DOM est le graph dont les noeuds sont les balises html consituant le document.
javascript permet de manipuler le DOM dynamiquement.
Lorsqu'une page html est lue, window et document
<!doctype html> <html> <head> <meta charset="utf-8"> <script> "use strict"; document.addEventListener('DOMContentLoaded', function() { var heading = document.createElement("h1"); heading.textContent = "gros titre!"; document.body.appendChild(heading); }) </script> </head> <body></body> </html>
Lorsqu'une page html est lue, window et document sont initialisées et on peut manipuler le DOM avec :
document.getElementById(id) element.getElementsByTagName(name) document.createElement(name) parentNode.appendChild(node) element.innerHTML element.style.left element.setAttribute element.getAttribute element.addEventListener window.content window.onload window.dump window.scrollTo
<div onclick="changeFont();"></div> // don't do this myDiv.addEventListener('click', function(){ // after myDiv = document.getElementById(); doSomething(); });
Le problème du code synchrone
var f = readfile(file); // 10s var g = readfile(file2); // 12s var h = readfile(file3); // 15s combine(f, g, h); // runs after 10 + 12 + 15 = 37s
var fP = readfile(file); var gP = readfile(file2); var hP = readfile(file3); fP.then(function(contentF){ console.log('Done', contentF); }); Promise.all([fP, gP, hP]) .then(function(results){ // runs after max(10, 12, 15) = 15s var f = results[0]; var g = results[1]; var h = results[2]; return combine(f, g, h); }) .catch(errorHandler);
// export module.exports = 9.81; // dans gravite.js module.exports = function(masse){ // dans appliquerG.js return 9.81 * masse; }; // import var gravite = require('./gravite.js'); // my own stuff var appliquerGravite = require('./appliquerG.js'); var moment = require('moment'); // npm package
// export module.exports = { // dans math.js sum: function (a, b){ a + b }, substract: function (a, b) { a - b } } // import var additioner = require('./math.js').sum; var soustraire = require('./math.js').substract; // ou var math = require('./math.js'); math.sum(3, 4); math.substract(31, 22);
La plus grosse bibliothèque de modules pour Node
npm install npm --save -g // upgrades npm npm init // initialize an npm project
{ "name": "ToilettesBordeaux", "version": "0.0.0", "description": "## Données", "main": "index.js", "scripts": { "build": "browserify js/main.js -o app.js -d", "start": "devserver", "test-server": "devserver -p 9184", "test": "casperjs test test/casper", "watch": "watchify js/main.js -o app.js -d -v", "serve": "devserver", "lint": "eslint js/" }, "repository": { "type": "git", "url": "git://github.com/anthill/ToilettesBordeaux.git" }, "author": "", "license": "MIT", "bugs": { "url": "https://github.com/anthill/ToilettesBordeaux/issues" }, "dependencies": { "browserify": "~6.1.0", "leaflet": "~0.7.3", "react": "~0.11.1", "react-tabs": "^0.1.2" }, "devDependencies": { "watchify": "~2.0.0", "grunt": "~0.4.5", "grunt-devserver": "~0.6.0", "eslint": "~0.9.2", "casperjs": "~1.1.0-beta3", "tree-kill": "0.0.6" } }
Il décrit le projet, ses scripts et ses dépendances
Dossier contenant l'arbre de dépendances
Ne jamais commit !
projet_Node/ js/ node_modules/ <!-- dependencies: always installed--> browserify/ <!-- devDependencies: not installed when subdependency--> watchify/ grunt/ node_modules/ <!-- here only dependencies--> async/ coffee-script/ ... grunt-devserver/ package.json
On peut lister les dépendances avec
npm ls
npm run makeCoffee // postmakeCoffee is run npm start
GOGOGO
Indispensable pour utiliser Node dans le navigateur
browserify js/main.js -o browserify-bundle.js -d
Puis importer le bundle dans le HTML
<script defer src="browserify-bundle.js"></script>
watchify, l'équivalent temps réel
Créé par Facebook en 2013
Utilisé par
Existe en web et en natif
=> Rapidité
Il faut limiter les composants stateful
Trouver le bon algorithme pour la bonne tâche.
Peu de maths...
Avantages :
import pandas as pd import numpy as np import matplotlib.pyplot as plt
s = pd.Series([7, 'Einstein', 3.14, -1789710578, 'Dumas']) # adding index s = pd.Series([7, 'Einstein', 3.14, -1789710578, 'Dumas'], index=['A', 'Z', 'C', 'Y', 'E']) #from a dictionnary d = {'Chicago': 1000, 'New York': 1300, 'Portland': 900, 'San Francisco': 1100, 'Austin': 450, 'Boston': None} cities = pd.Series(d)
cities['Chicago'] cities[['Chicago', 'Portland', 'San Francisco']] cities[cities < 1000] # changing value cities['Chicago'] = 1400 # applying function np.sqrt(cities)
# changing value cities['Chicago'] = 1400 # applying function np.sqrt(cities) cities.notnull()
rng = pd.date_range('1/1/2012', periods=100, freq='S') ts = pd.Series(np.random.randint(0, 500, len(rng)), index=rng) ts.resample('5Min', how='sum')
data = {'year': [2010, 2011, 2012, 2011, 2012, 2010, 2011, 2012], 'team': ['Bears', 'Bears', 'Bears', 'Packers', 'Packers', 'Lions', 'Lions', 'Lions'], 'wins': [11, 8, 10, 15, 11, 6, 10, 4], 'losses': [5, 8, 6, 1, 5, 10, 6, 12]} football = pd.DataFrame(data, columns=['year', 'team', 'wins', 'losses'])
# read pd.read_csv('file.csv', sep=',') pd.read_json('test.json') pd.read_excel('foo.xlsx', 'Sheet1', index_col=None, na_values=['NA']) data = pd.read_sql_table('data', conn) # write df.to_hdf('foo.h5','df') names=cols)
Avantages :
from sklearn import datasets, linear_model # Create linear regression object regr = linear_model.LinearRegression() # Train the model using the training sets regr.fit(diabetes_X_train, diabetes_y_train) # Make predictions regr.predict(diabetes_X_test)
Idée: on suppose "naïvement" que toutes les features sont statistiquement indépendantes.
Théorème de Bayes (explication):
\[ P(y\mid x_1, x_2, ..., x_n) = \frac{P(y)P(x_1, x_2, ..., x_n\mid y)}{P(x_1, x_2, ..., x_n)} \]Avec l'indépendance des features:
\[ P(y\mid x_1, x_2, ..., x_n) = \frac{P(y)\prod_{i=1}^{n}P(x_i\mid y)}{P(x_1, x_2, ..., x_n)} \]ce qui permet de calculer la classe la plus probable, après avoir choisis une distribution pour \( P(x_i\mid y) \)
Exemple avec une gaussienne:
\[ P(x_i\mid y) = \frac{1}{\sqrt{2\pi \sigma_y^2}}exp\left(-\frac{(x_i-\mu_y)^2}{2\sigma_y^2} \right) \]Avantages :
from sklearn import datasets iris = datasets.load_iris() from sklearn.naive_bayes import GaussianNB gnb = GaussianNB() y_pred = gnb.fit(iris.data, iris.target).predict(iris.data) print("Number of mislabeled points out of a total %d points : %d" % (iris.data.shape[0],(iris.target != y_pred).sum()))Seuls 6 des points sur 150 sont mal labélisés.
Advantages :
Avantages :
Problèmes :
Avantages
Problèmes :
random forests gagnent souvent sur tout le monde, rapide et sclalable, sans paramètres.
Accuracy: à quel point la réponse est proche de la solution. Pensez à la cible avec des flêches et qu'on fait le décompte. Combien de prédictions sont de bonnes prédictions ?
Précision: à quel point cette réponse est reproductible. Penser au tireur et non à la cible. Est-ce que le modèle est fiable ?
Le dataset sur le cancer du sein permet d'illustrer la gravité de l'évaluation d'un modèle.
La robustesse du modèle (et c'est ça qui est important) se calcul par :
\[\frac{nb\ vrais\ positifs}{nb\ vrais\ positifs + nb\ faux\ positifs} \]La complétude du modèle :
\[\frac{nb\ vrais\ positifs}{nb\ vrais\ positifs + nb\ faux\ négatifs} \]Equilibre entre précision et sensibilité :
\[ 2\frac{precision \times recall}{precision+recall} \]from sklearn.datasets import load_iris from sklearn import tree iris = load_iris() clf = tree.DecisionTreeClassifier() clf = clf.fit(iris.data, iris.target) from sklearn.metrics import confusion_matrix cm = confusion_matrix(iris.target, clf.predict(iris.data)) # exercice from treeExport import makeJsonTree makeJsonTree(clf, iris.feature_names)
Consiste à diviser le learning set en plusieurs sous-ensembles et crée un modèle par sous ensemble. Le résultat est obtenu par moyenne pour la régression et par vote pour la classification.
Exemple: random forest: beaucoup d'arbres overfittés
Consiste à mettre en série des modèles qui apprennent de l'erreur résiduelle des précédents.
Exemple: adaboost: beaucoup d'arbres underfittés
import numpy as np import matplotlib.pyplot as plt from sklearn.cross_validation import train_test_split from sklearn.ensemble import GradientBoostingRegressor from sklearn.ensemble.partial_dependence import partial_dependence from sklearn.datasets.california_housing import fetch_california_housing cal_housing = fetch_california_housing() # if pb # https://raw.githubusercontent.com/scikit-learn/scikit-learn/3daab8a99862674514735a3caadd45cc542b43c1/sklearn/datasets/california_housing.py # separation 80/20 train-test X_train, X_test, y_train, y_test = train_test_split(cal_housing.data, cal_housing.target, test_size=0.2, random_state=1) names = cal_housing.feature_names
import pandas as pd X_df = pd.DataFrame(data=X_train, columns=names) X_df['LogMedHouseVal'] = y_train X_df.hist(column=['Latitude', 'Longitude', 'MedInc', 'LogMedHouseVal']) plt.show()
clf = GradientBoostingRegressor(n_estimators=300, max_depth=6, learning_rate=0.04, loss='huber', random_state=1) clf.fit(X_train, y_train) from sklearn.metrics import mean_absolute_error from scipy.stats import pearsonr y_pred = clf.predict(X_test) mae = mean_absolute_error(y_test, y_pred) print('MAE: %.4f' % mae) pea = pearsonr(y_test, y_pred) print('PEA: %.4f' % pea[])
# importances des features indices = np.argsort(clf.feature_importances_) plt.barh(np.arange(len(names)), clf.feature_importances_[indices]) plt.yticks(np.arange(len(names)) + 0.25, np.array(names)[indices]) plt.xlabel('Relative importance') plt.show()
Il s'agit de trouver une nouvelle base de vecteurs propres qui élimine les corrélations.
Lorsqu'une prédiction d'un modèle diffère significativement de la réalité, il y une anomalie.
Il s'agit de regrouper des points par des règles de proximité géométriques dans un espace à N dimensions.
Excellent post décrivant la prédicition via k-means clustering.
Une Application Programmtion Interface est un ensemble de contraintes sur les entrées/sorties d'un programme pour que tout le monde puisse se parler.
Les representations des objets sont des URI:
http://api.example.com/client/123
Avec le protocole HTTP:
curl https://api.github.com/users/vallettea { "login": "vallettea", "id": 371303, "avatar_url": "https://avatars.githubusercontent.com/u/371303?v=3", "gravatar_id": "", "url": "https://api.github.com/users/vallettea", "html_url": "https://github.com/vallettea", "followers_url": "https://api.github.com/users/vallettea/followers", "following_url": "https://api.github.com/users/vallettea/following{/other_user}", "gists_url": "https://api.github.com/users/vallettea/gists{/gist_id}", "starred_url": "https://api.github.com/users/vallettea/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/vallettea/subscriptions", "organizations_url": "https://api.github.com/users/vallettea/orgs", "repos_url": "https://api.github.com/users/vallettea/repos", "events_url": "https://api.github.com/users/vallettea/events{/privacy}", "received_events_url": "https://api.github.com/users/vallettea/received_events", "type": "User", "site_admin": false, "name": "Alexandre Vallette", "company": null, "blog": null, "location": null, "email": null, "hireable": null, "bio": null, "public_repos": 50, "public_gists": 61, "followers": 32, "following": 3, "created_at": "2010-08-20T21:09:06Z", "updated_at": "2016-02-26T23:22:07Z" }
Avec express.js:
app.get('/user/:name', function(req, res){ var user = req.params.user; console.log('requesting sensor user', user); // result of the call to a db var data = { name: "toto", age: 12 }; res.status(200).send(data); });
Avec flask:
from flask import Flask, jsonify app = Flask(__name__) @app.route("/") def hello(): return "Hello World!" @app.route('/user/<username>') def show_user_profile(username): list = [ {'param': 'foo', 'val': 2}, {'param': 'bar', 'val': 10} ] return jsonify(result=list) if __name__ == "__main__": app.run() </username>
Webhooks:
var githubhook = require('githubhook'); // configure listener for github changes var github = githubhook({/* options */ host: "0.0.0.0", port: 8082, path: "/pushchanges", secret: "123456" }); // listen to push on github on branch master github.on('push', function (repo, ref, data) { var branchName = _s.strRightBack(ref, "/"); var fullNameRepository = data.repository.full_name; var removedFilesArray = data["head_commit"]["removed"]; var addedFilesArray = data["head_commit"]["added"]; var modifiedFilesArray = data["head_commit"]["modified"]; }); // listen to github push github.listen();
Avec socket.io:
var io = require('socket.io')(80); var cfg = require('./config.json'); var tw = require('node-tweet-stream')(cfg); tw.track('socket.io'); tw.track('javascript'); tw.on('tweet', function(tweet){ io.emit('tweet', tweet); });
Toute information visible sur internet peut être récupérée.
Exemple: scrapper la météo avec python
soup = BeautifulSoup(urllib2.urlopen("http://www....").read()) a = soup('table', {'width': '100%', "border":"1", "cellpadding":"1" ,"cellspacing":"0", "bordercolor":"#C0C8FE" ,"bgcolor":"#EBFAF7"})[0] b = a.findAll("tr")
Exemple: scrapper la qualité de l'eau
casper.start("http://...", function() { this.selectOptionByValue('select[name="departement"]', "033") }); casper.then( function() { this.selectOptionByValue('select[name="communeDepartement"]', "063") }); casper.then(function(){ this.waitUntilVisible('input[value="Rechercher"]', function() { this.click('input[value="Rechercher"]'); }); })
Penser en service
Ansible permet de déployer automatiquement une infrastructure complexe sur plusieurs machines.
Avantages :