Python实现抓取HTML网页并以PDF文件形式保存的方法


Posted in Python onMay 08, 2018

本文实例讲述了Python实现抓取HTML网页并以PDF文件形式保存的方法。分享给大家供大家参考,具体如下:

一、前言

今天介绍将HTML网页抓取下来,然后以PDF保存,废话不多说直接进入教程。

今天的例子以廖雪峰老师的Python教程网站为例:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000

二、准备工作

1. PyPDF2的安装使用(用来合并PDF):

PyPDF2版本:1.25.1

https://pypi.python.org/pypi/PyPDF2/1.25.1

https://github.com/mstamy2/PyPDF2

安装:

pip install PyPDF2

使用示例:

from PyPDF2 import PdfFileMerger
merger = PdfFileMerger()
input1 = open("hql_1_20.pdf", "rb")
input2 = open("hql_21_40.pdf", "rb")
merger.append(input1)
merger.append(input2)
# Write to an output PDF document
output = open("hql_all.pdf", "wb")
merger.write(output)

2. requests、beautifulsoup 是爬虫两大神器,reuqests 用于网络请求,beautifusoup 用于操作 html 数据。有了这两把梭子,干起活来利索。scrapy 这样的爬虫框架我们就不用了,这样的小程序派上它有点杀鸡用牛刀的意思。此外,既然是把 html 文件转为 pdf,那么也要有相应的库支持, wkhtmltopdf 就是一个非常的工具,它可以用适用于多平台的 html 到 pdf 的转换,pdfkit 是 wkhtmltopdf 的Python封装包。首先安装好下面的依赖包

pip install requests
pip install beautifulsoup4
pip install pdfkit

3. 安装 wkhtmltopdf

Windows平台直接在 http://wkhtmltopdf.org/downloads.html 下载稳定版的 wkhtmltopdf 进行安装,安装完成之后把该程序的执行路径加入到系统环境 $PATH 变量中,否则 pdfkit 找不到 wkhtmltopdf 就出现错误 “No wkhtmltopdf executable found”。Ubuntu 和 CentOS 可以直接用命令行进行安装

$ sudo apt-get install wkhtmltopdf # ubuntu
$ sudo yum intsall wkhtmltopdf   # centos

三、数据准备

1. 获取每篇文章的url

def get_url_list():
  """
  获取所有URL目录列表
  :return:
  """
  response = requests.get("http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000")
  soup = BeautifulSoup(response.content, "html.parser")
  menu_tag = soup.find_all(class_="uk-nav uk-nav-side")[1]
  urls = []
  for li in menu_tag.find_all("li"):
    url = "http://www.liaoxuefeng.com" + li.a.get('href')
    urls.append(url)
  return urls

2. 通过文章url用模板保存每篇文章的HTML文件

html模板:

html_template = """
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
</head>
<body>
{content}
</body>
</html>
"""

进行保存:

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_="x-wiki-content")[0]
    # 标题
    title = soup.find('h4').get_text()
    # 标题加入到正文的最前面,居中显示
    center_tag = soup.new_tag("center")
    title_tag = soup.new_tag('h1')
    title_tag.string = title
    center_tag.insert(1, title_tag)
    body.insert(1, center_tag)
    html = str(body)
    # body中的img标签的src相对路径的改成绝对路径
    pattern = "(<img .*?src=\")(.*?)(\")"
    def func(m):
      if not m.group(3).startswith("http"):
        rtn = m.group(1) + "http://www.liaoxuefeng.com" + m.group(2) + m.group(3)
        return rtn
      else:
        return m.group(1)+m.group(2)+m.group(3)
    html = re.compile(pattern).sub(func, html)
    html = html_template.format(content=html)
    html = html.encode("utf-8")
    with open(name, 'wb') as f:
      f.write(html)
    return name
  except Exception as e:
    logging.error("解析错误", exc_info=True)

3. 把html转换成pdf

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)

4. 把转换好的单个PDF合并为一个PDF

merger = PdfFileMerger()
for pdf in pdfs:
  merger.append(open(pdf,'rb'))
  print u"合并完成第"+str(i)+'个pdf'+pdf

完整源码:

# coding=utf-8
import os
import re
import time
import logging
import pdfkit
import requests
from bs4 import BeautifulSoup
from PyPDF2 import PdfFileMerger
html_template = """
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
</head>
<body>
{content}
</body>
</html>
"""
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_="x-wiki-content")[0]
    # 标题
    title = soup.find('h4').get_text()
    # 标题加入到正文的最前面,居中显示
    center_tag = soup.new_tag("center")
    title_tag = soup.new_tag('h1')
    title_tag.string = title
    center_tag.insert(1, title_tag)
    body.insert(1, center_tag)
    html = str(body)
    # body中的img标签的src相对路径的改成绝对路径
    pattern = "(<img .*?src=\")(.*?)(\")"
    def func(m):
      if not m.group(3).startswith("http"):
        rtn = m.group(1) + "http://www.liaoxuefeng.com" + m.group(2) + m.group(3)
        return rtn
      else:
        return m.group(1)+m.group(2)+m.group(3)
    html = re.compile(pattern).sub(func, html)
    html = html_template.format(content=html)
    html = html.encode("utf-8")
    with open(name, 'wb') as f:
      f.write(html)
    return name
  except Exception as e:
    logging.error("解析错误", exc_info=True)
def get_url_list():
  """
  获取所有URL目录列表
  :return:
  """
  response = requests.get("http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000")
  soup = BeautifulSoup(response.content, "html.parser")
  menu_tag = soup.find_all(class_="uk-nav uk-nav-side")[1]
  urls = []
  for li in menu_tag.find_all("li"):
    url = "http://www.liaoxuefeng.com" + li.a.get('href')
    urls.append(url)
  return urls
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()
  file_name = u"liaoxuefeng_Python3_tutorial"
  urls = get_url_list()
  for index, url in enumerate(urls):
   parse_url_to_html(url, str(index) + ".html")
  htmls =[]
  pdfs =[]
  for i in range(0,124):
    htmls.append(str(i)+'.html')
    pdfs.append(file_name+str(i)+'.pdf')
    save_pdf(str(i)+'.html', file_name+str(i)+'.pdf')
    print u"转换完成第"+str(i)+'个html'
  merger = PdfFileMerger()
  for pdf in pdfs:
    merger.append(open(pdf,'rb'))
    print u"合并完成第"+str(i)+'个pdf'+pdf
  output = open(u"廖雪峰Python_all.pdf", "wb")
  merger.write(output)
  print u"输出PDF成功!"
  for html in htmls:
    os.remove(html)
    print u"删除临时文件"+html
  for pdf in pdfs:
    os.remove(pdf)
    print u"删除临时文件"+pdf
  total_time = time.time() - start
  print(u"总共耗时:%f 秒" % total_time)
if __name__ == '__main__':
  main()

更多Python相关内容感兴趣的读者可查看本站专题:《Python文件与目录操作技巧汇总》、《Python编码操作技巧总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》及《Python入门与进阶经典教程》

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
Python库urllib与urllib2主要区别分析
Jul 13 Python
python 采集中文乱码问题的完美解决方法
Sep 27 Python
详解django.contirb.auth-认证
Jul 16 Python
解决python3 urllib 链接中有中文的问题
Jul 16 Python
Python 编程速成(推荐)
Apr 15 Python
在pycharm下设置自己的个性模版方法
Jul 15 Python
django和vue实现数据交互的方法
Aug 21 Python
python制作英语翻译小工具代码实例
Sep 09 Python
Tensorflow实现多GPU并行方式
Feb 03 Python
keras Lambda自定义层实现数据的切片方式,Lambda传参数
Jun 11 Python
python爬虫使用正则爬取网站的实现
Aug 03 Python
浅谈python数据类型及其操作
May 25 Python
Python读写docx文件的方法
May 08 #Python
python docx 中文字体设置的操作方法
May 08 #Python
Python解析并读取PDF文件内容的方法
May 08 #Python
python-docx修改已存在的Word文档的表格的字体格式方法
May 08 #Python
对Python中gensim库word2vec的使用详解
May 08 #Python
用python处理MS Word的实例讲解
May 08 #Python
基于python批量处理dat文件及科学计算方法详解
May 08 #Python
You might like
火车头采集器3.0采集图文教程
2007/03/17 PHP
PHP实现MySQL更新记录的代码
2008/06/07 PHP
php中session_unset与session_destroy的区别分析
2011/06/16 PHP
php中时间轴开发(刚刚、5分钟前、昨天10:23等)
2011/10/03 PHP
php下载文件的代码示例
2012/06/29 PHP
用PHP提取中英文词语以及数字的首字母的方法介绍
2013/04/23 PHP
PHP获取和操作配置文件php.ini的几个函数介绍
2013/06/24 PHP
PHP 的Opcache加速的使用方法
2017/12/29 PHP
laravel执行php artisan migrate报错的解决方法
2019/10/09 PHP
javascript操作文本框readOnly
2007/05/15 Javascript
js wmp操作代码小结(音乐连播功能)
2008/11/08 Javascript
聊聊JS动画库 Velocity.js的使用
2018/03/13 Javascript
用Object.prototype.toString.call(obj)检测对象类型原因分析
2018/10/11 Javascript
Element-UI踩坑之Pagination组件的使用
2018/10/29 Javascript
微信小程序webview实现长按点击识别二维码功能示例
2019/01/24 Javascript
一篇不错的Python入门教程
2007/02/08 Python
谈谈Python进行验证码识别的一些想法
2016/01/25 Python
浅谈python函数之作用域(python3.5)
2017/10/27 Python
python删除字符串中指定字符的方法
2018/08/13 Python
Python设计模式之享元模式原理与用法实例分析
2019/01/11 Python
python变量赋值方法(可变与不可变)
2019/01/12 Python
详解Python3 对象组合zip()和回退方式*zip
2019/05/15 Python
python实现websocket的客户端压力测试
2019/06/25 Python
Iconfont(矢量图标)+iconmoon(图标svg互转)配合javascript实现社交分享系统
2020/04/21 Python
Python devel安装失败问题解决方案
2020/06/09 Python
Python爬取网页信息的示例
2020/09/24 Python
python对输出的奇数偶数排序实例代码
2020/12/04 Python
Python实现石头剪刀布游戏
2021/01/20 Python
css3圆角边框和边框阴影示例
2014/05/05 HTML / CSS
美国咖啡批发网站:Coffee.org
2017/06/29 全球购物
DC Shoes官网:美国滑板鞋和服饰品牌
2017/09/03 全球购物
Herve Leger官网:标志性绷带连衣裙等
2018/12/26 全球购物
全球最大化妆品零售网站:SkinStore
2020/10/24 全球购物
家长通知书家长评语
2014/04/17 职场文书
烹饪大赛策划方案
2014/05/26 职场文书
事业单位岗位说明书
2015/10/08 职场文书