【问题标题】:How to convert webpage into PDF by using Python如何使用 Python 将网页转换为 PDF
【发布时间】:2014-06-15 01:28:51
【问题描述】:

我正在寻找使用 Python 将网页打印到本地文件 PDF 的解决方案。一个好的解决方案是使用 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

【问题讨论】:

  • 请注意,如果您是自行回答,则可以同时发布问答,并且通常的质量规则仍然适用于这两个部分。

标签: python html pdf qprinter


【解决方案1】:

您也可以使用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

【讨论】:

  • 这太棒了,比使用 reportlab 或使用打印驱动器进行转换要容易得多。非常感谢。
  • PDFKit 需要一个正在运行的 X 服务器(或“虚拟”X 服务器)。 :( 见这里:github.com/JazzCore/python-pdfkit/wiki/…
  • 看来windows不支持pdfkit。这是真的吗?
  • 完美!!即使下载嵌入的图像,也不要费心使用它!你必须apt-get install wkhtmltopdf
  • pdfkit 依赖于非 python 包 wkhtmltopdf,而后者又需要一个正在运行的 X 服务器。因此,虽然在某些环境中很好,但这并不是一个在 python 中普遍适用的答案。
【解决方案2】:

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)

【讨论】:

  • 我可以提供文件路径而不是url吗?
  • 我想我会更喜欢这个项目,因为它的依赖项是 python 包而不是系统包。截至 2018 年 1 月,它似乎有更频繁的更新和更好的文档。
  • 要安装的东西太多了。我在 libpango 停了下来,然后去了 pdfkit。讨厌系统范围的 wkhtmltopdf,但 weasyprint 还需要一些系统范围的安装。
  • 这不会转换 html 文件中的javascripts。为此,您需要使用pdfkit
  • 我认为选项应该是'wb',而不是'w',因为pdfbytes 对象。
【解决方案3】:

感谢下面的帖子,我可以添加要打印的网页链接地址,并在生成的 PDF 上显示时间,无论它有多少页。

Add text to Existing PDF using 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,你是说在线PDF转换成本地PDF文件?
  • 感谢您的回复...对不起我的迟到。我最终使用了 wkhtmltopdf,因为它能够处理我扔给它的东西。但我在问如何加载我的硬盘本地的 pdf。干杯
  • @user2426679 抱歉,我还是没听明白。也许是因为我也是 Python 的新手。你的意思是用 Python 读取本地 PDF 文件?
  • xhtml2pdf 使用的html5lib 存在一些问题。此解决方案解决了问题:github.com/xhtml2pdf/xhtml2pdf/issues/318
【解决方案4】:

这是一个工作正常的:

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 中的链接。
  • 有人知道为什么这会为我生成空白 pdf 文件吗?
【解决方案5】:

这是一个使用 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!"

【讨论】:

    【解决方案6】:

    根据这个答案:How to convert webpage into PDF by using Python,建议使用 pdfkit。您还必须安装 wkhtmltopdf

    如果你有一个本地的.html文件,那么你需要使用这个命令:

    pdfkit.from_file('test.html', 'out.pdf')
    

    但是如果您没有将 wkhtmltopdf 可执行文件添加到系统路径中,这将引发错误。这是让我绊倒的部分,我想分享。

    在 Windows 上,打开您的环境变量并将它们添加到您的 System variables > Path,如下所示。就我而言,这些 .exe 文件在我从 exe 安装 wkhtmltopdf 后位于此处:

    C:\Program Files\wkhtmltopdf\bin

    【讨论】:

      【解决方案7】:

      我尝试使用 pdfkit 的 @NorthCat 回答。

      需要安装 wkhtmltopdf。安装可以从这里下载。 https://wkhtmltopdf.org/downloads.html

      安装可执行文件。然后写一行来指示 wkhtmltopdf 的位置,如下所示。 (引用自Can't create pdf using python PDFKIT Error : " No wkhtmltopdf executable found:"

      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并安装到软件中心后它去了哪里?
      【解决方案8】:

      如果你使用 selenium 和 chromium,你不需要自己管理 cookie,你可以从 chromium 的 print 生成 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 = "https://stackoverflow.com/questions/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()
      

      【讨论】:

      • 首先我使用 weasyprint 但它不支持 cookie 即使你可以编写自己的default_url_fetcher 来处理 cookie 但后来我在 Ubuntu16 中安装它时出现问题。然后我使用 wkhtmltopdf 它支持 cookie 设置但是处理某些页面时会导致许多 OSERROR,例如 -15 -11。
      • 感谢@肖元梦先生的分享。
      • 嗨@YuanmengXiao 我在上面复制了你的代码,我收到了这个错误:Traceback (most recent call last): File "C:/Users/brentond/Documents/Python/PdfWebsite.py", line 39 , 在 driver = webdriver.Chrome(chromedriver, options=webdriver_options) NameError: name 'chromedriver' is not defined
      • 然后我安装了一个名为 chromedriver 的模块并将其导入到上面的代码中,现在得到这个错误 Traceback (最近一次调用最后一次): File "C:/Users/brentond/Documents/Python/PdfWebsite. py”,第 33 行,在 中导入 chromedriver 文件“C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\lib\site-packages\chromedriver_init_。 py", line 16, in raise RuntimeError('This package仅支持Linux、MacOSX或Windows平台') RuntimeError: This package仅支持Linux、MacOSX或Windows平台
      • 你应该从chromedriver.chromium.org下载chromedrver,你最好学习如何使用selenium来驱动chrome浏览器。
      【解决方案9】:

      这个解决方案使用 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('https://stackoverflow.com/questions/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_())
      

      【讨论】:

      • 我试过这个并得到这个错误: Traceback(最近一次调用最后一次):文件“C:/Users/brentond/Documents/Python/PdfWebsite.py”,第 2 行,来自 PyQt5 import QtWidgets, QtWebEngineWidgets ImportError: DLL load failed: The specified module could not be found.
      • 你必须先安装 PyQt5 包:pip install PyQt5
      • 我确实安装了它......但据我所知,没有名为 QtwebEngineWidgets 的 PyQt5 方法......至少在我在 PyCharm 中安装的 5.15.2 中没有。
      • 需要pip install PyQtWebEngine才能工作
      猜你喜欢
      • 2013-10-23
      • 1970-01-01
      • 2012-03-25
      • 2011-02-08
      • 1970-01-01
      • 1970-01-01
      • 2021-10-29
      • 2021-11-09
      相关资源
      最近更新 更多