Python实现抓取HTML网页并以PDF文件形式保存的方法
作者:Limerence 发布时间:2022-12-15 22:56:30
本文实例讲述了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程序设计有所帮助。
来源:https://blog.csdn.net/hubaoquanu/article/details/66973149


猜你喜欢
- python logging模块主要是python提供的通用日志系统,使用的方法其实挺简单的,这块就不多介绍。下面主要会讲到在使用pytho
- 本文实例为大家分享了JavaScript实现扫雷小游戏的具体代码,供大家参考,具体内容如下工具:Sublime Text / Dreamwe
- 目标:代码改写成tf2格式把tensorflow 1.X中的代码,迁移到tensorflow2中。一些常见的改写经验。包括sess,tf.p
- 这篇文章主要介绍了python使用enumerate获取迭代元素下标,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习
- #测试网址: http://localhost/blog/testurl.php?id=5 //获取域名或主机地址 echo $_SERVE
- 今天想用ruby on rails做一个小项目,需要用到mysql数据库,项目中的数据已经有了,只不过是保存在Sql Server中,用ra
- 本文实例讲述了Python实现网络端口转发和重定向的方法。分享给大家供大家参考,具体如下:【任务】需要将某个网络端口转发到另一个主机(for
- 1. requests发送文件功能Requests 使得上传多部分编码文件变得很简单url = 'http://httpbin.or
- 这篇文章主要介绍了Python Lambda函数使用总结详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需
- 前言开发环境:Centos 7 + Python 3.5.1 + Qt Creator(只是使用Qt Creator编译而已,并没有使用QT
- 一个MDB数据库就是硬盘上的另外一个文件,所以,像其他文件一样,它也将遇到相同的文件访问许可问题。这个问题的意思是为了读取(和写入,就像您将
- 看代码吧~import pymongofrom dateutil import parserdateStr = "2019-05-
- 最近帮伙计做了一个从网页抓取股票信息并把相应信息存入MySQL中的程序。使用环境:Python 2.5 for WindowsMySQLdb
- mysql 误删除ibdata1之后如何恢复如果误删除了在线服务器中mysql innodb相关的数据文件ibdata1以及日志文件 ib_
- 利用ResNet18进行手写数字识别先写resnet18.py代码如下:import torchfrom torch import nnfr
- MobaXterm一款强大好用的远程终端登录利器,之前操作远端服务器一直使用的是XShell和Xftp,后来偶得一神器MobaXterm,能
- 小程序miniso的一个发布内容截图功能,话不多,先上代码wxml文件:<view class="cut-1-1 t-c {
- 1.figure语法及操作(1)figure语法说明figure(num=None, figsize=None, dpi=None, fac
- K线数据提取依据原有数据集格式,按要求生成新表:1、每分钟的close数据的第一条、最后一条、最大值及最小值,2、每分钟vol数据的增长量(
- Vue 单页面应用 把公共组件放在 app.vue 但是我希望某个页面没有这些公共组件怎么办(比如登陆页面)每个页面都有 导航栏 但是我希望