Python pas cher
Jusqu'à présent, vous avez appris à extraire du texte et des pages de fichiers PDF et à concaténer et fusionner deux fichiers PDF ou plus. Ce sont toutes des opérations courantes avec les PDF, mais PyPDF2
possède de nombreuses autres fonctionnalités utiles.
Dans cette section, vous apprendrez comment faire pivoter et rogner des pages dans un fichier PDF.
Rotation des pages
Vous allez commencer par apprendre à faire pivoter les pages. Pour cet exemple, vous utiliserez le ugly.pdf
fichier dans le practice_files
dossier. le ugly.pdf
fichier contient une belle version de Hans Christian Andersen Le vilain petit canard, sauf que chaque page impaire est tournée de quatre-vingt-dix degrés dans le sens antihoraire.
Corrigeons ça. Dans une nouvelle fenêtre interactive IDLE, commencez par importer le PdfFileReader
et PdfFileWriter
cours de PyPDF2
, aussi bien que Chemin
classe du pathlib
module:
>>> de pathlib importation Chemin
>>> de PyPDF2 importation PdfFileReader, PdfFileWriter
Créez maintenant un Chemin
objet pour le ugly.pdf
fichier:
>>> pdf_path = (
... Chemin.maison()
... / "création et modification de pdfs"
... / "practice_files"
... / "ugly.pdf"
... )
Enfin, créez de nouveaux PdfFileReader
et PdfFileWriter
instances:
>>> lecteur PDF = PdfFileReader(str(pdf_path))
>>> pdf_writer = PdfFileWriter()
Votre objectif est d'utiliser pdf_writer
pour créer un nouveau fichier PDF dans lequel toutes les pages ont la bonne orientation. Les pages paires du PDF sont déjà correctement orientées, mais les pages impaires tournent dans le sens antihoraire de quatre-vingt-dix degrés.
Pour corriger le problème, vous utiliserez PageObject.rotateClockwise ()
. Cette méthode prend un argument entier, en degrés, et fait pivoter une page dans le sens horaire de ce nombre de degrés. Par exemple, .rotateClockwise (90)
fait pivoter une page PDF de 90 degrés dans le sens des aiguilles d'une montre.
Remarque: En plus de .le sens des aiguilles d'une montre()
, le PageObject
la classe a également .rotateCounterClockwise ()
pour faire tourner les pages dans le sens antihoraire.
Il existe plusieurs façons de faire tourner les pages du PDF. Nous allons discuter de deux façons différentes de le faire. Les deux comptent sur .le sens des aiguilles d'une montre()
, mais ils adoptent différentes approches pour déterminer les pages à faire pivoter.
La première technique consiste à parcourir les index des pages du PDF et à vérifier si chaque index correspond à une page qui doit être tournée. Si oui, alors vous appellerez .le sens des aiguilles d'une montre()
pour faire pivoter la page, puis ajoutez-la à pdf_writer
.
Voici à quoi cela ressemble:
>>> pour n dans gamme(lecteur PDF.getNumPages()):
... page = lecteur PDF.getPage(n)
... si n % 2 == 0:
... page.le sens des aiguilles d'une montre(90)
... pdf_writer.ajouter une page(page)
...
Notez que la page pivote si l'index est pair. Cela peut sembler étrange car les pages impaires du PDF sont celles qui tournent incorrectement. Cependant, les numéros de page dans le PDF commencent par 1
, tandis que les index de page commencent par 0
. Cela signifie que les pages PDF impaires ont des indices pairs.
Si cela vous fait tourner la tête, ne vous inquiétez pas! Même après des années à gérer des trucs comme celui-ci, les programmeurs professionnels se font toujours tromper par ce genre de choses!
Remarque: Lorsque vous exécutez le pour
boucle ci-dessus, vous verrez un tas de sortie dans la fenêtre interactive de IDLE. C'est parce que .le sens des aiguilles d'une montre()
renvoie un PageObject
exemple.
Vous pouvez ignorer cette sortie pour l'instant. Lorsque vous exécutez des programmes à partir de la fenêtre de l'éditeur IDLE, cette sortie ne sera pas visible.
Maintenant que vous avez fait pivoter toutes les pages du PDF, vous pouvez écrire le contenu de pdf_writer
dans un nouveau fichier et vérifiez que tout fonctionne:
>>> avec Chemin("ugly_rotated.pdf").ouvert(mode="wb") comme fichier de sortie:
... pdf_writer.écrire(fichier de sortie)
...
Vous devriez maintenant avoir un fichier dans votre répertoire de travail actuel appelé ugly_rotated.pdf
, avec les pages du ugly.pdf
fichier tout tourné correctement.
Le problème avec l'approche que vous venez d'utiliser pour faire pivoter les pages dans le ugly.pdf
fichier est qu'il dépend de savoir à l'avance quelles pages doivent être tournées. Dans un scénario réel, il n'est pas pratique de parcourir un PDF entier en prenant note des pages à faire pivoter.
En fait, vous pouvez déterminer quelles pages doivent être tournées sans connaissance préalable. Bien, quelquefois vous pouvez.
Voyons comment, en commençant par un nouveau PdfFileReader
exemple:
>>> lecteur PDF = PdfFileReader(str(pdf_path))
Vous devez le faire car vous avez modifié les pages de l'ancien PdfFileReader
par exemple en les faisant tourner. Donc, en créant une nouvelle instance, vous recommencez.
PageObject
les instances gèrent un dictionnaire de valeurs contenant des informations sur la page:
>>> lecteur PDF.getPage(0)
'/Contenu':[IndirectObject(110)IndirectObject(120)[IndirectObject(110)IndirectObject(120)[IndirectObject(110)IndirectObject(120)[IndirectObject(110)IndirectObject(120)
IndirectObject (13, 0), IndirectObject (14, 0), IndirectObject (15, 0),
IndirectObject (16, 0), IndirectObject (17, 0), IndirectObject (18, 0)],
'/ Rotate': -90, '/ Resources': '/ ColorSpace': '/ CS1':
IndirectObject (19, 0), '/ CS0': IndirectObject (19, 0), '/ XObject':
'/ Im0': IndirectObject (21, 0), '/ Font': '/ TT1':
IndirectObject (23, 0), '/ TT0': IndirectObject (25, 0), '/ ExtGState':
'/ GS0': IndirectObject (27, 0), '/ CropBox': [0, 0, 612, 792],
'/ Parent': IndirectObject (1, 0), '/ MediaBox': [0, 0, 612, 792],
'/ Type': '/ Page', '/ StructParents': 0
Oui! Mélangé avec tout ce qui n'a pas de sens est une clé appelée /Tourner
, que vous pouvez voir sur la quatrième ligne de sortie ci-dessus. La valeur de cette clé est -90
.
Vous pouvez accéder au /Tourner
clé sur un PageObject
en utilisant la notation en indice, comme vous pouvez le faire sur un Python dicter
objet:
>>> page = lecteur PDF.getPage(0)
>>> page[[[["/Tourner"]
-90
Si vous regardez le /Tourner
clé pour la deuxième page lecteur PDF
, vous verrez qu'il a une valeur de 0
:
>>> page = lecteur PDF.getPage(1)
>>> page[[[["/Tourner"]
0
Tout cela signifie que la page à l'index 0
a une valeur de rotation de -90
degrés. En d'autres termes, il a été tourné de 90 degrés dans le sens antihoraire. La page à l'index 1
a une valeur de rotation de 0
, il n'a donc pas du tout été tourné.
Si vous faites pivoter la première page à l'aide de .le sens des aiguilles d'une montre()
, alors la valeur de /Tourner
changements depuis -90
à 0
:
>>> page = lecteur PDF.getPage(0)
>>> page[[[["/Tourner"]
-90
>>> page.le sens des aiguilles d'une montre(90)
>>> page[[[["/Tourner"]
0
Maintenant que vous savez comment inspecter /Tourner
, vous pouvez l'utiliser pour faire pivoter les pages ugly.pdf
fichier.
La première chose que vous devez faire est de réinitialiser votre lecteur PDF
et pdf_writer
des objets afin de prendre un nouveau départ:
>>> lecteur PDF = PdfFileReader(str(pdf_path))
>>> pdf_writer = PdfFileWriter()
Maintenant, écrivez une boucle qui boucle sur les pages du pdf_reader.pages
itérable, vérifie la valeur de /Tourner
et fait pivoter la page si cette valeur est -90
:
>>> pour page dans lecteur PDF.pages:
... si page[[[["/Tourner"] == -90:
... page.le sens des aiguilles d'une montre(90)
... pdf_writer.ajouter une page(page)
...
Non seulement cette boucle est légèrement plus courte que la boucle de la première solution, mais elle ne repose sur aucune connaissance préalable des pages à faire pivoter. Vous pouvez utiliser une boucle comme celle-ci pour faire pivoter des pages dans n'importe quel PDF sans jamais avoir à l'ouvrir et à le regarder.
Pour terminer la solution, écrivez le contenu de pdf_writer
vers un nouveau fichier:
>>> avec Chemin("ugly_rotated2.pdf").ouvert(mode="wb") comme fichier de sortie:
... pdf_writer.écrire(fichier de sortie)
...
Vous pouvez maintenant ouvrir le ugly_rotated2.pdf
fichier dans votre répertoire de travail actuel et le comparer au ugly_rotated.pdf
fichier que vous avez généré précédemment. Ils devraient être identiques.
Remarque: Un mot d'avertissement sur la /Tourner
clé: il n'est pas garanti d'exister sur une page.
Si la /Tourner
n'existe pas, cela signifie généralement que la page n'a pas été tournée. Cependant, ce n'est pas toujours une hypothèse sûre.
Si un PageObject
n'a pas /Tourner
clé, puis un KeyError
sera levé lorsque vous essayez d'y accéder. Vous pouvez intercepter cette exception avec un essayez ... sauf
bloquer.
La valeur de /Tourner
peut ne pas toujours être ce que vous attendez. Par exemple, si vous numérisez un document papier avec la page tournée de quatre-vingt-dix degrés dans le sens antihoraire, le contenu du PDF apparaîtra pivoté. Cependant, le /Tourner
la clé peut avoir la valeur 0
.
C'est l'une des nombreuses bizarreries qui peuvent rendre frustrant le travail avec les fichiers PDF. Parfois, il vous suffit d'ouvrir un PDF dans un programme de lecture de PDF et de comprendre manuellement les choses.
Pages de recadrage
Une autre opération courante avec les PDF est le recadrage des pages. Vous devrez peut-être effectuer cette opération pour diviser une seule page en plusieurs pages ou pour extraire uniquement une petite partie d'une page, telle qu'une signature ou une figure.
Par exemple, le practice_files
dossier comprend un fichier appelé half_and_half.pdf
. Ce fichier PDF contient une partie du texte de Hans Christian Andersen La petite Sirène.
Chaque page de ce PDF comporte deux colonnes. Divisons chaque page en deux pages, une pour chaque colonne.
Pour commencer, importez le PdfFileReader
et PdfFileWriter
cours de PyPDF2
et le Chemin
classe du pathlib
module:
>>> de pathlib importation Chemin
>>> de PyPDF2 importation PdfFileReader, PdfFileWriter
Créez maintenant un Chemin
objet pour le half_and_half.pdf
fichier:
>>> pdf_path = (
... Chemin.maison()
... / "création et modification de pdfs"
... / "practice_files"
... / "half_and_half.pdf"
... )
Ensuite, créez un nouveau PdfFileReader
objet et obtenez la première page du PDF:
>>> lecteur PDF = PdfFileReader(str(pdf_path))
>>> première page = lecteur PDF.getPage(0)
Pour recadrer la page, vous devez d'abord en savoir un peu plus sur la structure des pages. PageObject
des exemples comme première page
avoir un .mediaBox
attribut qui représente une zone rectangulaire définissant les limites de la page.
Vous pouvez utiliser la fenêtre interactive d'IDLE pour explorer la .mediaBox
avant de l'utiliser recadrez la page:
>>> première page.mediaBox
RectangleObject ([0, 0, 792, 612])
le .mediaBox
l'attribut renvoie un RectangleObject
. Cet objet est défini dans le PyPDF2
package et représente une zone rectangulaire sur la page.
La liste [0, 0, 792, 612]
dans la sortie définit la zone rectangulaire. Les deux premiers nombres sont les coordonnées x et y du coin inférieur gauche du rectangle. Les troisième et quatrième chiffres représentent respectivement la largeur et la hauteur du rectangle. Les unités de toutes les valeurs sont des points, qui sont égaux à 1/72 de pouce.
RectangleObject ([0, 0, 792, 612])
représente une région rectangulaire avec le coin inférieur gauche à l'origine, une largeur de 792
points, ou 11 pouces, et une hauteur de 612 points, ou 8,5 pouces. Ce sont les dimensions d'une page au format lettre standard en orientation paysage, qui est utilisée pour l'exemple PDF de La petite Sirène. Une page PDF de format lettre en orientation portrait renverrait la sortie RectangleObject ([0, 0, 612, 792])
.
UNE RectangleObject
possède quatre attributs qui renvoient les coordonnées des coins du rectangle: .en bas à gauche
, .en bas à droite
, .en haut à gauche
, et .En haut à droite
. Tout comme les valeurs de largeur et de hauteur, ces coordonnées sont données en points.
Vous pouvez utiliser ces quatre propriétés pour obtenir les coordonnées de chaque coin de la RectangleObject
:
>>> première page.mediaBox.en bas à gauche
(0, 0)
>>> première page.mediaBox.en bas à droite
(792, 0)
>>> première page.mediaBox.en haut à gauche
(0, 612)
>>> première page.mediaBox.En haut à droite
(792, 612)
Chaque propriété renvoie un tuple
contenant les coordonnées du coin spécifié. Vous pouvez accéder aux coordonnées individuelles avec des crochets comme vous le feriez pour tout autre tuple Python:
>>> première page.mediaBox.En haut à droite[[[[0]
792
>>> première page.mediaBox.En haut à droite[[[[1]
612
Vous pouvez modifier les coordonnées d'un mediaBox
en affectant un nouveau tuple à l'une de ses propriétés:
>>> première page.mediaBox.en haut à gauche = (0, 480)
>>> première page.mediaBox.en haut à gauche
(0, 480)
Lorsque vous modifiez le .en haut à gauche
les coordonnées, .En haut à droite
l'attribut s'ajuste automatiquement pour conserver une forme rectangulaire:
>>> première page.mediaBox.En haut à droite
(792, 480)
Lorsque vous modifiez les coordonnées du RectangleObject
retourné par .mediaBox
, vous recadrez efficacement la page. le première page
L'objet contient désormais uniquement les informations présentes dans les limites du nouveau RectangleObject
.
Allez-y et écrivez la page recadrée dans un nouveau fichier PDF:
>>> pdf_writer = PdfFileWriter()
>>> pdf_writer.ajouter une page(première page)
>>> avec Chemin("cropped_page.pdf").ouvert(mode="wb") comme fichier de sortie:
... pdf_writer.écrire(fichier de sortie)
...
Si vous ouvrez le cropped_page.pdf
dans votre répertoire de travail actuel, vous verrez que la partie supérieure de la page a été supprimée.
Comment recadreriez-vous la page pour que seul le texte sur le côté gauche de la page soit visible? Vous devrez réduire de moitié les dimensions horizontales de la page. Vous pouvez y parvenir en modifiant la .En haut à droite
coordonnées du .mediaBox
objet. Voyons comment cela fonctionne.
Tout d'abord, vous devez obtenir de nouveaux PdfFileReader
et PdfFileWriter
objets puisque vous venez de modifier la première page de lecteur PDF
et l'a ajouté à pdf_writer
:
>>> lecteur PDF = PdfFileReader(str(pdf_path))
>>> pdf_writer = PdfFileWriter()
Obtenez maintenant la première page du PDF:
>>> première page = lecteur PDF.getPage(0)
Cette fois, travaillons avec une copie de la première page afin que la page que vous venez d'extraire reste intacte. Vous pouvez le faire en important le copie
module de la bibliothèque standard de Python et en utilisant copie profonde ()
pour faire une copie de la page:
>>> importation copie
>>> côté gauche = copie.copie profonde(première page)
Vous pouvez maintenant modifier côté gauche
sans changer les propriétés de première page
. De cette façon, vous pouvez utiliser première page
plus tard pour extraire le texte sur le côté droit de la page.
Maintenant, vous devez faire un peu de calcul. Vous avez déjà compris que vous devez déplacer le coin supérieur droit du .mediaBox
en haut au centre de la page. Pour ce faire, vous allez créer un nouveau tuple
avec le premier composant égal à la moitié de la valeur d'origine et l'affecter à la .En haut à droite
propriété.
Tout d'abord, obtenez les coordonnées actuelles du coin supérieur droit du .mediaBox
.
>>> current_coords = côté gauche.mediaBox.En haut à droite
Ensuite, créez un nouveau tuple
dont la première coordonnée est la moitié de la valeur de la coordonnée actuelle et la deuxième coordonnée est la même que l'original:
>>> new_coords = (current_coords[[[[0] / 2, current_coords[[[[1])
Enfin, affectez les nouvelles coordonnées au .En haut à droite
propriété:
>>> côté gauche.mediaBox.En haut à droite = new_coords
Vous avez maintenant recadré la page d'origine pour ne contenir que le texte sur le côté gauche! Extrayons ensuite le côté droit de la page.
Obtenez d'abord une nouvelle copie de première page
:
>>> côté droit = copie.copie profonde(première page)
Bouge le .en haut à gauche
coin au lieu du .En haut à droite
coin:
>>> côté droit.mediaBox.en haut à gauche = new_coords
Cela définit le coin supérieur gauche sur les mêmes coordonnées que vous avez déplacé le coin supérieur droit lors de l'extraction du côté gauche de la page. Donc, right_side.mediaBox
est maintenant un rectangle dont le coin supérieur gauche est en haut au centre de la page et dont le coin supérieur droit est en haut à droite de la page.
Enfin, ajoutez le côté gauche
et côté droit
pages à pdf_writer
et écrivez-les dans un nouveau fichier PDF:
>>> pdf_writer.ajouter une page(côté gauche)
>>> pdf_writer.ajouter une page(côté droit)
>>> avec Chemin("cropped_pages.pdf").ouvert(mode="wb") comme fichier de sortie:
... pdf_writer.écrire(fichier de sortie)
...
Maintenant, ouvrez le cropped_pages.pdf
fichier avec un lecteur PDF. Vous devriez voir un fichier avec deux pages, la première contenant le texte du côté gauche de la première page d'origine et la seconde contenant le texte du côté droit d'origine.
Vérifie ta compréhension
Développez le bloc ci-dessous pour vérifier votre compréhension:
dans le practice_files /
dossier dans le référentiel compagnon de cet article, il existe un fichier appelé split_and_rotate.pdf
.
Créez un nouveau fichier appelé rotated.pdf
dans le répertoire personnel de votre ordinateur qui contient toutes les pages de split_and_rotate.pdf
, mais chacun est tourné de 90 degrés dans le sens antihoraire.
Vous pouvez développer le bloc ci-dessous pour voir une solution:
Configurez le chemin d'accès au fichier PDF:
# Tout d'abord, importez les classes et bibliothèques nécessaires
de pathlib importation Chemin
de PyPDF2 importation PdfFileReader
# Ensuite, créez un objet `Path` dans le fichier PDF.
# Vous devrez peut-être modifier cela pour correspondre au chemin
# sur ton ordinateur.
pdf_path = (
Chemin.maison()
/ "création et modification de pdfs"
/ "practice_files"
/ "split_and_rotate.pdf"
)
Vous pouvez maintenant créer PdfFileReader
et PdfFileWriter
instances:
lecteur PDF = PdfFileReader(str(pdf_path))
pdf_writer = PdfFileWriter()
Faites une boucle sur les pages lecteur PDF
, tournez-les tous de 90 degrés en utilisant .rotateCounterClockwise ()
et ajoutez-les à pdf_writer
:
pour page dans lecteur PDF.pages:
rotated_page = page.RotateCounterClockwise(90)
pdf_writer.ajouter une page(rotated_page)
Enfin, écrivez le contenu de pdf_writer
dans un fichier appelé rotated.pdf
dans le répertoire personnel de votre ordinateur:
chemin_sortie = Chemin.maison() / "rotated.pdf"
avec chemin_sortie.ouvert(mode="wb") comme fichier de sortie:
pdf_writer.écrire(fichier de sortie)
[ad_2]