Comment convertir une page Web en PDF en utilisant Python

92

Je trouvais une solution pour imprimer une page Web dans un fichier PDF local, en utilisant Python. l'une des bonnes solutions consiste à utiliser Qt, que vous trouverez ici, https://bharatikunal.wordpress.com/2010/01/ .

Cela n'a pas fonctionné au début car j'avais un problème avec l'installation de PyQt4 car il donnait des messages d'erreur tels que « ImportError: No module named PyQt4.QtCore» et « ImportError: No module named PyQt4.QtCore».

C'était parce que PyQt4 n'est pas installé correctement. J'avais l'habitude d'avoir les bibliothèques situées à C: \ Python27 \ Lib mais ce n'est pas pour PyQt4.

En fait, il suffit de le télécharger à partir de http://www.riverbankcomputing.com/software/pyqt/download (attention à la bonne version de Python que vous utilisez) et de l'installer sur C: \ Python27 (mon cas). C'est tout.

Maintenant, les scripts fonctionnent bien, donc je veux les partager. pour plus d'options d'utilisation de Qprinter, veuillez vous référer à http://qt-project.org/doc/qt-4.8/qprinter.html#Orientation-enum .

Mark K
la source

Réponses:

156

Vous pouvez également utiliser pdfkit :

Usage

import pdfkit
pdfkit.from_url('http://google.com', 'out.pdf')

Installer

MacOS: brew install Caskroom/cask/wkhtmltopdf

Debian / Ubuntu: apt-get install wkhtmltopdf

Les fenêtres: choco install wkhtmltopdf

Voir la documentation officielle pour MacOS / Ubuntu / autre OS: https://github.com/JazzCore/python-pdfkit/wiki/Installing-wkhtmltopdf

NorthCat
la source
4
C'est génial, bien plus facile que de jouer avec reportlab ou d'utiliser un lecteur d'impression pour convertir. Merci beaucoup.
Dowlers
@NorthCat pouvez-vous donner un autre exemple sur la conversion de tableaux html avec pdfkit?
Babel
1
Il semble que Windows ne prend pas en charge pdfkit. Est-ce vrai?
Kane Chew
2
Parfait !! Même téléchargez les images intégrées, ne vous en faites pas! Vous devrezapt-get install wkhtmltopdf
Tinmarino
4
pdfkit dépend du package non-python wkhtmltopdf, qui à son tour nécessite un serveur X en cours d'exécution. Donc, bien que cela soit agréable dans certains environnements, ce n'est pas une réponse qui fonctionne généralement en python.
Rasmus Kaj
45

WeasyPrint

pip install weasyprint  # No longer supports Python 2.x.

python
>>> import weasyprint
>>> pdf = weasyprint.HTML('http://www.google.com').write_pdf()
>>> len(pdf)
92059
>>> open('google.pdf', 'wb').write(pdf)
JohnMudd
la source
5
Puis-je fournir le chemin du fichier au lieu de l'URL?
Piyush S.Wanare
11
Je pense que je préférerai ce projet car ses dépendances sont des packages python plutôt qu'un package système. Depuis janvier 2018, il semble avoir des mises à jour plus fréquentes et une meilleure documentation.
stv
3
Il y a trop de choses à installer. Je me suis arrêté à libpango et suis allé chercher le pdfkit. Nasty pour wkhtmltopdf à l'échelle du système, mais weasyprint nécessite également des installations à l'échelle du système.
visoft
1
Je pense que l'option devrait être 'wb', non 'w', parce que pdfc'est un bytesobjet.
Anatoly Scherbakov
1
pour moi, il ne télécharge que la première page et ignore le reste
Fábio
24

grâce aux messages ci-dessous, et je suis en mesure d'ajouter sur la page Web l'adresse du lien à imprimer et l'heure actuelle sur le PDF généré, quel que soit le nombre de pages qu'il contient.

Ajouter du texte à un PDF existant à l'aide de Python

https://github.com/disflux/django-mtr/blob/master/pdfgen/doc_overlay.py

Pour partager le script comme ci-dessous:

import time
from pyPdf import PdfFileWriter, PdfFileReader
import StringIO
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from xhtml2pdf import pisa
import sys 
from PyQt4.QtCore import *
from PyQt4.QtGui import * 
from PyQt4.QtWebKit import * 

url = 'http://www.yahoo.com'
tem_pdf = "c:\\tem_pdf.pdf"
final_file = "c:\\younameit.pdf"

app = QApplication(sys.argv)
web = QWebView()
#Read the URL given
web.load(QUrl(url))
printer = QPrinter()
#setting format
printer.setPageSize(QPrinter.A4)
printer.setOrientation(QPrinter.Landscape)
printer.setOutputFormat(QPrinter.PdfFormat)
#export file as c:\tem_pdf.pdf
printer.setOutputFileName(tem_pdf)

def convertIt():
    web.print_(printer)
    QApplication.exit()

QObject.connect(web, SIGNAL("loadFinished(bool)"), convertIt)

app.exec_()
sys.exit

# Below is to add on the weblink as text and present date&time on PDF generated

outputPDF = PdfFileWriter()
packet = StringIO.StringIO()
# create a new PDF with Reportlab
can = canvas.Canvas(packet, pagesize=letter)
can.setFont("Helvetica", 9)
# Writting the new line
oknow = time.strftime("%a, %d %b %Y %H:%M")
can.drawString(5, 2, url)
can.drawString(605, 2, oknow)
can.save()

#move to the beginning of the StringIO buffer
packet.seek(0)
new_pdf = PdfFileReader(packet)
# read your existing PDF
existing_pdf = PdfFileReader(file(tem_pdf, "rb"))
pages = existing_pdf.getNumPages()
output = PdfFileWriter()
# add the "watermark" (which is the new pdf) on the existing page
for x in range(0,pages):
    page = existing_pdf.getPage(x)
    page.mergePage(new_pdf.getPage(0))
    output.addPage(page)
# finally, write "output" to a real file
outputStream = file(final_file, "wb")
output.write(outputStream)
outputStream.close()

print final_file, 'is ready.'
Mark K
la source
Merci d'avoir partagé votre code! Des conseils pour que cela fonctionne pour les fichiers pdf locaux? Ou est-ce aussi simple que d'ajouter "file: ///" à l'URL? Je ne suis pas très familier avec ces bibliothèques ... merci
user2426679
@ user2426679, vous voulez dire convertir un PDF en ligne en fichiers PDF locaux?
Mark K
merci pour votre réponse ... désolé pour mon retard. J'ai fini par utiliser wkhtmltopdf car il était capable de gérer ce que je lui jetais. Mais je demandais comment charger un pdf local sur mon disque dur. Cheers
user2426679
@ user2426679 désolé, je ne vous comprends toujours pas. peut-être parce que je suis aussi un novice en Python. Vous vouliez dire lire des fichiers PDF locaux en Python?
Mark K
Il y a eu quelques problèmes avec html5lib, qui est utilisé par xhtml2pdf. Cette solution a résolu le problème: github.com/xhtml2pdf/xhtml2pdf/issues/318
Blairg23
14

voici celui qui fonctionne bien:

import sys 
from PyQt4.QtCore import *
from PyQt4.QtGui import * 
from PyQt4.QtWebKit import * 

app = QApplication(sys.argv)
web = QWebView()
web.load(QUrl("http://www.yahoo.com"))
printer = QPrinter()
printer.setPageSize(QPrinter.A4)
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName("fileOK.pdf")

def convertIt():
    web.print_(printer)
    print("Pdf generated")
    QApplication.exit()

QObject.connect(web, SIGNAL("loadFinished(bool)"), convertIt)
sys.exit(app.exec_())
Mark K
la source
Fait intéressant, les liens de page Web sont générés sous forme de texte plutôt que de liens dans le PDF généré.
amergin
Quelqu'un sait pourquoi cela générerait des fichiers PDF vierges pour moi?
boson
11

Voici une solution simple utilisant QT. J'ai trouvé cela dans le cadre d'une réponse à une question différente sur StackOverFlow. Je l'ai testé sur Windows.

from PyQt4.QtGui import QTextDocument, QPrinter, QApplication

import sys
app = QApplication(sys.argv)

doc = QTextDocument()
location = "c://apython//Jim//html//notes.html"
html = open(location).read()
doc.setHtml(html)

printer = QPrinter()
printer.setOutputFileName("foo.pdf")
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setPageSize(QPrinter.A4);
printer.setPageMargins (15,15,15,15,QPrinter.Millimeter);

doc.print_(printer)
print "done!"
Jim Paul
la source
2

J'ai essayé la réponse @NorthCat en utilisant pdfkit.

Il fallait installer wkhtmltopdf. L'installation peut être téléchargée à partir d'ici. https://wkhtmltopdf.org/downloads.html

Installez le fichier exécutable. Ensuite, écrivez une ligne pour indiquer où se trouve wkhtmltopdf, comme ci-dessous. (référencé dans Impossible de créer un pdf à l'aide de python PDFKIT Erreur: "Aucun exécutable wkhtmltopdf trouvé:"

import pdfkit


path_wkthmltopdf = "C:\\Folder\\where\\wkhtmltopdf.exe"
config = pdfkit.configuration(wkhtmltopdf = path_wkthmltopdf)

pdfkit.from_url("http://google.com", "out.pdf", configuration=config)
Mark K
la source
1

Si vous utilisez du sélénium et du chrome, vous n'avez pas besoin de gérer vous-même les cookies et vous pouvez générer une page pdf à partir de l'impression de chrome au format pdf. Vous pouvez vous référer à ce projet pour le réaliser. https://github.com/maxvst/python-selenium-chrome-html-to-pdf-converter

base modifiée> https://github.com/maxvst/python-selenium-chrome-html-to-pdf-converter/blob/master/sample/html_to_pdf_converter.py

import sys
import json, base64


def send_devtools(driver, cmd, params={}):
    resource = "/session/%s/chromium/send_command_and_get_result" % driver.session_id
    url = driver.command_executor._url + resource
    body = json.dumps({'cmd': cmd, 'params': params})
    response = driver.command_executor._request('POST', url, body)
    return response.get('value')


def get_pdf_from_html(driver, url, print_options={}, output_file_path="example.pdf"):
    driver.get(url)

    calculated_print_options = {
        'landscape': False,
        'displayHeaderFooter': False,
        'printBackground': True,
        'preferCSSPageSize': True,
    }
    calculated_print_options.update(print_options)
    result = send_devtools(driver, "Page.printToPDF", calculated_print_options)
    data = base64.b64decode(result['data'])
    with open(output_file_path, "wb") as f:
        f.write(data)



# example
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

url = "/programming/23359083/how-to-convert-webpage-into-pdf-by-using-python#"
webdriver_options = Options()
webdriver_options.add_argument("--no-sandbox")
webdriver_options.add_argument('--headless')
webdriver_options.add_argument('--disable-gpu')
driver = webdriver.Chrome(chromedriver, options=webdriver_options)
get_pdf_from_html(driver, url)
driver.quit()
Yuanmeng Xiao
la source
1
Tout d'abord, j'utilise weasyprint mais il ne prend pas en charge les cookies même si vous pouvez écrire le vôtre default_url_fetcherpour gérer les cookies, mais plus tard, je rencontre un problème lors de son installation dans Ubuntu16.Ensuite, j'utilise wkhtmltopdf it suport cookie setting mais cela a causé de nombreux OSERROR comme -15-11 lors de la manipulation une page.
Yuanmeng Xiao le
Merci d'avoir partagé M. @Yuanmeng Xiao.
Mark K le
1

Cette solution a fonctionné pour moi en utilisant PyQt5 version 5.15.0

import sys
from PyQt5 import QtWidgets, QtWebEngineWidgets
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QPageLayout, QPageSize
from PyQt5.QtWidgets import QApplication

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    loader = QtWebEngineWidgets.QWebEngineView()
    loader.setZoomFactor(1)
    layout = QPageLayout()
    layout.setPageSize(QPageSize(QPageSize.A4Extra))
    layout.setOrientation(QPageLayout.Portrait)
    loader.load(QUrl('/programming/23359083/how-to-convert-webpage-into-pdf-by-using-python'))
    loader.page().pdfPrintingFinished.connect(lambda *args: QApplication.exit())

    def emit_pdf(finished):
        loader.page().printToPdf("test.pdf", pageLayout=layout)

    loader.loadFinished.connect(emit_pdf)
    sys.exit(app.exec_())
Y.kh
la source