Cách chuyển trang web thành PDF bằng Python


95

Tôi đang tìm giải pháp để in trang web thành tệp cục bộ PDF bằng Python. một trong những giải pháp tốt là sử dụng Qt, được tìm thấy tại đây, https://bharatikunal.wordpress.com/2010/01/ .

Nó không hoạt động ngay từ đầu vì tôi gặp sự cố với quá trình cài đặt PyQt4 vì nó đưa ra các thông báo lỗi như ' ImportError: No module named PyQt4.QtCore' và ' ImportError: No module named PyQt4.QtCore'.

Đó là do PyQt4 không được cài đặt đúng cách. Tôi đã từng có các thư viện đặt tại C: \ Python27 \ Lib nhưng nó không dành cho PyQt4.

Trên thực tế, nó chỉ cần tải xuống từ http://www.riverbankcomputing.com/software/pyqt/download (nhớ phiên bản Python chính xác mà bạn đang sử dụng) và cài đặt nó vào C: \ Python27 (trường hợp của tôi). Đó là nó.

Bây giờ các tập lệnh chạy tốt nên tôi muốn chia sẻ nó. để có thêm tùy chọn trong việc sử dụng Qprinter, vui lòng tham khảo http://qt-project.org/doc/qt-4.8/qprinter.html#Orientation-enum .

Câu trả lời:


157

Bạn cũng có thể sử dụng pdfkit :

Sử dụng

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

Tải về

Hệ điều hành Mac: brew install Caskroom/cask/wkhtmltopdf

Debian / Ubuntu: apt-get install wkhtmltopdf

Các cửa sổ: choco install wkhtmltopdf

Xem tài liệu chính thức cho MacOS / Ubuntu / hệ điều hành khác: https://github.com/JazzCore/python-pdfkit/wiki/Installing-wkhtmltopdf


4
Điều này thật tuyệt vời, dễ dàng hơn so với việc làm lộn xộn với bảng báo cáo hoặc sử dụng ổ đĩa in để chuyển đổi. Cám ơn rất nhiều.
Dowlers

@NorthCat bạn có thể đưa ra một ví dụ khác về việc chuyển đổi bảng html bằng pdfkit không?
Babel

1
Có vẻ như windows không hỗ trợ pdfkit. Có đúng như vậy không?
Kane Chew

2
Hoàn hảo !! Ngay cả khi tải xuống các hình ảnh nhúng, đừng bận tâm sử dụng nó! Bạn sẽ phảiapt-get install wkhtmltopdf
Tinmarino

4
pdfkit phụ thuộc vào gói wkhtmltopdf không phải python, do đó nó yêu cầu một máy chủ X đang chạy. Vì vậy, mặc dù tốt trong một số môi trường, nhưng đây không phải là câu trả lời hoạt động chung trong 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)

5
Tôi có thể cung cấp đường dẫn tệp thay vì url không?
Piyush S. Wanare,

12
Tôi nghĩ rằng tôi sẽ thích dự án này vì nó phụ thuộc là các gói python hơn là một gói hệ thống. Kể từ tháng 1 năm 2018, nó dường như có nhiều bản cập nhật thường xuyên hơn và tài liệu tốt hơn.
stv

4
Có quá nhiều thứ để cài đặt. Tôi dừng lại ở libpango và tìm pdfkit. Khó cho wkhtmltopdf toàn hệ thống nhưng weasyprint cũng yêu cầu một số cài đặt trên toàn hệ thống.
visoft

1
Tôi tin rằng tùy chọn nên là 'wb', không 'w', vì pdflà một bytesđối tượng.
Anatoly Scherbakov

1
đối với tôi, nó chỉ tải trang đầu tiên và bỏ qua phần còn lại
Fábio

24

nhờ các bài đăng dưới đây và tôi có thể thêm vào địa chỉ liên kết trang web sẽ được in và hiện tại trên tệp PDF được tạo, bất kể nó có bao nhiêu trang.

Thêm văn bản vào PDF hiện có bằng Python

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

Để chia sẻ script như bên dưới:

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.'

Cảm ơn vì đã chia sẻ mã của bạn! Bất kỳ lời khuyên nào để làm cho việc này hoạt động cho các tệp pdf cục bộ? Hay nó dễ dàng như thêm "tệp: ///" vào url? Tôi không phải là rất quen thuộc với các thư viện ... thanks
user2426679

@ user2426679, ý bạn là chuyển đổi PDF trực tuyến thành các tệp PDF cục bộ?
Mark K

cảm ơn bạn đã trả lời ... xin lỗi vì sự chậm trễ của tôi. Tôi đã kết thúc bằng cách sử dụng wkhtmltopdf vì nó có thể xử lý những gì tôi đang ném vào nó. Nhưng tôi đang hỏi làm thế nào để tải một pdf cục bộ vào hdd của tôi. Cheers
user2426679 28/12/14

@ user2426679 xin lỗi mình vẫn chưa hiểu bạn nhé. có lẽ vì tôi cũng là một người mới làm quen với Python. Ý bạn là đọc các tệp PDF cục bộ bằng Python?
Mark K

Đã xảy ra một số vấn đề với html5libxhtml2pdf. Giải pháp này khắc phục được vấn đề: github.com/xhtml2pdf/xhtml2pdf/issues/318
Blairg23

14

đây là một trong những hoạt động tốt:

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_())

Điều thú vị là các liên kết trang web được tạo dưới dạng văn bản chứ không phải là các liên kết trong tệp PDF được tạo.
amergin

1
Bất cứ ai biết tại sao điều này sẽ được tạo pdf trống cho tôi?
boson

11

Đây là một giải pháp đơn giản bằng cách sử dụng QT. Tôi thấy đây là một phần của câu trả lời cho một câu hỏi khác trên StackOverFlow. Tôi đã thử nghiệm nó trên 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!"

4

Tôi đã thử câu trả lời @NorthCat bằng pdfkit.

Nó yêu cầu wkhtmltopdf được cài đặt. Bản cài đặt có thể được tải xuống từ đây. https://wkhtmltopdf.org/downloads.html

Cài đặt tệp thực thi. Sau đó, viết một dòng để cho biết wkhtmltopdf ở đâu, như bên dưới. (được tham chiếu từ Không thể tạo pdf bằng python PDFKIT Lỗi: "Không tìm thấy tệp thực thi 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)

2

Giải pháp này phù hợp với tôi khi sử dụng PyQt5 phiên bả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_())

1

Nếu bạn sử dụng selen và chromium, bạn không cần phải tự quản lý cookie và bạn có thể tạo trang pdf từ bản in của chromium dưới dạng pdf. Bạn có thể tham khảo dự án này để hiện thực hóa nó. https://github.com/maxvst/python-selenium-chrome-html-to-pdf-converter

cơ sở đã sửa đổi> 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
Đầu tiên, tôi sử dụng weasyprint nhưng nó không hỗ trợ cookie, thậm chí bạn có thể viết cookie của riêng mình default_url_fetcherđể xử lý cookie nhưng sau đó tôi xảy ra sự cố khi cài đặt nó trong Ubuntu16. một số trang.
Yuanmeng Xiao

Cảm ơn chia sẻ của anh @Yuanmeng Xiao.
Mark K
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.