Récupérer les images d’une galerie en python

Rédigé par Fred - - Aucun commentaire

Quand je veux récupérer plusieurs pages, je le fais souvent avec wget. L’utilisation des options --load-cookies, --save-cookies et --keep-session-cookies avec --post-data étant plus que pratique. Pour parser, ensuite, c’est souvent pénible, même si awk est là pour aider.

man wget donne :

# Log in to the server.  This can be done only once.
 wget --save-cookies cookies.txt \
      --post-data 'user=foo&password=bar' \
      http://server.com/auth.php

 # Now grab the page or pages we care about.
 wget --load-cookies cookies.txt \
      -p http://server.com/interesting/article.php

Pour parser, j’aime bien python ; je trouve ça plus lisible. Par contre, ce que j’utilisais jusqu’à présent pour me logguer sur une page était moins glop :

import urllib, urllib2, cookielib

username = 'foo'
password = 'bar'

cj = cookielib.CookieJar()
handle = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
login_data = urllib.urlencode({'username' : username, 'pwd' : password})
handle.open('http://www.example.com/login.php', login_data)
res = handle.open('http://www.example.com/my_account.php')
print res.read()

Mais ça, c’était avant. Depuis, j’ai découvert Requests. Pour faire un POST, c’est aussi simple que :

import requests

url= 'http://www.example.com/login.php'
login_data = {username = 'myuser', password = 'mypassword'}

req = requests.post(url, login_data)
page = req.content

Si on a besoin de gérer les cookies, on peut passer par une Session :

import requests

url= 'http://www.example.com'
login_data = {username = 'myuser', password = 'mypassword'}

s = requests.Session()
req = s.post(url + '/login.php', login_data)
req = s.get(url + '/my_account.php')

C’est quand même plus lisible, non ?

En fait, récemment, je voulais parcourir les images de la galerie d’un site. Mais cette galerie contenait 10 images seulement par page, pour 40 pages. J’ai donc fait un script pour mettre toutes les images sur une seule page.

Les images sont encapsulées par une balise a class="foo" et donc j’utilise BeautifulSoup pour toutes les lister (soup.findAll("a","foo")).

Comme j’ai « besoin » de consulter les images plusieurs fois, j’ai préféré enregistrer les images en local plutôt que de laisser un lien sur le site. Pour ça j’ai utilisé stream=True de la méthode .get (cf ce lien sur SO).

J’ai pas fait très propre puisque j’affiche la page sur stdout que je pipe avec tee pour mettre dans un fichier. Mais au moins, je vois si ça marche :þ

# -*- coding: utf-8 -*-
from BeautifulSoup import BeautifulSoup
from requests import session

login_data = { 'login': 'fredtantini', 
               'password': 'toto1234',
               'action': 1 }

urlToVisit = 'http://www.example.com'

#on ouvre une session
with session() as s:
    #on se connecte
    req = s.post(urlToVisit + '/login.php', data=login_data)
    print "<html><body>"
    #comme je sais qu’il y a 40 pages
    for nPage in xrange(1,41):
        #on récupère la page
        request = s.get(urlToVisit + '/some_page.php?p='+str(nPage))
        #que l’on passe à BS
        soup = BeautifulSoup(request.text)    
        print "<h1> Page - ",nPage,"</h1>"
        #Pour tous les liens
        for i in soup.findAll("a","foo"):
            #on récupère l’image
            r = s.get(urlToVisit + '/' + i.img['src'], stream=True)
            #on la télécharge par parties (cf lien SO plus haut)
            if r.status_code == 200:
                with open(i.img['alt'] + ".jpg", 'wb') as f:
                    for chunk in r.iter_content():
                        f.write(chunk)
            print str(i).replace('./images/', './')

print "</body></html>"

Quelques notes SoapUI

Rédigé par Fred - - Aucun commentaire

Voici un premier article sur SoapUI. Un second arrivera prochainement :]

Les informations sont un peu brutes, cela me sert surtout de notes. Du coup, c’est directement technique et suppose que vous connaissiez déjà SoapUI. D’abord un « rappel » sur les property expansions puis comment on peut passer des paramètres entre les différents pas du cas de test et comment faire des assertions variables.

Lire la suite de Quelques notes SoapUI

Différence entre <code>eval-after-load</code> et <code>add-hook</code>

Rédigé par Fred - - Aucun commentaire

J’expliquais dans le billet sur le démarrage d’Emacs que

le code de eval-after-load sera exécuté seulement une fois […]

Les nomdumode-mode-hooks, eux, sont exécutés pour chaque buffer dans lequel le mode sera activé.

Pour illustrer mes propos, voici un code à mettre dans un nouveau buffer (C-x b auie) :

(setq auie 0)
(setq nrst 0)
(eval-after-load "python" ;puisque dans python.el
  '(progn
     (setq auie (1+ auie))
     ))


(add-hook 'python-mode-hook
          (lambda ()
            (setq nrst (1+ nrst))
            ))
(progn
  (python-mode)
  (message (concat "auie vaut :" (number-to-string auie) ", nrst : " (number-to-string nrst))))

Passez en mode elisp (M-x emacs-lisp-mode), puis évaluez le buffer (M-x eval-buffer). Un petit message devrait s’afficher. Allez à la fin du buffer (M->) et évaluez la dernière sexp (C-x C-e). Évaluez plusieurs fois ; constatez que auie n’augmente pas, nrst si.

Autrement dit, si l’on veut exécuter du code lorsque l’on passe dans le mode foo, et que l’on ne veut pas charger le fichier foo.el ni faire un (require 'foo) dans son fichier init.el, on a deux possibilités :

  1. Utiliser eval-after-load pour exécuter du code une fois.
  2. Utiliser add-hook pour exécuter du code plusieurs fois.

En fait, eval-after-load va exécuter le code à chaque fois que la bibliothèque est chargée. Mais généralement, on fait un (autoload 'foo-mode "foo" "docstring") ; au premier appel de foo-mode (avec un M-x ou avec un add-to-list 'auto-mode-alist), foo.el est chargé et le code du eval-after-load est exécuté. Aux prochains appels de foo-mode, foo.el est déjà chargé, le code n’est plus exécuté.

eval-after-load est donc approprié si l’on veut changer des valeurs par défaut :

(eval-after-load "ace-jump-mode"
  '(ace-jump-mode-enable-mark-sync)) ;par défaut, c’est à disable

(eval-after-load "foo-mode"
  '(my-init-foo-mode)) ; on charge des choses en plus

(eval-after-load "org"
  '(require 'ox-md nil t)) ;l’export markdown n’est pas chargé automatiquement

(eval-after-load 'foo-mode
  '(define-key foo-mode-map (kbd "C-à") 'my-useful-fonction)) ; un raccourci utilisé seulement pour ce mode

Le add-hook lui est utilisé à chaque fois que foo-mode est lancé (et non pas à chaque fois que foo.el est chargé). C’est ce choix que l’on fera si l’on veut activer un minor mode pour un major mode ou si on veut changer des valeurs de variables changées par le major mode.

; à chaque fois que l’on passe en elisp mode, on met les parenthèses en couleur
(add-hook 'emacs-lisp-mode 'rainbow-delimiters-mode)

;avant de sauver, on lance un nettoyage
(add-hook 'before-save-hook 'whitespace-cleanup)

;le mode foo redéfinit à chaque fois C-> et je ne veux pas
(add-hook 'foo-mode-hook '(lambda ()
  (define-key foo-mode-map "\C->" 'foobar))) 

;on met c-basic-offset à 4
(add-hook 'c-mode-common-hook
  '(lambda () 
     (setq c-basic-offset 4)))

;si on veut différentes valeurs selon que l’on soit en foo ou en bar
(add-hook foo-mode-hook
  '(lambda () 
    (setq spam 42)) nil t)

(add-hook bar-mode-hook
  '(lambda () 
    (setq spam 3.14)) nil t)

En espérant avoir été clair.

Le démarrage d’Emacs

Rédigé par Fred - - Aucun commentaire

Introduction

Il y a quelques temps de cela (je viens de me rendre compte que cela fait plus de 10 ans déjà…), je commençais à utiliser Emacs. Et, comme beaucoup je suppose, pour configurer, je copiais/collais des bouts de code dans mon .emacs sans chercher à comprendre ce que ça faisait (comment ça c’est encore le cas ‽). Typiquement, j’avais plein de :

(autoload 'php-mode "php-mode" "Major mode for editing php code." t)
(add-to-list 'auto-mode-alist '("\\.php$" . php-mode))

plutôt obscurs.

Et au fil du temps, les lignes s’accumulaient, et Emacs n’était plus aussi rapide à charger.

Je me suis alors intéressé à comment le rendre plus rapide au démarrage. Bien que je me sois rendu compte que la meilleure solution pour moi serait d’utiliser emacsclient1, j’ai d’abord fait du nettoyage, en utilisant le plus possible customize et en regroupant ça dans un seul fichier avec :

(setq custom-file "~/.emacs.d/config/custom.el") (load custom-file)

Puis j’ai supprimé tout ce dont je ne me servais en fait pas, et je me suis penché sur ce qu’il se passe au démarrage d’Emacs, pour savoir si je ne lui faisais pas faire des choses inutiles. Et, avec les différentes versions d’Emacs certainement, j’ai bien vu que la plupart de ces lignes étaient (devenues ?) inutiles.

tl;dr

Que fait autoload ? Qu’y a-t-il dans auto-mode-alist ? Le bout de code précédent pour avoir le mode python est-il nécessaire ? suffisant ? Peut-on faire autrement ? C’est à ça que je vais m’intéresser par la suite. Pour cela, je me suis penché dans le code et le manuel d’Emacs et je vous partage ce que j’en ai retenu et laisse des informations pas forcément pertinentes, mais fortement en relation et toujours instructives.

Lire la suite de Le démarrage d’Emacs

Un peu de typographie et marquer les raccourcis clavier dans org-mode

Rédigé par Fred - - Aucun commentaire

Utilisant la disposition de clavier bépo, et soucieux d’écrire le plus correctement possible, j’ai pris l’habitude de mettre des espaces insécables lorsque c’est nécessaire (même si, je l’avoue, je n’utilise pas les espaces fines… désolé). Depuis plusieurs jours, j’utilise également les apostrophes courbes (!wfr) et plus celles qui se trouve sur la touche 4 des claviers azerty, des droites : l’apostrophe courbe vs l'apostrophe droite.

Lire la suite de Un peu de typographie et marquer les raccourcis clavier dans org-mode

Une espace une tabulation

Rédigé par Fred - - Aucun commentaire

Aujourd'hui, je vais parler des espaces dans Emacs, mais pas que (oui, ces temps-ci, ce sera beaucoup, beaucoup d'Emacs dont il sera question). Et oui, les espaces dont je vais parler, ce sont les espaces aux féminins : le caractère typographique, représenté par un espace (au masculin celui-ci) entre les mots.

Pour voir les espaces que vous avez tapées, et savoir si un espace est constituée d'une ou plusieurs espaces, voire de tabulations, il existe un mode pour cela : M-x whitespace-mode permet de voir tout ce qui est d'habitude invisible (ou presque).

Les espaces seront alors représentées par des · (ou seront en couleur si la ligne ne dépasse pas du buffer), les fins de lignes par $, les espaces (qui devraient être fines) insécables par ¤, les tabulations seront en couleur, etc.

Bon, c'est pas le truc dont je vais me servir souvent. Par contre, dans la bibliothèque du mode (find-library whitespace si vous avez installé le paquet emacs2x-el), il y a tout un tas de fonctions liés aux espaces en général, comme whitespace-cleanup qui se charge des :

  1. lignes vides en début de buffer ;
  2. lignes vides en fin de buffer ;
  3. 8 espaces ou plus en début de lignes ;
  4. espaces avant les tabulations ;
  5. espaces et tabulations en fin de ligne ;
  6. 8 espaces ou plus après une tabulations.

(extrait de l'aide de la fonction, C-h f whitespace-cleanup).

Bref, de quoi faire du ménage si vous n'avez pas fait C-x C-o à la fin de votre fichier par exemple (voir précédemment).

La bibliothèque propose tout un tas d'autres fonctions, qui sont grandement customizable, et je vous invite à y jeter un coup d'œil. Si le whitespace cleanup est trop radical pour vous, ce hook est plutôt sympa :

(add-hook 'before-save-hook 'delete-trailing-whitespace)

Raccourcis utilisés

Pour entrer un caractère utf-8 avec son code hexadécimal (ou son nom) C-x 8 Enter puis le code.

Relancer une précédente commande en ksh

Rédigé par Fred - - Aucun commentaire

Pour le boulot, on fait parfois des sudo su - someUser avec someUser qui est en ksh et qui en plus est en mode vi (Adieu C-r, C-p, C-k, C-e. Bonjour /, Esc-k, dd, A). Du coup, comme il est « partagé », je ne mets pas de bash par défaut ni de set -o emacs (sympa hein ‽). Et au final, je m’y retrouve plutôt bien. Il n’y a pas tellement de différences entre ksh et bash.

Sauf une chose dont je me sers au final assez souvent, l’history expansion (avec le fameux sudo !! par exemple, mais aussi !!:gs:/foo/bar/). Mais en cherchant un peu, il y a quelque chose qui y ressemble vaguement : la commande r. Ça n’est pas la panacée, mais c’est un début : ça permet de relancer la dernière commande qui commence par l’argument de r.

$> echo "toto"
$> touch toto
$> r e
#lance echo "toto"
$> r t
#lance touch toto

Avec un argument entier, cela fait la même chose que ! en bash : un positif = la nième commande, un négatif = la nième commande avant celle-ci.

$> echo "toto"
$> touch toto
$> r -2
#lance echo "toto"

Et enfin, avec r avant=apres, on relance la dernière commande en changeant le premier avant par après.

$> cp fic1 /tmp/fic1
$> r 1=2
#lance cp fic2 /tmp/fic1

Des raccourcis en vrac

Rédigé par Fred - - Aucun commentaire

Bon, j’ai tout plein de choses à faire, mais pas de temps. Quelques choses à partager aussi, mais pas de temps non plus. Du coup, je vais essayer de partager moins mais plus fréquemment.

C’est pas gagné…

En attendant, voici des choses que j’ai trouvées récemment, sans rapport, et sans transition.

Lire la suite de Des raccourcis en vrac

Fil RSS des articles