วิธีแปลงหน้าเว็บเป็น 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 / OS อื่น ๆ : https://github.com/JazzCore/python-pdfkit/wiki/Installing-wkhtmltopdf


4
วิธีนี้ยอดเยี่ยมง่ายกว่าการยุ่งกับ reportlab หรือใช้ไดรฟ์พิมพ์เพื่อแปลง ขอบคุณมาก.
Dowlers

@NorthCat คุณสามารถยกตัวอย่างอื่นเกี่ยวกับการแปลงตาราง html ด้วย pdfkit ได้หรือไม่?
Babel

1
ดูเหมือนว่า windows ไม่รองรับ pdfkit เป็นเช่นนั้นจริงหรือ?
Kane Chew

2
เป๊ะ !! แม้แต่ดาวน์โหลดภาพที่ฝังไว้ก็อย่าใช้มัน! คุณจะต้องapt-get install wkhtmltopdf
Tinmarino

4
pdfkit ขึ้นอยู่กับแพ็คเกจที่ไม่ใช่ python wkhtmltopdf ซึ่งจะต้องใช้เซิร์ฟเวอร์ X ที่ทำงานอยู่ ดังนั้นแม้ว่าจะดีในบางสภาพแวดล้อม แต่นี่ไม่ใช่คำตอบที่ใช้ได้กับ 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
ฉันสามารถระบุเส้นทางของไฟล์แทน url ได้หรือไม่?
Piyush S. Wanare

12
ฉันคิดว่าฉันจะชอบโครงการนี้เนื่องจากการอ้างอิงเป็นแพ็คเกจ python มากกว่าแพ็คเกจระบบ ในเดือนมกราคม 2018 ดูเหมือนว่าจะมีการอัปเดตบ่อยขึ้นและมีเอกสารประกอบที่ดีขึ้น
stv

4
มีหลายอย่างเกินไปที่จะติดตั้ง ฉันหยุดที่ libpango และไปหา pdfkit น่ารังเกียจสำหรับ wkhtmltopdf ทั้งระบบ แต่ weasyprint ยังต้องการการติดตั้งทั้งระบบ
visoft

1
ฉันเชื่อว่าตัวเลือกควรเป็น'wb'ไม่ใช่'w'เพราะpdfเป็นbytesวัตถุ
Anatoly Scherbakov

1
สำหรับฉันมันแค่ดาวน์โหลดหน้าแรกและไม่สนใจส่วนที่เหลือ
Fábio

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 ในเครื่อง หรือว่าง่ายเหมือนการเติม "file: ///" ไว้ที่ url ก่อน? ฉันไม่ค่อยคุ้นเคยกับไลบรารีเหล่านี้ ... ขอบคุณ
user2426679

@ user2426679 คุณหมายถึงแปลง PDF ออนไลน์เป็นไฟล์ PDF ในเครื่องใช่หรือไม่?
Mark K

ขอบคุณสำหรับการตอบกลับของคุณ ... ขอโทษสำหรับความล่าช้าของฉัน ฉันลงเอยด้วยการใช้ wkhtmltopdf เนื่องจากสามารถจัดการกับสิ่งที่ฉันขว้างปาไปได้ แต่ฉันถามวิธีการโหลด pdf ที่อยู่ในเครื่อง HDD ของฉัน ไชโย
user2426679

@ user2426679 ขออภัยฉันยังไม่เข้าใจคุณ อาจเป็นเพราะฉันเป็นมือใหม่กับ Python ด้วย คุณหมายถึงอ่านไฟล์ PDF ในเครื่องใน Python หรือไม่?
Mark K

มีปัญหาบางอย่างhtml5libซึ่งใช้โดย xhtml2pdf วิธีนี้แก้ไขปัญหา: github.com/xhtml2pdf/xhtml2pdf/issues/318
Blairg23

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 เปล่าให้ฉัน
boson

11

นี่คือวิธีง่ายๆโดยใช้ QT ฉันพบว่านี่เป็นส่วนหนึ่งของคำตอบสำหรับคำถามอื่นใน StackOverFlow ฉันทดสอบบน 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

ฉันลองใช้คำตอบ @NorthCat โดยใช้ pdfkit

ต้องติดตั้ง wkhtmltopdf สามารถดาวน์โหลดการติดตั้งได้จากที่นี่ https://wkhtmltopdf.org/downloads.html

ติดตั้งไฟล์ปฏิบัติการ จากนั้นเขียนบรรทัดเพื่อระบุว่า wkhtmltopdf อยู่ที่ไหนเช่นด้านล่าง (อ้างอิงจากไม่สามารถสร้าง pdf โดยใช้ python PDFKIT Error: "ไม่พบ 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_())

1

หากคุณใช้ซีลีเนียมและโครเมียมคุณไม่จำเป็นต้องจัดการคุกกี้ด้วยตัวคุณเองและคุณสามารถสร้างหน้า 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 แต่มันไม่รองรับคุกกี้แม้ว่าคุณจะสามารถเขียนของคุณเอง default_url_fetcherเพื่อจัดการกับคุกกี้ แต่ในภายหลังฉันก็เกิดปัญหาเมื่อติดตั้งใน Ubuntu16 จากนั้นฉันใช้ wkhtmltopdf เป็นการตั้งค่าคุกกี้ที่รองรับ แต่มันทำให้ OSERROR หลายตัวเช่น -15-11 เมื่อจัดการ บางหน้า
Yuanmeng Xiao

ขอบคุณสำหรับการแบ่งปันคุณ @ หยวนเหมิงเสี่ยว
Mark K
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.