Как конвертировать веб-страницу в PDF с помощью Python

97

Я находил решение для печати веб-страницы в локальный файл PDF с помощью Python. Одно из хороших решений - использовать Qt, который можно найти здесь, https://bharatikunal.wordpress.com/2010/01/ .

Вначале это не сработало, так как у меня возникла проблема с установкой PyQt4, потому что он выдавал сообщения об ошибках, такие как ' ImportError: No module named PyQt4.QtCore' и ' ImportError: No module named PyQt4.QtCore'.

Это произошло потому, что PyQt4 установлен неправильно. Раньше у меня были библиотеки, расположенные в C: \ Python27 \ Lib, но это не для PyQt4.

Фактически, его просто нужно загрузить с http://www.riverbankcomputing.com/software/pyqt/download (обратите внимание на правильную версию Python, которую вы используете) и установить в C: \ Python27 (в моем случае). Вот и все.

Теперь скрипты работают нормально, поэтому я хочу им поделиться. для получения дополнительных сведений об использовании Qprinter см. http://qt-project.org/doc/qt-4.8/qprinter.html#Orientation-enum .

Марк К
источник

Ответы:

159

Вы также можете использовать pdfkit :

Применение

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

Установить

MacOS: brew install Caskroom/cask/wkhtmltopdf

Debian / Ubuntu: apt-get install wkhtmltopdf

Windows: choco install wkhtmltopdf

См. Официальную документацию для MacOS / Ubuntu / других ОС: https://github.com/JazzCore/python-pdfkit/wiki/Installing-wkhtmltopdf

NorthCat
источник
4
Это круто, намного проще, чем возиться с reportlab или использовать диск для печати для преобразования. Спасибо.
Даулс
@NorthCat можете привести еще один пример преобразования таблиц HTML с помощью pdfkit?
Babel
1
Похоже, Windows не поддерживает pdfkit. Это правда?
Кейн Чу
2
Отлично !! Даже загружайте встроенные изображения, не беспокойтесь об этом! Тебе придетсяapt-get install wkhtmltopdf
Тинмарино
4
pdfkit зависит от пакета wkhtmltopdf, отличного от python, который, в свою очередь, требует работающего X-сервера. Таким образом, хотя это и хорошо в некоторых средах, это не тот ответ, который обычно работает на python.
Расмус Кай
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)
Джон Мадд
источник
5
Могу ли я указать путь к файлу вместо URL-адреса?
Пиюш С. Ванаре
12
Я думаю, что предпочту этот проект, поскольку он зависит от пакетов Python, а не от системного пакета. По состоянию на январь 2018 года, похоже, он имеет более частые обновления и лучшую документацию.
stv
4
Слишком много вещей нужно установить. Я остановился на libpango и выбрал pdfkit. Противно для общесистемного wkhtmltopdf, но weasyprint также требует некоторых общесистемных установок.
visoft
1
Я считаю, что вариант должен быть 'wb', а не 'w'потому, что pdfэто bytesобъект.
Анатолий Щербаков
1
для меня он загружает только первую страницу и игнорирует остальные
Фабио
24

Благодаря сообщениям, приведенным ниже, я могу добавить адрес ссылки на веб-страницу, который будет напечатан и отображать время в созданном PDF-файле, независимо от того, сколько страниц в нем есть.

Добавить текст в существующий PDF с помощью Python

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

Чтобы поделиться сценарием, как показано ниже:

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.'
Марк К
источник
Спасибо, что поделились своим кодом! Какие-нибудь советы по работе с локальными файлами PDF? Или это так же просто, как добавить к URL-адресу "file: ///"? Я не очень знаком с этими библиотеками ... спасибо
user2426679
@ user2426679, вы имеете в виду преобразование онлайн-PDF в локальные PDF-файлы?
Mark K
спасибо за ответ ... извините за опоздание. В итоге я использовал wkhtmltopdf, так как он мог справиться с тем, что я ему бросал. Но я спрашивал, как загрузить PDF-файл, локальный для моего жесткого диска. Cheers
user2426679
@ user2426679 извини, я все еще тебя не понимаю. может быть, потому что я тоже новичок в Python. Вы имели в виду читать локальные PDF-файлы на Python?
Mark K
Были некоторые проблемы с html5lib, который используется xhtml2pdf. Это решение
устранило
14

вот тот, который работает нормально:

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_())
Марк К
источник
Интересно, что ссылки на веб-страницы создаются как текст, а не как ссылки в созданном PDF-файле.
amergin
1
Кто-нибудь знает, почему это будет генерировать для меня пустые PDF-файлы?
бозон
11

Вот простое решение с использованием QT. Я нашел это как часть ответа на другой вопрос о StackOverFlow. Тестировал на винде.

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!"
Джим Пол
источник
4

Я попробовал ответить @NorthCat, используя pdfkit.

Требуется установка wkhtmltopdf. Установку можно скачать отсюда. https://wkhtmltopdf.org/downloads.html

Установите исполняемый файл. Затем напишите строку, чтобы указать, где находится wkhtmltopdf, как показано ниже. (ссылка на документ Не удается создать PDF-файл с помощью Python. Ошибка PDFKIT: «Не найден исполняемый файл 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)
Марк К
источник
Куда он исчез после того, как я щелкнул .deb и установил его в программном центре?
webNoob13
2

Это решение сработало для меня с использованием PyQt5 версии 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
источник
1

Если вы используете селен и хром, вам не нужно самостоятельно управлять файлами cookie, и вы можете сгенерировать страницу pdf из распечатки хрома в формате pdf. Вы можете направить этот проект на реализацию. https://github.com/maxvst/python-selenium-chrome-html-to-pdf-converter

измененная база> 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()
Юаньмэн Сяо
источник
1
Во-первых, я использую weasyprint, но он не поддерживает файлы cookie, даже если вы можете написать свой собственный default_url_fetcherдля обработки файлов cookie, но позже у меня возникла проблема при его установке в Ubuntu16. Затем я использую wkhtmltopdf, он поддерживает настройку cookie, но это вызвало многие OSERROR, такие как -15-11, при обработке какая-то страница.
Юаньмэн Сяо,
Спасибо, что поделились с господином @Yuanmeng Сяо.
Марк К.