使用 Python 將 HTML 轉成 PDF
背景
很多人應該經常遇到在網上看到好的學習教程和資料但卻沒有電子檔的,心里頓時癢癢,
下述指導一下大家,如何將網站上的各類教程轉換成 PDF 電子書。
關鍵核心
- 主要使用的是wkhtmltopdf的Python封裝—【pdfkit】
環境安裝
- python3系列
- pip install requests
- pip install beautifulsoup4
- pip install pdfkit
- 如果是liunx系,則 sudo yum intsall wkhtmltopdf
- 如果是windows系,則下載穩定版的 wkhtmltopdf 進行安裝,安裝完成之后把該程序的執行路徑加入到系統環境 $PATH 變量中
牛刀小試
一個簡單的例子:
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')
實例代碼實現
如將自強學堂中的django教程,生成一個pdf文件
#coding=utf-8
from __future__ import unicode_literals
import os,sys,re,time
import requests,codecs
from bs4 import BeautifulSoup
from urllib.parse import urlparse
import pdfkit
import platform
requests.packages.urllib3.disable_warnings()
system=platform.system()
print(sys.getdefaultencoding())
str_encode='gbk' if system is 'Windows' else 'utf-8'
print(str_encode)
html_template = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
{content}
</body>
</html>
"""
if not os.path.exists(os.path.join(os.path.dirname(__file__),'html')):
os.mkdir(os.path.join(os.path.dirname(__file__),'html'))
url_list=[]
start_url='http://www.ziqiangxuetang.com/django/django-tutorial.html'
# s=requests.session()
# html_doc=s.get('{}'.format(start_url),verify=False).content
# soup = BeautifulSoup(html_doc,'html.parser')
# print(soup.prettify())
def get_url_list(url):
"""
獲取所有URL目錄列表
:return:
"""
last_position = find_last(url, "/") + 1
tutorial_url_head = url[0:last_position]
domain = get_domain(url) + "/"
print(domain)
response = requests.get(url)
soup = BeautifulSoup(response.content, "html.parser")
urls = []
for a in soup.find_all("a"):
href = str(a.get('href'))
result = href.find('/')
if result == -1:
url = tutorial_url_head + href
else:
url = domain + href
if 'django' in url:
urls.append(url)
return urls
def find_last(string, char):
last_position = -1
while True:
position = string.find(char, last_position + 1)
if position == -1:
return last_position
last_position = position
def get_domain(url):
r = urlparse(url)
return r.scheme + "://" + r.netloc
def parse_url_to_html(url,name):
"""
解析URL,返回HTML內容
:param url:解析的url
:param name: 保存的html文件名
:return: html
"""
try:
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
# 正文
body = soup.find_all(class_="w-col l10 m12")
h = str(body)
html = h[1:-1]
html = html_template.format(content=html)
html = html.encode("utf-8")
title=soup.title.get_text()
print(url)
with open('{}/{}'.format(os.path.join(os.path.dirname(__file__),'html'),name), 'wb') as f:
f.write(html)
return '{}/{}'.format(os.path.join(os.path.dirname(__file__),'html'),name)
except Exception as e:
print(e)
def save_pdf(htmls, file_name):
"""
把所有html文件保存到pdf文件
:param htmls: html文件列表
:param file_name: pdf文件名
:return:
"""
options = {
'page-size': 'Letter',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
'custom-header': [
('Accept-Encoding', 'gzip')
],
'cookie': [
('cookie-name1', 'cookie-value1'),
('cookie-name2', 'cookie-value2'),
],
'outline-depth': 10,
}
pdfkit.from_file(htmls, file_name, options=options)
def main():
start = time.time()
urls = get_url_list(start_url)
htmls = [parse_url_to_html(url, str(index) + ".html") for index, url in enumerate(urls)]
print(htmls)
try:
save_pdf(htmls, 'cralwer_{}.pdf'.format(time.strftime('%Y_%m_%d_%H_%M_%S')))
except Exception as e:
print(e)
for html in htmls:
os.remove(html)
total_time = time.time() - start
print(u"總共耗時:{0:.2f}秒".format(total_time))
main()
大概思路
- 先傳入一個起始站點的url,本例以自強學堂為例,http://www.ziqiangxuetang.com/django/django-tutorial.html
- 然后,通過爬蟲獲取所有含django的url地址,存放在一個列表中,然后再依次獲取url,解析各個url中的正文body內容,通過人工分析,各個url正文Body對應的class為w-col l10 m12,所以只需要爬取w-col l10 m12的內容即可。
- 將獲取到的正文內容存放在html文件中,最終返回一個含所有html文件地址的列表htmls。
- 通過pdfkit.from_file接收一個htmls列表,生成對應pdf文件。
常見問題
-
IOError: ‘No wkhtmltopdf executable found’
確保 wkhtmltopdf 在你的系統路徑中($PATH),會通過 configuration進行了配置 (詳情看上文描述)。 在Windows系統中使用where wkhtmltopdf命令 或 在 linux系統中使用 which wkhtmltopdf 會返回 wkhtmltopdf二進制可執行文件所在的確切位置. -
IOError: ‘Command Failed’
如果出現這個錯誤意味著 PDFKit不能處理一個輸入。你可以嘗試直接在錯誤信息后面直接運行一個命令來查看是什么導致了這個錯誤 (某些版本的 wkhtmltopdf會因為段錯誤導致處理失敗 -
正常生成,但是出現中文亂碼
在html中加入
參考
志軍的項目: https://github.com/lzjun567/crawler_html2pdf
歡迎訂閱號

技術改變世界!
--狂詩絕劍

浙公網安備 33010602011771號