目前接到一个任务,就是把confluence上的所有文章保存为PDF,其实就是把HTML字符串保存为PDF文件,一开始在网上各种搜,copy代码下来运行都会报错,简直要疯了,最后找到了一个大佬写的代码,可以运行!!!在此十分感谢!!!原文链接见文章末尾
首先安装wkhtmltopdf,去官网下载wkhtmltopdf的exe文件运行安装就行
我把大佬的代码修改了一下,结合Python协程,让文章下载的速度更快,其实还可以再结合多线程完成,看具体的需求了。代码如下
import re
import requests # pip install requests
import parsel # pip install parsel
import pdfkit # pip install pdfkit
import asyncio
import aiohttp # pip install aiohttp
html_str = """
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
{article}
</body>
</html>
"""
def change_title(title):
"""
替换标题中的特殊字符
:param title: 传入文章标题
:return: 返回一个替换掉特殊字符的标题
"""
# 使用re.compile()将正则表达式的字符串形式编译为一个对象,通过该对象提供的一些列方法对文本进行匹配查找
pattern = re.compile(r"[/\:*?\"<>|]") # '/ \ : * ? " < > |'
# re.sub() 第一个参数对应的正则表达式,第二个参数为要替换成的字符串, 第三个参数为源字符串
new_title = re.sub(pattern, "_", title) # 替换为下划线
return new_title
async def get_all_page_url(url):
"""
获取需要保存的文章的url并保存为PDF文件
:param url: 文章列表的url
:return:
"""
headers = {
'user-agent': 'xxx' # 写自己浏览器的信息
}
response = requests.get(url=url, headers=headers)
selector = parsel.Selector(response.text)
# 获取所有文章的URL
hrefs = selector.css('ul.column_article_list li a::attr(href)').getall()
# wkhtmltopdf.exe 存放的路径
path = r"xxx\bin\wkhtmltopdf.exe"
config = pdfkit.configuration(wkhtmltopdf=path)
async with aiohttp.ClientSession() as client:
await asyncio.gather(*[get_page_content_to_pdf(client, link, config, headers) for link in hrefs])
async def get_page_content_to_pdf(client, url, config_obj, headers):
"""
保存网页上的内容为PDF文件
:param client:
:param url:
:param config_obj:
:param headers:
:return:
"""
select = {
'title': '#articleContentId::text',
'content': '#content_views'
}
async with client.get(url, headers=headers) as resp:
assert resp.status == 200
text = await resp.text()
selector = parsel.Selector(text)
title = selector.css(select['title']).get()
content = selector.css(select['content']).get()
new_title = change_title(title)
# 创建文件保存地址以及保存文件的名字和格式
pdf_path = './pdf/' + new_title + '.pdf'
# str.format() 字符串格式化方法
html = html_str.format(article=content)
print(f'正在保存:{title}')
# 把 html 通过 pdfkit 变成 pdf 文件
pdfkit.from_string(html, pdf_path, configuration=config_obj)
print(f'{title}保存完成')
if __name__ == '__main__':
_url = 'https://blog.csdn.net/2301_77659011/category_12530863.html'
asyncio.run(get_all_page_url(_url))
经过发现,如果要保存的网页上有图片之类的资源,需要图片的链接是完整的外部链接(即以http开头的),不然保存下来的pdf里会没有图片的部分,目前没有发现更好的解决方法
关于HTML转PDF,参考:HTML转PDF
关于协程中的aiohttp.ClientSession,参考:aiohttp.ClientSession