因爲閱讀網上的很多電子書存在翻頁繁瑣和查找不方便的問題,也很難在網站上做筆記。故查閱部分資料想要自己寫一個小爬蟲,然後可以將爬取到的電子書內容頁面(html格式)最終保存成PDF格式。故編寫如下爬蟲代碼來實現此功能。由於Python3和Python2.7的版本兼容性問題,from main import WKhtmlToPdf, wkhtmltopdf 始終未能或者成功,故只在正確爬取了電子書後,我並不能將很好的將已經處理成單頁的PDF文件拼接起來合成一個大的PDF文件。但是,條條大路通羅馬,我發現Adobe reader9.0可以直接幫助我解決PDF的拆分與合併問題。最終依然可以達到異曲同工的作用!
1.Adobe reader9.0直接做拆分
直接通過Adobe reader9.0打開要拆分的PDF,然後選擇"文檔">“拆分文檔”>頁數=1>確定>大功告成!
2.使用Adobe reader9.0直接做合併
“文件”>“合併”>“合併文件到單個PDF”>“添加文件”>通過上移和下調文件位置>合併文件>大功告成!
3.使用爬蟲爬取網站電子書的HTML,轉換成爲PDF後,再做PDF文件的合併
原理很簡單:通過查看網頁源代碼,發現網頁佈局上感興趣的標籤的規律,然後分別取到一級標題及其URL鏈接,二級標題及其URL鏈接,如此進行即可。說到這裏,這種嵌套的邏輯使用多層字典即可很好的完成嵌套分層功能。本文爬取的網站爲:http://python3-cookbook.readthedocs.io/zh_CN/latest/ ,此網站是學習Python3的最佳如本教程之一。
3.1.代碼
# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
import requests
import random
import time
import pandas as pd
import os
import sys
#from imp import reload
#reload(MyModule)
#from main import WKhtmlToPdf, wkhtmltopdf
#wkhtmltopdf在界面執行失敗,所以使用命令行試試。
import re
import pdfkit
from PyPDF2 import PdfFileMerger
def parse_title_and_url(html):
"""
python3-cookbook電子網頁轉爲PDF,提取一二級標題。
"""
base_url = html
res=requests.get(base_url)
res.encoding='utf-8' #設置頁面的編碼方式
soup=BeautifulSoup(res.text,'html.parser')
book_name = ''
chapter_info = []
book_name = soup.find('div', class_='wy-side-nav-search').a.text
menu = soup.find_all('div', class_='wy-menu')
chapters = menu[0].ul.find_all('li', class_='toctree-l1')
for chapter in chapters: #這裏獲得只是一級目錄
info = {}
# 獲取一級標題和url
# 標題中含有'/'和'*'會保存失敗
info['title'] = chapter.a.text.replace('/', '').replace('*', '')
info['url'] = base_url + chapter.a.get('href')
info['child_chapters'] = [] #裝在二級標題
#new_url1='http://python3-cookbook.readthedocs.io/zh_CN/latest/chapters/p01_data_structures_algorithms.html'
new_url1=base_url + chapter.a.get('href')
res1=requests.get(new_url1) #二級目錄
res1.encoding='utf-8' #設置頁面的編碼方式
soup=BeautifulSoup(res1.text,'html.parser')
try:
menu2 = soup.find_all('div', class_='toctree-wrapper compound')
chapters2 = menu2[0].ul.find_all('li', class_='toctree-l1')
except:
continue
for chapter1 in chapters2: #這裏獲得只是一級目錄
info1 = {}
# 獲取一級標題和url
# 標題中含有'/'和'*'會保存失敗
info1['title'] = chapter1.a.text.replace('/', '').replace('*', '')
info1['url'] = base_url + chapter1.a.get('href')[3:] #取出URL拼接中存在的'../'
info1['child_chapters'] = []
info['child_chapters'].append(info1)
chapter_info.append(info)
return chapter_info
html='http://python3-cookbook.readthedocs.io/zh_CN/latest/'
chapter_info=parse_title_and_url(html)
#獲取章節內容
def get_one_page(url):
"""
解析URL,獲取需要的html內容
:param url: 目標網址
:return: html
"""
res1=requests.get(url) #二級目錄
res1.encoding='utf-8' #設置頁面的編碼方式
return res1.text
html_template = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
{content}
</body>
</html>
"""
def get_content(url):
"""
解析URL,獲取需要的html內容
:param url: 目標網址
:return: html
"""
html = get_one_page(url)
soup = BeautifulSoup(html, 'html.parser')
content = soup.find('div', attrs={'itemprop': 'articleBody'}) #這裏沒有改變
html = html_template.format(content=content)
return html
#獲取章節內容
#循環保存下來每一個網頁
#for i in range(len(chapter_info)):
# for j in range(len(chapter_info[i]['child_chapters'])):
# url11=chapter_info[i]['child_chapters'][j]['url']
# #chapter_info[0]['child_chapters'][0]['url']
# #url11='http://python3-cookbook.readthedocs.io/zh_CN/latest/c01/p01_unpack_sequence_into_separate_variables.html'
# html11=get_content(url11)
# chapter_info[i]['child_chapters'][j]['child_chapters'].append(html11)
def save_pdf(html, filename):
"""
把所有html文件保存到pdf文件
:param html: 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_string(html, filename, options=options)
def parse_html_to_pdf():
"""
解析URL,獲取html,保存成pdf文件
:return: None
"""
try:
#for chapter in chapter_info[:1]:
for chapter in chapter_info[1:]:
ctitle = chapter['title']
url = chapter['url']
# 文件夾不存在則創建(多級目錄)
dir_name ='E:/ququ/'+ctitle+'/'
print(ctitle)
print(url)
print(dir_name)
if not os.path.exists(dir_name):
os.makedirs(dir_name)
html = get_content(url)
#padf_path = os.path.join(dir_name, ctitle + '.pdf')
save_pdf(html, dir_name+ctitle + '.pdf')
children = chapter['child_chapters']
if children:
for child in children:
html = get_content(child['url'])
pdf_path = dir_name+child['title'] + '.pdf'
save_pdf(html, pdf_path)
except Exception as e:
print(e)
parse_html_to_pdf()
3.2.代碼運行結果如下:
使用Adobe reader9.0直接做合併,同時注意調整順序即可。先完成各章的章節合併(選中上圖中的如:第一章:數據結構和算法>右鍵>" 在acrobat中合併支持的文件"),並注意將順序調整好,執行合併操作,合併後的文件命名爲"組合i" (i=1,…章節數),最後再對各章節做最終合併即可得到一個完整的python3-cookbook網頁版教程的PDF手冊。效果大致如下:
注:這裏我特別將文件名保存成Python3.PDF
完工後的效果展示如下: