Cómo convertir una página web en PDF usando Python

95

Estaba encontrando una solución para imprimir una página web en un archivo PDF local, usando Python. una de las buenas soluciones es usar Qt, que se encuentra aquí, https://bharatikunal.wordpress.com/2010/01/ .

No funcionó al principio porque tuve problemas con la instalación de PyQt4 porque me dio mensajes de error como ' ImportError: No module named PyQt4.QtCore' y ' ImportError: No module named PyQt4.QtCore'.

Fue porque PyQt4 no está instalado correctamente. Solía ​​tener las bibliotecas ubicadas en C: \ Python27 \ Lib, sin embargo, no es para PyQt4.

De hecho, simplemente necesita descargarlo de http://www.riverbankcomputing.com/software/pyqt/download (tenga en cuenta la versión correcta de Python que está usando) e instalarlo en C: \ Python27 (mi caso). Eso es.

Ahora los scripts funcionan bien, así que quiero compartirlos. Para obtener más opciones sobre el uso de Qprinter, consulte http://qt-project.org/doc/qt-4.8/qprinter.html#Orientation-enum .

Mark K
fuente

Respuestas:

157

También puede utilizar pdfkit :

Uso

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

Instalar en pc

Mac OS: brew install Caskroom/cask/wkhtmltopdf

Debian / Ubuntu: apt-get install wkhtmltopdf

Ventanas: choco install wkhtmltopdf

Consulte la documentación oficial para MacOS / Ubuntu / otro sistema operativo: https://github.com/JazzCore/python-pdfkit/wiki/Installing-wkhtmltopdf

NorthCat
fuente
4
Esto es increíble, mucho más fácil que jugar con Reportlab o usar una unidad de impresión para convertir. Muchas gracias.
Dowlers
@NorthCat ¿puedes dar otro ejemplo sobre la conversión de tablas html con pdfkit?
Babel
1
Parece que Windows no es compatible con pdfkit. ¿Es eso cierto?
Kane Chew
2
Perfecto !! Incluso descargue las imágenes incrustadas, ¡no se moleste en usar eso! Tendrás que hacerloapt-get install wkhtmltopdf
Tinmarino
4
pdfkit depende del paquete wkhtmltopdf que no es de Python, que a su vez requiere un servidor X en ejecución. Entonces, aunque es bueno en algunos entornos, esta no es una respuesta que funcione generalmente en Python.
Rasmus Kaj
47

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
fuente
5
¿Puedo proporcionar la ruta del archivo en lugar de la URL?
Piyush S. Wanare
12
Creo que preferiré este proyecto ya que sus dependencias son paquetes de Python en lugar de un paquete de sistema. A partir de enero de 2018, parece tener actualizaciones más frecuentes y mejor documentación.
stv
4
Hay demasiadas cosas para instalar. Paré en libpango y fui por el pdfkit. Desagradable para wkhtmltopdf en todo el sistema, pero weasyprint también requiere algunas instalaciones en todo el sistema.
visoft
1
Creo que la opción debería ser 'wb', no 'w', porque pdfes un bytesobjeto.
Anatoly Scherbakov
1
para mí solo descarga la primera página e ignora el resto
Fábio
24

gracias a las publicaciones a continuación, y puedo agregar la dirección del enlace de la página web para que se imprima y presente el tiempo en el PDF generado, sin importar cuántas páginas tenga.

Agregar texto a PDF existente usando Python

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

Para compartir el guión de la siguiente manera:

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
fuente
¡Gracias por compartir tu código! ¿Algún consejo para hacer que esto funcione para archivos PDF locales? ¿O es tan fácil como anteponer "file: ///" a la URL? No estoy muy familiarizado con estas bibliotecas ... gracias
user2426679
@ user2426679, ¿te refieres a convertir PDF en línea en archivos PDF locales?
Mark K
gracias por tu respuesta ... perdón por mi tardanza. Terminé usando wkhtmltopdf ya que podía manejar lo que le estaba lanzando. Pero estaba preguntando cómo cargar un pdf que era local en mi disco duro. Saludos
user2426679
@ user2426679 lo siento, todavía no te entiendo. tal vez porque también soy un novato en Python. ¿Te refieres a leer archivos PDF locales en Python?
Mark K
Hubo algunos problemas con html5lib, que es utilizado por xhtml2pdf. Esta solución solucionó el problema: github.com/xhtml2pdf/xhtml2pdf/issues/318
Blairg23
14

aquí está el que funciona 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
fuente
Curiosamente, los enlaces de la página web se generan como texto en lugar de enlaces en el PDF generado.
partir del
1
¿Alguien sabe por qué esto generaría archivos PDF en blanco para mí?
boson
11

Aquí hay una solución simple usando QT. Encontré esto como parte de una respuesta a una pregunta diferente en StackOverFlow. Lo probé en 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
fuente
4

Probé la respuesta de @NorthCat usando pdfkit.

Era necesario instalar wkhtmltopdf. La instalación se puede descargar desde aquí.https://wkhtmltopdf.org/downloads.html

Instale el archivo ejecutable. Luego, escriba una línea para indicar dónde está wkhtmltopdf, como se muestra a continuación. (referenciado desde No se puede crear pdf usando Python PDFKIT Error: "No se encontró el ejecutable wkhtmltopdf:"

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
fuente
¿A dónde fue después de hacer clic en .deb e instalarlo en el centro de software?
webNoob13
2

Esta solución funcionó para mí usando PyQt5 versión 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
fuente
1

Si usa selenio y cromo, no necesita administrar las cookies usted mismo, y puede generar una página pdf a partir de la impresión de chromium como pdf. Puedes referir este proyecto para realizarlo. https://github.com/maxvst/python-selenium-chrome-html-to-pdf-converter

base modificada> 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
fuente
1
En primer lugar, utilizo weasyprint pero no admite cookies, incluso usted puede escribir las suyas propias default_url_fetcherpara manejar las cookies, pero luego ocurre un problema al instalarlo en Ubuntu16.Luego utilizo wkhtmltopdf, admite la configuración de cookies, pero causó muchos OSERROR como -15-11 cuando se maneja alguna página.
Yuanmeng Xiao
Gracias por compartir al Sr. @Yuanmeng Xiao.
Mark K