要使用的是wkhtmltopdf的Python封装——pdfkit
安装
1. Install python-pdfkit:
$ pip install pdfkit
2. Install wkhtmltopdf:
$ sudo apt-get install wkhtmltopdf
sudo yum intsall wkhtmltopdf
brew install Caskroom/cask/wkhtmltopdf
使用
一个简单的例子:
import pdfkit
pdfkit.from_url('http://google.com', 'out.pdf')
pdfkit.from_file('test.html', 'out.pdf')
pdfkit.from_string('Hello!', 'out.pdf')
你也可以传递一个url或者文件名列表:
pdfkit.from_url(['google.com', 'yandex.ru', 'engadget.com'], 'out.pdf')
pdfkit.from_file(['file1.html', 'file2.html'], 'out.pdf')
也可以传递一个打开的文件:
with open('file.html') as f:
pdfkit.from_file(f, 'out.pdf')
如果你想对生成的PDF作进一步处理, 你可以将其读取到一个变量中:
# 设置输出文件为False,将结果赋给一个变量
pdf = pdfkit.from_url('http://google.com', False)
你可以制定所有的 wkhtmltopdf 选项 http://wkhtmltopdf.org/usage/wkhtmltopdf.txt. 你可以移除选项名字前面的 '--' .如果选项没有值, 使用None, False or * 作为字典值:
options = {
'page-size': 'Letter',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
'no-outline': None
}
pdfkit.from_url('http://google.com', 'out.pdf', options=options)
默认情况下, PDFKit 将会显示所有的 wkhtmltopdf 输出. 如果你不想看到这些信息,你需要传递一个 quiet 选项:
options = {
'quiet': ''
}
pdfkit.from_url('google.com', 'out.pdf', options=options)
由于wkhtmltopdf的命令语法 , TOC 和 Cover 选项必须分开指定:
toc = {
'xsl-style-sheet': 'toc.xsl'
}
cover = 'cover.html'
pdfkit.from_file('file.html', options=options, toc=toc, cover=cover)
当你转换文件、或字符串的时候,你可以通过css选项指定扩展的 CSS 文件。
# 单个 CSS 文件
css = 'example.css'
pdfkit.from_file('file.html', options=options, css=css)
# Multiple CSS files
css = ['example.css', 'example2.css']
pdfkit.from_file('file.html', options=options, css=css)
你也可以通过你的HTML中的meta tags传递任意选项:
body = """
<html>
<head>
<meta name="pdfkit-page-size" content="Legal"/>
<meta name="pdfkit-orientation" content="Landscape"/>
</head>
Hello World!
</html>
"""
pdfkit.from_string(body, 'out.pdf') #with --page-size=Legal and --orientation=Landscape
配置
每个API调用都有一个可选的参数。这应该是pdfkit.configuration()API 调用的一个实例. 采用configuration 选项作为初始化参数。可用的选项有:
示例 :针对wkhtmltopdf不在系统路径中(不在$PATH里面)
PATH里面):
config = pdfkit.configuration(wkhtmltopdf='/opt/bin/wkhtmltopdf'))
pdfkit.from_string(html_string, output_file, configuration=config)
问题
IOError:'No wkhtmltopdf executable found':
确保 wkhtmltopdf 在你的系统路径中(PATH), 会通过 configuration进行了配置 (详情看上文描述)。 在Windows系统中使用where wkhtmltopdf命令 或 在 linux系统中使用 which wkhtmltopdf 会返回 wkhtmltopdf二进制可执行文件所在的确切位置.
如果出现这个错误意味着 PDFKit不能处理一个输入。你可以尝试直接在错误信息后面直接运行一个命令来查看是什么导致了这个错误 (某些版本的 wkhtmltopdf会因为段错误导致处理失败)
确保两项:
1)、你的系统中有中文字体
2)、在html中加入
下面是我随便写的一个HTML表格:
<html>
<head><meta charset="UTF-8"></head>
<body>
<table width="400" border="1">
<tr>
<th align="left">Item....</th>
<th align="right">1</th>
</tr>
<tr>
<td align="left">衣服</td>
<td align="right">1.10</td>
</tr>
<tr>
<td align="left">化妆品</td>
<td align="right">.00</td>
</tr>
<tr>
<td align="left">食物</td>
<td align="right">0.40</td>
</tr>
<tr>
<th align="left">tOTAL</th>
<th align="right">01.50</th>
</tr>
</table>
</body>
</html>
下面是生成的PDF截图
近临近开学了,大家都在忙着准备各种学习的资料,准备在新的学期好好学习,充实自己。小编身边的同学也是如此,最近,小编的同学小丽就遇到了一个很棘手的问题。
她想将一个网页的Python学习的教程打印下来,方便自己来学习,但是上千页的教程,如果通过手动的方式,一个一个的去转成pdf并保存到本地,实在是麻烦的不。
这就是一个html转pdf的问题,其实网上有很多不错的html资源,但是苦于学习起来,不方便!于是小编就跟小丽保证,这点小事包在我身上。今天,小编就跟分享一下如何用Python把html资料变成pdf。
如今网上的在线学习资料可谓是多如牛毛,为了方便讲解,小编就利用python3.9.2的中文文档作为演示的例子,来将其抓取并保存到本地,其网页链接如下:
https://docs.python.org/zh-cn/3.9/tutorial/index.html
打开上述链接后,大家会在网页中找到不同内容的链接地址,包括了基础的python字符、python语法等内容。
在上图中,我们需要格外关注的是红色方格标注的链接,每个链接都会跳转到对应的子网页中,而在子网页中,就是我们想要保存的内容。
可以看到,上图中,在python速览子页面中,包含了我们需要提取的文字内容。所以将html内容保存为pdf的第一步便是获取到子页面的链接。由于教程大都是固定内容,因此对于教程的网页,大都采用的是静态页面,在网页源代码中可以很轻松地找到子页面的网页链接。
对于子网页的链接抓取,程序如下图所示:
程序中,通过BeautifulSoup库来解析网页源代码,然后提取所有的子页面链接地址并返回,如果抓取失败,则直接返回None。
03.html转pdf
在得到子网页的链接后,接下来就是将html的子网页保存为pdf文件。小编使用的pdfkit库,pdfkit库可以将网页保存为pdf文档。首先小编来介绍一下pdfkit库的安装。
按照上述的操作流程,就可以安装pdfkit库。对于pdfkit库的使用,常见的用法有以下三种:
上面的程序主要完成以下几步:
首先需要指定wkhtmltopdf.exe文件的路径;
因此,pdfkit库只能将子网页保存为单独的pdf文档,无法直接通过pdfkit库将所有的子网页拼接成一个完整的pdf文档,小编通过PyPDF2库中的PdfFileMerger类来实现pdf文档的拼接。程序如下图所示。
程序中首先将所有的html网页保存为单独的pdf文档,然后通过PdfFileMerger类对象来实现pdf文档的拼接。最后就可以得到全部的pdf内容。最后我们通过视频的展示,来看一下程序的效果吧。
除此之外,程序不光可以抓取python3.9的中文文档,针对其他的在线文档,只需要对获取网页链接的程序进行修改即可抓取,例如对于Flask中文文档的抓取,程序只需要按照下图进行修改,即可将Flask的在线文档保存为PDF文档。
学习Python其实非常有趣,也很有用。因为Python有大量的现成的库,可以帮助我们把工作中的很多琐碎的烦事轻松解决。小编将上述的程序稍加修改,很快就帮阿丽搞定了教程,保存为pdf发送给了她,小编与女神的关系更拉近了一步
我们看一下通过Python Selenium WebDriver执行JavaScript语句的几种不同方法。
在本教程中,让我们分析Selenium WebDriver中使用最少但功能最强大的功能。是的,我将讨论JavaScript执行器,并向您展示通过Python Selenium WebDriver执行JavaScript语句的几种不同方法。
可能会发生这种情况,在某些实时项目中,Selenium WebDriver无法对特定的Web元素执行操作。例如,由于WebDriver模拟最终用户交互,因此很自然地会拒绝单击最终用户看不到的元素(有时即使Web元素在页面上可见,也会发生这种情况)。可能有其他几个类似的原因或情况。
在这些情况下,我们可以依靠JavaScript来单击或对该Web元素执行操作,并且可以通过WebDriver执行这些JavaScript语句。
您可以使用JavaScript执行WebElement界面所做的所有操作。
什么是JavaScript?
JavaScript是一种脚本语言,它在客户端运行,即在浏览器上运行,并且当您浏览网页时会做一些神奇的事情。有关更多详细信息,请在DZone上搜索关键字“JavaScript”。
我们如何在WebDriver中使用JavaScript?
Python Selenium WebDriver提供了一个内置方法:
driver.execute_script("some javascript code here");
我们可以通过两种方式在浏览器中执行JavaScript。
方法1:在文档根级别执行JavaScript
在这种情况下,我们使用JavaScript提供的方法捕获我们想要使用的元素,然后在其上声明一些操作并使用WebDriver执行此JavaScript。
例:
javaScript = "document.getElementsByName('username')[0].click();"
driver.execute_script(javaScript)
我们在这里做什么?
第1步:我们正在使用JavaScript检查并通过属性“名称”获取元素。(另外,可以使用'id'和'class'属性。)
第2步:使用JavaScript声明并对元素执行单击操作。
第3步:调用execute_script()方法并将我们创建的JavaScript作为字符串值传递。
请注意 上面[0] 的 getElementsByName('username')[0] 声明。JavaScript函数 getElementsByName , getElementsByClassName 等返回所有匹配的元件的阵列。在我们的例子中,我们需要对可以通过的第一个匹配元素进行操作 index [0] 。如果您知道自己在做什么,即,如果您知道要操作的元素的索引,则可以直接使用索引,例如 getElementsByName('username')[2] 。
但是,如果您使用的是JavaScript函数' getElementById ',则不需要使用任何索引,因为它只返回一个元素('id'应该是唯一的)。
执行时,WebDriver会将JavaScript语句注入浏览器,脚本将执行该任务。在我们的示例中,它对目标元素执行单击操作。此JavaScript具有自己的命名空间,不会干扰实际网页中的JavaScript。
方法2:在元素级别执行JavaScript
在这种情况下,我们使用WebDriver捕获我们想要使用的元素,然后使用JavaScript在其上声明一些操作,并通过将web元素作为参数传递给JavaScript来使用WebDriver执行此JavaScript。
这令人困惑吗?让我们分解吧。
例如:
userName = driver.find_element_by_xpath("//button[@name='username']")
driver.execute_script("arguments[0].click();", userName)
我们在这里做什么?
第1步:使用WebDriver提供的方法检查和捕获元素,例如'find_element_by_xpath ':
userName = driver.find_element_by_xpath("//button[@name='username']")
第2步:使用JavaScript声明并对元素执行单击操作:
arguments[0].click()
第3步:execute_script() 使用我们创建的JavaScript语句作为字符串值调用 方法,并使用WebDriver作为参数捕获Web元素:
driver.execute_script("arguments[0].click();", userName)
上面两行代码可以缩短为下面的格式,我们使用WebDriver找到一个元素,声明一些JavaScript函数,并使用WebDriver执行JavaScript。
driver.execute_script("arguments[0].click();",
driver.find_element_by_xpath("//button[@name='username']"))
更频繁面临的另一个问题是需要滚动到网页的底部。您可以在一行代码中执行此操作:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
此外,您的语句中可以有多个JavaScript操作。
例如:
userName = driver.find_element_by_xpath("//button[@name='username']")
password = driver.find_element_by_xpath("//button[@name='password']")
driver.execute_script("arguments[0].click();arguments[1].click();", userName, password)
在这种情况下,web元素的顺序的使用很重要。访问 index 与 [0] 一个JavaScript语句中的任何位置将检索传递的第一个网页元素。
driver.execute_script("arguments[1].click();arguments[0].click();", userName, password)
如何返回值
JavaScript执行程序的另一个重要方面是它可用于从Web元素中获取值。这意味着该 execute_script() 方法可以返回值。
例如:
print driver.execute_script('return document.getElementById("fsr").innerText')
请注意,如果您想要JavaScript代码返回的内容,则需要使用return。此外,可以使用Selenium定位元素并将其传递到脚本中。
什么元素找不到会发生什么?
当JavaScript找不到要操作的元素时,它会抛出带有相应错误消息的WebDriver异常。
场景1:我们正在尝试使用' print driver.execute_script('return document.getElementById("fsr").innerText') ' 来读取属性, 但网页中没有这样的元素。我们在异常跟踪中收到以下消息:
selenium.common.exceptions.WebDriverException: Message: unknown error: Cannot read property 'innerText' of null
场景2:我们试图在JavaScript中使用无效的操作或错误函数名称,例如' print driver.execute_script('document.getElementById("fsr").clic();') '。(注意click() 方法名称中的拼写错误 。)
selenium.common.exceptions.WebDriverException: Message: unknown error: document.getElementById(...).clic is not a function
摘要
以下是可以使用JavaScript的一些潜在操作的摘要。
使用Selenium处理DOM时,JavaScript的基本知识有很大帮助。
*请认真填写需求信息,我们会在24小时内与您取得联系。