Comment extraire et analyser les données de fichiers PDF en R
Besoin d’extraire les textes de fichiers PDF ?
Vous êtes au bon endroit !
Note : Dans cet article, on traite des fichiers PDF qui sont lisibles par la machine. Si ce n’est pas votre cas, je recommande un usage préalable de Adobe Acrobat Pro qui le fera automatiquement pour vous. Ensuite, revenez ici.
Dans cet article, on va apprendre à :
- Extraire le contenu d’un fichier PDF en R (deux techniques)
- Nettoyer le résultat afin de pouvoir lancer des analyses sémantiques
D’abord je vais expliquer les outils que j’utilise, et ensuite je vous montrerai comment faire sur des exemples.
Pourquoi des fichiers PDF ?
Lorsque j’ai commencé à travaillé en freelance, j’ai fait pas mal de missions qui consistaient à simplement extraire les données contenues dans des fichiers PDF.
Mes clients avaient en général deux options : Soit le faire manuellement, soit trouver un moyen d’automatiser la tâche.
La première était en général pénible et coûteux (en temps ou en personnel) au vu du nombre de fichiers à extraire. Des milliers au minimum.
Du coup, je les aidais à mettre en place la deuxième option.
Par exemple, un client avait des milliers de factures qui avaient toutes la même structure et il voulait extraire :
- le nombre de produits vendus,
- le montant de chaque facture
- les données de ses clients
Sauf qu’avoir tout en PDF n’était pas pratique.
Lui, il voulait une spreadsheet propre où plus tard il pourra facilement voir qui a acheté quoi, combien, et faire des calculs. Même tout simplement faire sa compta.
Un autre exemple classique est cet autre client qui voulait analyser des documents officiels, par exemple des discours à l’ONU.
Pareil, tout était sous forme PDF, donc j’ai eu besoin de tout extraire.
Alors, par où on commence ?
Deux techniques pour extraire le texte des fichiers PDF
Première technique : `pdftools::pdf_text`
La première technique requier l’utilisation du package pdftools
disponible sur le CRAN :
Un rapide coup d’œil à la documentation vous montrera les quelques fonctions du package.
La plus importante est pdf_text
.
Dans cet article, je vais utiliser un article de l’ONU que vous pouvez trouver à l’adresse suivante : https://github.com/Huitziii/crispy-pdf/raw/master/71_PV.62.pdf
La fonction pdf_text
va directement importer le text brut sous la forme d’un vecteur de type character avec des espaces pour représenter l’espace vide et des \n
pour les sauts de ligne.
Avoir toute la page dans un seul élément est pas vraiment super pratique.
Du coup, on va utiliser strsplit
pour séparer les lignes les unes des autres :
Si vous voulez en savoir plus sur les fonctions du package pdftools
, je vous recommande la lecture de Introducing pdftools - A fast and portable PDF extractor, un article écrit par l’auteur du package lui-même.
Deuxième technique : Le package `tm`
tm
c’est le package cible quand on veut faire de l’analyse sémantique en R
Le côté pratique, c’est qu’il va nous permettre d’importe notre document PDF en R tout en gardant sa structure intact. Et en plus, il sera dans un objet tout prêt pour les analyses à faire ensuite.
Il existe une fonction readPDF
, mais elle ne permet pas directement de lire un fichier PDF comme dans la partie précédente.
À la place, elle va nous permettre de créer notre propre fonction de lecteur PDF. L’avantage, c’est qu’on peut utiliser le driver PDF qu’on veut.
Par défaut, il va utiliser xpdf
, disponible sur http://www.xpdfreader.com/download.html.
Il faut :
- Télécharger l’archive à partir du site web (dans la section Xpdf tools)
- La dézipper
- S’assurer qu’elle est dans le PATH du système.
Ensuite, on peut créer notre fonction extracteur de PDF :
L’argument control
permet de spécifier les paramètres comme si on était en ligne de commande. Donc là, c’est comme si on avait écrit xpdf -layout
dans le shell.
À présent, on est prêt à importer le document PDF !
La différence majeure par rapport à la première méthode est que de nouvelles lignes vides sont apparues, ce qui est plus fidèle au document original.
Par exemple, ça peut nous aider à savoir quand se termine l’en-tête.
Une autre différence est la manière dont les pages sont gérées. Avec cette méthode, on a directement tout le texte dans l’objet et les sauts de page sont symbolisés par des symboles \f
. Précédemment, on avait une liste avec 1 page = 1 élément.
On affiche ici la première ligne de la deuxième page, avec un \f
affiché devant.
Extraire l’information utile
On ne veut pas s’arrêter ici.
Une fois que vous avez le document PDF importé dans R, vous voulez extraire les morceaux de texte que vous intéresse, et vous débarrasser du reste.
C’est ce qu’on va faire tout de suite.
Pour y arriver, j’utilise des outils standards de manipulation de chaînes de caractère :
- Les fonctions
grep
etgrepl
- Des fonctions basiques de manipulations de
str
(commestr_split
) - Le package
stringr
L’objectif est d’extraire tous les discours des orateurs dans le document présenté plus tôt (celui-là), excepté que je ne veux pas les discours du président.
Je sais que si je peux le faire sur un document, alors je pourrai ensuite faire rouler mon script sur les milliers de documents que j’ai téléchargé au préalable.
Voici les étapes :
- Nettoyer les en-têtes et pieds de page sur toutes les pages.
- Concaténer les deux colonnes ensemble.
- Trouver les lignes avec les noms des orateurs.
- Extraire les bonnes lignes.
Je vais utiliser des expressions régulières (regex) à plusieurs reprises dans le code.
Si vous ne savez pas du tout ce que c’est, je vous conseille une rapide recherche Google (regex tutorial) pour comprendre un peu. C’est essential à connaître dès que vous manipulez du texte, de toute façon.
Si vous connaissez juste un tout petit peu, ça suffira, je ne suis pas un grand expert non plus.
Je vous conseille aussi, si vous voulez apprendre, de suivre les étapes en même temps que moi sur R, afin de mieux appréhender ce qu’on fait.
1. Nettoyer les en-têtes et pieds de page
Avez-vous remarqué que chaque page contient des infos en haut et en bas ?
On trouve la date, l’identifiant du document, etc.
On va se débarrasser de ça.
À présent, on a un document un peu plus propre.
La prochaine étape, c’est de rassembler les deux colonnes en une seule.
2. Concaténer les deux colonnes ensemble.
Mon idée (mais il y a d’autres manières de faire), c’est d’utiliser la fonction str_split
pour séparer chaque ligne dès qu’il y a deux espaces consécutifs (ça montre que ce n’est pas une phrase normale).
Ensuite, puisqu’il y aura plein d’espaces ensemble au début des lignes, je détecte là où il y a du texte, là où il n’y en a pas, et je sélectionne seulement les éléments avec du texte.
Vous allez voir, c’est un peu compliqué, mais ça marche :
Maintenant on met tout ensemble, grâce au marqueur page
que j’ai ajouté plus tôt :
Maintenant qu’on a un vecteur tout propre, on peut extraire les discours.
3. Trouver les lignes avec les noms des orateurs
Là il faut regarder le document d’un peu plus près et trouver les patterns qui vont nous aider à repérer là où démarrent les discours.
C’est assez facile en fait parce que tous les noms des orateurs commencent par “Mr.” ou “Mrs.”. Et le président est toujours appelé “The President:” ou “The Acting President:”.
On prend les lignes :
Maintenant c’est facile !
On sait où commencent les discours, et ils finissent toujours quand quelqu’un d’autre va parler :
Boom !
On a extrait tous les discours dans une liste.
Maintenant, on peut analyser ce que raconte chaque représentant de son pays, comment ça évolue au fil des documents, au fil des années, selon les sujets abordés, etc.
Alors oui c’est vrai que pour ce document, on aurait pu le faire à la main.
Mais imaginez que vous ayez des milliers de documents comme ça… ça devient fastidieux. Impossible même !
C’est là que ça devient fun en fait.
Même si tous les documents se ressemblent, ils vont tous avoir leurs petites spécificités, leurs petites exceptions, etc. Peut-être que le format du document va évoluer au fil des années. Parfois il y a des fautes de frappe.
En fait, même avec cette extraction, ce n’est pas parfait et on pourrait l’améliorer.
Alors au travail !
Commentaires
Laisser un commentaire
Les champs obligatoires sont marqués *