Archive for the ‘Développement’ Category

Web scraping with python (part 1 : crawling)

Wednesday, December 29th, 2004

Example One : I am looking for my next job. So I subscribe to many job sites in order to receive notifications by email of new job ads (example = Monster…). But I’d rather check these in my RSS aggregator instead of my mailbox. Or in some sort of aggregating Web platform. Thus, I would be able to do many filtering/sorting/ranking/comparison operations in order to navigate through these numerous job ads.

Example Two : I want to buy a digital camcorder. So I want to compare the available models. Such a comparison implies that I rank the most common models according to their characteristics. Unfortunately, the many sites providing reviews or comparisons of camcorders are not often comprehensive and they don’t offer me the capability of comparing them with respect to my way of ranking and weighting the camcorder features (example = dvspot). So I would prefer pumping all the technical stuff from these sites and manipulate this data locally on my computer. Unfortunately, this data is merged within HTML. And it may be complex to extract it automatically from all the presentation code.

These are common situations : interesting data spread all over the web and merged in HTML presentation code. How to consolidate this data so that you can analyze and process it with your own tools ? In some near future, I expect this data will be published so that it is directly processable by computers (this is what the Semantic Web is intending to do). For now, I was used to do it with Excel (importing Web data, then cleaning it and the like) and I must admit that Excel is fairly good at it. But I’d like some more automation for this process. I’d like some more scripting for this operation so that I don’t end with inventing complex Excel macros or formulas just to automate Web site crawling, HTML extraction and data cleaning. With such an itch to scratch, I tried to address this problem with python.

This series of messages introduces my current hacks that automate web sites crawling and data extraction from HTML pages. The current output of these scripts is a bunch of CSV files that can be further processed … in Excel. I wish I would output RDF instead of CSV. So there remains much room for further improvement (see RDF Web Scraper for a similar but approach). Anyway… Here is part One : how to crawl complex web sites with Python ?. The next part will deal with data extraction from the retrieved web pages, involving much HTML cleansing and parsing.

My crawlers are fully based on the John L. Lee’s mechanize framework for python. There are other tools available in Python. And several other approaches are available when you want to deal with automating the crawling of web sites. Note that you can also try to scrape the screens of legacy terminal-based applications with the help of python (this is called “screen scraping”). Some approaches of web crawling automation rely on recording the behaviour of a user equipped with a web browser and then reproduce this same behaviour in an automated session. That is an attractive and futuristic approach. But this implies that you find a way to guess what the intended automatic crawling behaviour will be from a simple example. In other words, with this approach, you have either to ask the user to click on every web link (all the job postings…) and this gives no value to the automation of the task. Or your system “guesses” what automatic behaviour is expected just by recording a sample of what a human agent would do. Too complex… So I preferred a more down-to-earth solution implying that you write simple crawling scripts “by hand”. (You may still be interested in automatically record user sessions in order to be more productive when producing your crawling scripts.) As a summary : my approach is fully based on mechanize so you may consider the following code as example of uses of mechanize in “real-world” situations.

For purpose of clarity, let’s first focus on the code part that is specific to your crawling session (to the site you want to crawl) . Let’s take the example of the dvspot.com site which you may try to crawl in order to download detailed description of camcorders :

    # Go to home page
    #
    b.open("http://www.dvspot.com/reviews/cameraList.php?listall=1&start=0")
    #
    # Navigate through the paginated list of cameras
    #
    next_page = 0
    while next_page == 0:
     #
     # Display and save details of every listed item
     #
     url = b.response.url
     next_element = 0
     while next_element >= 0:
      try:
       b.follow_link(url_regex=re.compile(r"cameraDetail"), nr=next_element)
       next_element = next_element + 1
       print save_response(b,"dvspot_camera_"+str(next_element))
       # go back to home page
       b.open(url)
       # if you crawled too many items, stop crawling
       if next_element*next_page > MAX_NR_OF_ITEMS_PER_SESSION:
          next_element = -1
          next_page = -1
      except LinkNotFoundError:
       # You certainly reached the last item in this page
       next_element = -1
    #
     try:
      b.open(url)
      b.follow_link(text_regex=re.compile(r"Next Page"), nr=0)
      print "processing Next Page"
     except LinkNotFoundError:
      # You reached the last page of the listing of items
      next_page = -1

You noticed that the structure of this code (conditional loops) depends on the organization of the site you are crawling (paginated results, …). You also have to specify the rule that will trigger “clicks” from your crawler. In the above example, your script first follows every link containing “cameraDetail” in its URL (url_regex). Then it follows every link containing “Next Page” in the hyperlink text (text_regex).

This kind of script is usually easy to design and write but it can become complex when the web site is improperly designed. There are two sources of difficulties. The first one is bad HTML. Bad HTML may crash the mechanize framework. This is the reason why you often have to pre-process the HTML either with the help of a HTML tidying library or with simple but string substitutions when your tidy library breaks the HTML too much (this may be the case when the web designer improperly decided to used nested HTML forms). Designing the proper HTML pre-processor for the Web site you want to crawl can be tricky since you may have to dive into the faulty HTML and the mechanize error tracebacks in order to identify the HTML mistakes and workaround them. I hope that future versions of mechanize would implement more robust HTML parsing capabilities. The ideal solution would be to integrate the Mozilla HTML parsing component but I guess this will be some hard work to do. Let’s cross our fingers.

Here are useful examples of pre-processors (as introduced by some other mechanize users and developpers) :

class TidyProcessor(BaseProcessor):
      def http_response(self, request, response):
          options = dict(output_xhtml=1,
                   add_xml_decl=1,
                   indent=1,
                   output_encoding='utf8',
                   input_encoding='latin1',
                   force_output=1
                   )
          r = tidy.parseString(response.read(), **options)
          return FakeResponse(response, str(r))
      https_response = http_response
#
class MyProcessor(BaseProcessor):
      def http_response(self, request, response):
          r = response.read()
          r = r.replace('"image""','"image"')
          r = r.replace('"','"')
          return FakeResponse(response, r)
      https_response = http_response
#
# Open a browser and optionally choose a customized HTML pre-processor
b = Browser()
b.add_handler(MyProcessor())

The second source of difficulties comes from non-RESTful sites. As an example the APEC site (a French Monster-like job site) is based on a proprietary web framework that implies that you cannot rely on links URLs to automate your browsing session. It took me some time to understand that, once loggin in, every time you click on a link, you are presented with a new frameset referring to the URLs that contain the interesting data you are looking for. And these URLs seem to be dependent on your session. No permalink, if you prefer. This makes the crawling process even more tricky. In order to deal with this source of difficulty when you write your crawling script, you have to open both your favorite text editor (to write the script) and your favorite web browser (Firefox of course !). One key knowledge is to know mechanize “find_link” capabilities. These capabilities are documented in _mechanize.py source code, in the find_link method doc strings. They are the arguments you will provide to b.follow_link in order to automate your crawler “clicks”. For more convenience, let me reproduce them here :

  • text: link text between link tags: <a href=”blah”>this bit</a> (as
    returned by pullparser.get_compressed_text(), ie. without tags but
    with opening tags “textified” as per the pullparser docs) must compare
    equal to this argument, if supplied
  • text_regex: link text between tag (as defined above) must match the
    regular expression object passed as this argument, if supplied
    name, name_regex: as for text and text_regex, but matched against the
    name HTML attribute of the link tag
  • url, url_regex: as for text and text_regex, but matched against the
    URL of the link tag (note this matches against Link.url, which is a
    relative or absolute URL according to how it was written in the HTML)
  • tag: element name of opening tag, eg. “a”
    predicate: a function taking a Link object as its single argument,
    returning a boolean result, indicating whether the links
  • nr: matches the nth link that matches all other criteria (default 0)

Links include anchors (a), image maps (area), and frames (frame,iframe).

Enough with explanations. Now comes the full code in order to automatically download camcorders descriptions from dvspot.com. I distribute this code here under the GPL (legally speaking, I don’t own the copyleft of this entire code since it is based on several snippets I gathered from the web and wwwsearch mailing list). Anyway, please copy-paste-taste !

from mechanize import Browser,LinkNotFoundError
from ClientCookie import BaseProcessor
from StringIO import StringIO
# import tidy
#
import sys
import re
from time import gmtime, strftime
#
# The following two line is specific to the site you want to crawl
# it provides some capabilities to your crawler for it to be able
# to understand the meaning of the data it is crawling ;
# as an example for knowing the age of the crawled resource
#
from datetime import date
# from my_parser import parsed_resource
#
"""
 Let's declare some customized pre-processors.
 These are useful when the HTML you are crawling through is not clean enough for mechanize.
 When you crawl through bad HTML, mechanize often raises errors.
 So either you tidy it with a strict tidy module (see TidyProcessor)
 or you tidy some errors you identified "by hand" (see MyProcessor).
 Note that because the tidy module is quite strict on HTML, it may change the whole
 structure of the page you are dealing with. As an example, in bad HTML, you may encounter
 nested forms or forms nested in tables or tables nested in forms. Tidying them may produce
 unintended results such as closing the form too early or making it empty. This is the reason
 you may have to use MyProcessor instead of TidyProcessor.
"""
#
class FakeResponse:
      def __init__(self, resp, nudata):
          self._resp = resp
          self._sio = StringIO(nudata)
#
      def __getattr__(self, name):
          try:
              return getattr(self._sio, name)
          except AttributeError:
              return getattr(self._resp, name)
#
class TidyProcessor(BaseProcessor):
      def http_response(self, request, response):
          options = dict(output_xhtml=1,
                   add_xml_decl=1,
                   indent=1,
                   output_encoding='utf8',
                   input_encoding='latin1',
                   force_output=1
                   )
          r = tidy.parseString(response.read(), **options)
          return FakeResponse(response, str(r))
      https_response = http_response
#
class MyProcessor(BaseProcessor):
      def http_response(self, request, response):
          r = response.read()
          r = r.replace('"image""','"image"')
          r = r.replace('"','"')
          return FakeResponse(response, r)
      https_response = http_response
#
# Open a browser and optionally choose a customized HTML pre-processor
b = Browser()
b.add_handler(MyProcessor())
#
""""
 Let's declare some utility methods that will enhance mechanize browsing capabilities
"""
#
def find(b,searchst):
    b.response.seek(0)
    lr = b.response.read()
    return re.search(searchst, lr, re.I)
#
def save_response(b,kw='file'):
    """Saves last response to timestamped file"""
    name = strftime("%Y%m%d%H%M%S_",gmtime())
    name = name + kw + '.html'
    f = open('./'+name,'w')
    b.response.seek(0)
    f.write(b.response.read())
    f.close
    return "Response saved as %s" % name
#
"""
Hereafter is the only (and somewhat big) script that is specific to the site you want to crawl.
"""
#
def dvspot_crawl():
    """
     Here starts the browsing session.
     For every move, I could have put as a comment an equivalent PBP command line.
     PBP is a nice scripting layer on top of mechanize.
     But it does not allow looping or conditional browsing.
     So I preferred scripting directly with mechanize instead of using PBP
     and then adding an additional layer of scripting on top of it.
    """
#
    MAX_NR_OF_ITEMS_PER_SESSION = 500
    #
    # Go to home page
    #
    b.open("http://www.dvspot.com/reviews/cameraList.php?listall=1&start=0")
    #
    # Navigate through the paginated list of cameras
    #
    next_page = 0
    while next_page == 0:
     #
     # Display and save details of every listed item
     #
     url = b.response.url
     next_element = 0
     while next_element >= 0:
      try:
       b.follow_link(url_regex=re.compile(r"cameraDetail"), nr=next_element)
       next_element = next_element + 1
       print save_response(b,"dvspot_camera_"+str(next_element))
       b.open(url)
       # if you crawled too many items, stop crawling
       if next_element*next_page > MAX_NR_OF_ITEMS_PER_SESSION:
          next_element = -1
          next_page = -1
      except LinkNotFoundError:
       # You reached the last item in this page
       next_element = -1
    #
     try:
      b.open(url)
      b.follow_link(text_regex=re.compile(r"Next Page"), nr=0)
      print "processing Next Page"
     except LinkNotFoundError:
      # You reached the last page of the listing of items
      next_page = -1
    #
    return
#
#
#
if __name__ == '__main__':
#
    """ Note that you may need to specify your proxy first.
    On windows, you do :
    set HTTP_PROXY=http://proxyname.bigcorp.com:8080
    """
    #
    dvspot_crawl()

In order to run this code, you will have to install mechanize 0.0.8a, pullparser 0.0.5b, clientcookie 0.4.19, clientform 0.0.16 and utidylib. I used Python 2.3.3. Latest clientcookie’s version was to be integrated into Python 2.4 I think. In order to install mechanize, pullparser, clientcookie and clientform, you just have to do the usual way :

python setup.py build
python setup.py install
python setup.py test

Last but not least : you should be aware that you may be breaking some terms of service from the website you are trying to crawl. Thanks to dvspot for providing such valuable camcorders data to us !

Next part will deal with processing the downloaded HTML pages and extract useful data from them.

Web scraping with Python

Friday, September 3rd, 2004

Here is a set of resources for scraping the web with the help of Python. The best solution seems to be Mechanize plus Beautiful Soup.

See also :

Off-topic : proxomitron looks like a nice (python-friendly ?) filtering proxy.

PHP pour des sites Web de grande échelle

Saturday, April 10th, 2004

Phil Windley a provoqué une discussion au sujet de la capacité de montée en charge de PHP. Une discussion intéressante car elle réunit en peu de messages l’essentiel des arguments en jeu.

Popularité des technologies et état de l’art des architectures applicatives

Monday, March 22nd, 2004

Encore des indicateurs sur la popularité de telle ou telle technologie Web à travers le comptage des modules Apache les plus couramment rencontrés sur le Net. Et puis, tant que j’y suis, un état de l’art des architectures applicatives en 2002.

Python compared to Smalltalk

Wednesday, March 17th, 2004

Python has many similarities with Smalltalk. Maybe one can say that Python is the Smalltalk of the Web. Here are some resources that compare Python with Smalltalk :

La folie des démarches qualité

Thursday, March 11th, 2004

CMMI, Six Sigma, CobiT, ITIL, ISO 9000, c’est la folie des modèles pour la gestion de la qualité en informatique. Prenez des repères avec cet article.

Exploiter .Net avec le langage Python

Thursday, March 11th, 2004

Jon Udell fait le point sur les possibilités d’utiliser le langage Python pour tirer profit des classes .Net ou Java. Pour exploiter les classes Java depuis Python, l’environnement d’exécution Jython a déjà fait ses preuves et conquis un public important. Pour .Net, les choses sont plus difficiles mais les tentatives évoquées par Jon Udell semblent prometteuses.

L’évaluation de l’accessibilité

Monday, March 8th, 2004

L’évaluation de l’accessibilité est quelque chose de facile à faire et qui peut permettre à n’importe quel développeur Web de corriger son site Web pour que même les personnes souffrant d’un handicap puissent l’utiliser sans difficulté.

LAMP pour les projets critiques

Tuesday, February 17th, 2004

Le modèle L.A.M.P. (Linux + Apache + MySQL + PHP/Python/Perl) a maintenant acquis de solides références auprès de grands comptes et ce, sur des projets critiques. C’est ce que commence à rapporter la presse informatique, malgré l’intérêt que les gros du conseil ont à promouvoir des technologies concurrentes. LAMP serait positionné non pas comme un concurrent de J2EE et .Net mais comme une solution idéale pour “la couche de présentation de projets critiques d’envergure tout en couvrant tous les besoins des projets départementaux”.

Différence entre approche orientée-objet et approché orientée-message

Tuesday, February 17th, 2004

Parmi les trois technologies fondamentales du génie logiciels (relationnel, objets et message), Uche Ogbuji souligne les différences entre orienté-objet (incarné notamment par Java) et langages de programmation “agiles” pour XML (incarné notamment par Python). Il évoque, pour une approche orientée message (XML), des méthodologies de développements dites “D4″ comme Dynamique, Déclaratif et Dirigé par les Données. Pour lui, l’absolutisme objet a de effets pervers paradoxaux : moindre maintenabilité et moindre réutilisabilité du code. Il ne présente pas la modélisation orientée message comme une panacée mais comme une approche distincte de l’approche objet, et qui se révèle plus efficace pour traiter certains types de problèmes. Bref, à chaque cas sa bonne approche de modélisation : parfois relationnel, parfois objet, parfois message.

Les trois technologies fondamentales du génie logiciel

Monday, February 16th, 2004

Trois technologies fondamentales sont nécessaires à l’architecte qui prétend maîtriser le génie logiciel : l’orienté-objet, le relationnel et l’orienté-message. Si l’une de ces trois compétences vous fait défaut, vous risquez de vous casser la figure. Et aujourd’hui, les technologies orientées message (XML) manquent encore un peu de maturité.

Authentification pour Atom

Monday, February 16th, 2004

Atom est un protocole de syndication de contenu concurrent de RSS. Il s’agit d’une invention bien pensée (quoique la méfiance de ses concepteurs à l’égard de RDF me laisse perplexe) mais dont le succès reste à mesurer. Toujours est-il qu’il fallait bien accompagner ce protocole d’une solution convenable pour assurer l’authentification des agents aggrégateurs de contenu. Et comme l’authentification HTTP basique ne pouvait pas convenir, Atom recourt à une extension de cette authentification appuyée sur la technologie WSSE. Résultat : une authentification HTTP qui ne requiert ni installation de modules Apache, ni accès aux fichiers .htaccess et permet une utilisation en environnement mutualisé, via des CGIs, le tout avec un bon niveau général de sécurité.

Introduction à ZETADB

Monday, February 16th, 2004

Le produit ZETADB permet de faire du développement rapide d’applications Web dans l’environnement Zope. Voici un document d’introduction pour apprendre à utiliser ce produit. C’est effectivement assez simple.

Qu’est-ce que le couplage faible ?

Monday, February 9th, 2004

Qu’est-ce que le “couplage faible” ? Le couplage faible, c’est “comme la pornographie” : tout le monde en parle, mais c’est bien difficile à définir :

Je n’essaierai pas aujourd’hui de définir ce qu’est la pornographie… mais je sais que c’en est lorsque j’en vois.

Citation du juge Potter Stewart de la Cour Suprême des USA dans l’affaire Jacobellis contre l’Etat d’Ohio, en 1964.

SolutionsLinux 2004

Friday, February 6th, 2004

Ouhla, la, quel salon que Solutions Linux 2004 ! Rien de que des gens très intéressants :

  • le directeur d’une SS2L qui a atterri à ce poste après de nombreuses années de bons et loyaux services au sein d’un groupe du CAC40 qui m’emploie actuellement et qui est réputé pour sa gestion “bon père de famille”, ou comment reprendre une société qui a été mal en point en nommant à sa tête une personne incarnant l’idée de “croissance durable”,
  • un réseau d’ “entreprises agiles” (Ingeniweb, Pilot Systems, Blue Dynamics, …), les Zope Service Providers de l’EuroZope Association, animé par le gourouisé Paul Everitt
  • Paul Everitt lui-même, qui non seulement déniche grâce à son réseautage permanent des projets commerciaux qui me font baver d’envie, mais prophétise également avec conviction un bel avenir pour les ZSP
  • d’autres spécialistes Zope mais qui n’ont pas rejoint le courant Plone ; je retiens notamment le travail de la société Emencia sur le léger Zwook ; Zwook cible la gestion de contenu plus bas de gamme que Plone (ce n’est pas péjoratif) : morale de l’histoire, bien que moins flexible et moins puissant, Zwook offre des fonctionnalités intuitives (quoique d’ergonomie moyenne) qui permettent par exemple de créer/modifier des skins via le Web sans avoir à toucher une ligne de code (sans bidouilles les ZPT ni même les CSS). Mais ce n’est sans doute qu’une question de temps avant que Plone propose quelque chose d’équivalent.
  • la SS2L (Société de Services en Logiciels Libres) Linagora qui m’a impressionné par son expérience autour de la gestion d’annuaires ; ils semblent avoir développé une approche open source de la problématique de la gestion des droits ainsi que de l’intégration de données d’annuaires (méta-annuaires) qui semble empreinte de pragmatisme, mais si elle manque de maturité pour donner lieu à la distribution de produits bien packagés pour y répondre.
  • des copains d’école ! Chez Nexen, on fait aussi dans la “croissance durable” et leur réputation dans le monde PHP francophone n’est plus à faire ; on annonce la publication d’un magazine ciblant les usages de PHP dans le monde de l’entreprise… prometteur !
  • une preuve vivante que le monde est petit : sur le stand de mes copains d’école, j’ai croisé un type qui a eu le culot de me prétendre que l’offre de Gitoyen était pourrie et que les gens de Globenet étaient tous des nazes incompétents alors que primo ce sont aussi des copains à moi et secondo j’admire leur présence au sein le monde associatif ; il m’a suffit de l’entendre pour comprendre qu’il s’agissait du dévoué Benjamin, maître des systèmes de Globenet ! heureux d’avoir enfin pu mettre un visage sur ton nom Benjamin.
  • le Monsieur Linux d’IBM pour l’Europe de l’Ouest avec qui j’ai eu une discussion très intéressante sur l’avenir de l’open source vu par LE géant de l’informatique : linux est un standard incontournable pour qui veut maintenir son leadership sur le marché. Par contre, autant les solutions open source pour l’infrastructure et la sécurité ont fait leurs preuves, autant l’offre open source sur la couche applicative n’est pas encore assez visible sur le marché pour retenir l’attention des titans. Et c’est délibérément qu’IBM ne veut pas anticiper les choses en la matière et se contente de se concentrer sur l’infra, en lorgnant un peu du côté du poste de travail histoire de suivre les initiatives de Novell et de SUN. D’où la juste prophétie de Paul Everitt :
    I picked a deal size (50-250k) that excludes the Sapients and IBMs. That’s just too small for their radar. Which is good, because (sadly) as open source crosses the chasm into the mainstream market, the new customers are going to want a cathedral on the supplier side to balance the bazaar on the software side.
    I say sad, because it means spectators will show up, after all the small companies did all the work, and these big boys will take all the money. I think this is unfair. But, so what, life is unfair, and this happens all the time.

  • des gens de chez Jouve, tiens, tiens… mais eux aussi intéressés sans doute avant tout par les offres pour l’infrastructure plus que pour l’applicatif

Bref, un salon stimulant et qui promet des années à venir riches en rebondissements pour l’avenir de l’open source dans la couche applicative.

Le SuperGuide pour débutants Zope

Monday, February 2nd, 2004

Voici le SuperGuide Zope pour débutants offert par ZopeMag.

Clavier virtuel UNICODE

Monday, February 2nd, 2004

Pour faire un annuaire international qui identifie les gens de manière permanente (même si la personne s’en va et revient, on sait que c’est bien la même personne), rien de mieux que de s’appuyer sur le prénom, le nom et la date de naissance de l’individu. Quel nom ? Le nom d’état civil de naissance et pas un autre. Dans quel alphabet ? Dans l’alphabet “officiel” de l’état civil de naissance de l’invididu ! En effet, M. Müller en Allemagne risque de se faire appeler M. Mueller en France. Et telle personne née en Chine aura du mal à faire saisir sous nom sous forme idéographique dans un système de paye français… Morale de l’histoire, il faut recourir à la translitération et normaliser celle-ci (ISO proposent un certain nombre de normes en la matière). Mais les difficultés ne sont pas terminées. Car pour pouvoir garantir la normalité de la translitération, il est nécessaire de ne pas laisser tout un chacun procéder à la translitération. Il est donc nécessaire de disposer d’un service centralisé de translitération (une appli web). Et pour pouvoir tout de même saisir les prénom et nom de l’individu dans son alphabet d’origine dans cette machine à translitérer, encore faut-il pouvoir saisir des caractères et idéogrammes non supportés par le clavier de l’opérateur de saisie. Là encore, il y a des solutions : les claviers virtuels UNICODE. Ces petits morceaux de code permettent d’afficher un clavier virtuel dans un navigateur Web, clavier supportant tous les jeux de caractères existant (dans la norme UNICODE). Voici les claviers virtuels UNICODE que j’ai repérés :

Ticle and Rope

Saturday, January 31st, 2004

The Ticle project is going on. It tries to add semantic abilities to Plone. But do the Ticle guys realize that they are kind of reinventing RDF ? or is it just me ? Wouldn’t they better rely on an existing RDF implementation as the ROPE project is trying to do on a lower layer (trying to equip Zope instead of Plone) ? I’m confused… and impatient to see a semantic Plone (or even Zope) in action ! Anyway, keep on the enthusiastic work guys !

Développement externalisé à l’offshore

Wednesday, January 28th, 2004

Vincent Massol, un ancien d’Octo Technologies semble-t-il, fait le point sur l’utilisation des méthodes de développement dites “agiles” dans le cadre de projets de développement externalisés à l’offshore. J’avoue que je n’ai pas encore consulté cet entretien (video). Mais j’ai déjà lu la discussion qui s’en est suivie. J’en retiens les points suivants :

  • les outils d’issue tracking jouent un rôle déterminant dans la mise en place d’un processus efficace de communication avec le sous-traitant
  • à l’offshore, il est plus difficile (voire impossible) pour un chef de projet de deviner l’aisance ou les difficultés rencontrées par les développeurs au quotidien ; d’où le risque de passer à côté d’erreurs graves
  • même en faisant des itérations rapides (livraisons toutes les 2 semaines), il est nécessaire de formaliser (via UML par exemple) les use cases de manière détaillée à chaque itération
  • de fréquents voyages allers-retours sont nécessaires
  • l’équipe offshore doit avoir un chef d’équipe : il n’est pas possible de gérer des relations individuelles multiples à distance
  • il est nécessaire d’avoir des cycles de livraisons courts et d’intégrer chaque livraison de manière continue
  • les tests doivent constituer “l’ultime documentation”
  • les décalages horaires constituent davantage un frein qu’un facteur positif
  • les logiciels de messagerie instantanée sont un moyen très apprécié de coordination quotidienne
  • dès qu’une personne sur site doit travailler en relation avec une personne distante, il est nécessaire d’organiser une rencontre physique préalable faute de quoi la relation interpersonnelle ne peut s’établir correctement et le travail échoue
  • le moindre détail doit être documenté, jusqu’à la position de chaque bouton à l’écran, la police des libellés affichés, etc. faute de quoi la société offshore qui travaille au forfait fournira un résultat ayant des “finitions” défectueuses
  • il est souhaitable d’organiser une réunion quotidienne d’une durée d’au moins une demi-heure avec téléphone + videoconf ou chat + videoconf, à l’heure qui convient le mieux aux deux équipes ; cette réunion doit être préparée à l’avance chaque jour et, sauf exception planifiée, la réunion doit s’interdire tout travail du type “brain storming” (ce n’est pas une réunion de créativité)
  • les échanges en vue de créativité “brain storming” doivent avoir lieu sous forme de texte (wikis, mails, chat, …)

Le carnet Web DCLab fournit des notes et indications complémentaires pour bien travailler avec des sociétés à l’offshore.
Mais… j’apprends que ma société revient sur ses ambitions initiales d’externalisation à l’offshore et adopte un discours plus prudent suite à quelques expérimentations et, surtout, suite à l’apparition d’objectifs stratégiques considérés comme plus prioritaires que l’externalisation à l’offshore. Les inquiétudes sociales liées à la délocalisation d’emplois informatiques contribuent sans doute à ce revirement. Est-ce un signe des temps ? Le signe que les sociétés ajusteraient leurs ambitions aux possibilités réelles des modes de fonctionnement avec des sociétés offshore ? Ou bien le signe d’une prudence dans le discours pour ne pas effrayer la populace ? Ou tout simplement le signe que le gain à espérer de l’externalisation à l’offshore ne suffit pas à placer ce genre d’opérations parmi les top priorités d’une direction informatique ? L’avenir le dira sans doute.

Sortir de Microsoft Access

Wednesday, January 21st, 2004

Comment extirper le contenu (tables, requêtes, formulaires, états, macros, modules, …) d’une base Access pour le faire migrer vers une base plus saine en vue d’en faire une appli Web ? Il existe plusieurs logiciels qui permettent d’effectuer l’opération d’export :

  • MDBTools, logiciel libre (licence GPL) en version beta, fonctionne sous linux
  • DBTools, freeware qui permet d’importer dans MySQL des schémas et données provenant d’Access, sans requérir de connexion ODBC
  • MySQLFront, freeware similaire à DBTools, permet d’importer des schémas et données dans MySQL, requiert une connexion ODBC à Access, mais ne serait plus supporté par son auteur
  • Access converter, Java Edition, 695$, convertit en Java les macros, modules et autre code VB d’une application Access, convertit les états Access en états Crystal Reports, mais ne semble pas faire migrer les tables et requêtes
  • Access to MySQL v.1.5, shareware à 39.85 $, fonctionne sous Windows, n’extrait que les tables (et sans les jointures), importe le schéma dans une base MySQL
  • MyAccess, shareware. de 30$, add-in pour Access qui convertit le schéma de données en schéma MySQL à condition de disposer d’une connexion ODBC vers la base MySQL cible, ne semble faire migrer que les tables et peut-être les requêtes

Une explication de la problématique de migration d’applications Access est proposée ici. Voir aussi ceci.