python爬虫:将知乎专栏文章转为pdf

欢迎关注本人的知乎主页~

实现思路

  1. 用户输入专栏ID:

    1. 代码首先提示用户输入一个知乎专栏的ID,默认值为 'c_1747690982282477569'
    2. 输入的ID用于构建API请求的URL。
  2. 发送HTTP请求:

    1. 使用 requests.get() 向知乎API发送GET请求,获取指定专栏的文章列表。
    2. 检查响应的状态码,确认请求是否成功。
  3. 如果请求成功,解析返回的JSON数据,并将其保存到本地文件 zhihu.json 中。

  4. 定义处理HTML内容的函数 process_content

    1. 这个函数用于处理文章的HTML内容,具体操作包括:
      1. 移除 data-pid 属性。
      2. 替换特殊的字符 \u003C\u003E<>
      3. 添加段落的缩进和底部边距。
      4. 移除包含 <img><figure> 标签。
      5. 移除 class="ztext-empty-paragraph"<p> 标签。
      6. 去除多余的 <br> 标签。
      7. 确保每个段落都在 <p></p> 之间。
  5. 从之前保存的 zhihu.json 文件中读取JSON数据,并解析为Python字典。

  6. 从解析后的数据中提取文章的具体内容和标题。

  7. 创建一个名为 articles 的目录来保存生成的HTML文件。

  8. 使用 Jinja2 模板引擎初始化模板环境,并加载预定义的HTML模板 template.html

  9. 遍历文章数据并生成HTML文件:

    1. 对每篇文章的内容进行处理,并使用Jinja2模板渲染为完整的HTML页面。
    2. 将渲染后的HTML内容保存到 articles 目录下的 .html 文件中。
  10. 转换HTML文件为PDF文件:

    1. 创建一个名为 pdfs 的目录来保存生成的PDF文件。
    2. 遍历 articles 目录中的所有HTML文件,并使用 pdfkit 将其转换为PDF格式。
    3. 在转换过程中,禁止加载远程资源,并忽略加载错误。
  11. 输出结果信息,告知用户所有文章已保存为HTML文件,并且所有HTML文件已转换为PDF文件。

完整代码

python 复制代码
import json
import os
import re
from jinja2 import Environment, FileSystemLoader
import requests
import pdfkit

# 用户输入专栏名称,默认为c_1747690982282477569
column_id = input("请输入知乎专栏ID(默认为 c_1747690982282477569):") or 'c_1747690982282477569'
url = f'https://www.zhihu.com/api/v4/columns/{column_id}/articles'

# 发送请求获取专栏文章列表
response = requests.get(url)

# 检查请求是否成功
if response.status_code == 200:
    # 解析 JSON 数据
    data = response.json()
    
    # 保存到本地文件
    output_file = 'zhihu.json'
    with open(output_file, 'w', encoding='utf-8') as file:
        json.dump(data, file, ensure_ascii=False, indent=4)
    
    print(f"数据已保存到 {output_file}")
else:
    print(f"请求失败,状态码:{response.status_code}")

def process_content(content):
    """
    处理HTML内容,移除不需要的标签和属性,调整样式等。
    """
    # 移除标识符号
    # 匹配 data-pid 属性,并允许属性值使用普通双引号或转义的双引号,以及可能存在的空白字符
    content = re.sub(r'data-pid\s*=\s*(?:"|\")(.+?)(?:"|\")', '', content)
    
    # 替换特殊字符
    content = content.replace('\u003C', '<').replace('\u003E', '>')
    
    # 处理<p>标签,添加缩进和底部边距
    content = content.replace('<p ', '<p style="text-indent: 2em; margin-bottom: 1em;">')
    
    # 处理</p>标签
    content = content.replace('</p>', '</p>')
    
    # 移除包含 <img> 的 <figure> 标签
    content = re.sub(r'<figure.*?>.*?</figure>', '', content, flags=re.DOTALL)
    
    # 移除 class="ztext-empty-paragraph"
    content = re.sub(r'<p[^>]*class\s*=\s*["\']ztext-empty-paragraph["\'][^>]*>', '</p>', content)
    
    # 去除多余的<br>
    content = re.sub(r'</p><br>', '</p>', content)
    
    # 最后一个段落不应该有额外的换行
    if content.endswith('<p style="text-indent: 2em; margin-bottom: 1em;">'):
        content = content[:-len('<p style="text-indent: 2em; margin-bottom: 1em;">')]
    content += '</p>'
    
    # 确保每段文本都包裹在<p>和</p>之间
    paragraphs = re.split(r'(<p[^>]*>)', content)
    cleaned_paragraphs = []
    for i in range(0, len(paragraphs), 2):
        if i + 1 < len(paragraphs):  # 如果有对应的<p>标签
            cleaned_paragraphs.append(paragraphs[i])
            cleaned_paragraphs.append(paragraphs[i + 1].strip())
        else:
            cleaned_paragraphs.append(paragraphs[i].strip())
    
    content = ''.join(cleaned_paragraphs)
    
    return content

# 定义输入文件名
input_file = 'zhihu.json'

# 从文件中读取JSON数据
with open(input_file, 'r', encoding='utf-8') as file:
    json_data = file.read()

# 解析JSON数据
data = json.loads(json_data)

# 提取"data"数组中的内容
articles_data = data['data']

# 创建一个目录来保存HTML和PDF文件
output_dir = 'articles'
os.makedirs(output_dir, exist_ok=True)

# 初始化Jinja2环境
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('template.html')

# 遍历每一篇文章的数据
for article in articles_data:
    # 获取文章内容和标题
    article_id = str(article['id'])
    content = article['content']
    processed_content = process_content(content)
    title = article['title']
    
    # 渲染HTML模板
    html_content = template.render(title=title, content=processed_content)
    
    # 移除连续的 '>>',只保留一个 '>'
    html_content = re.sub(r'(>)>', r'\1', html_content)
    
    # 将内容写入HTML文件
    html_file_path = os.path.join(output_dir, f'{article_id}.html')
    with open(html_file_path, 'w', encoding='utf-8') as file:
        file.write(html_content)

print("所有文章已保存为HTML文件")

# 指定输入文件夹
input_dir = 'articles'

# 创建一个目录来保存 PDF 文件
output_dir = 'pdfs'
os.makedirs(output_dir, exist_ok=True)

# 遍历文件夹中的所有 HTML 文件
for filename in os.listdir(input_dir):
    if filename.endswith('.html'):
        # 获取 HTML 文件的完整路径
        html_file_path = os.path.join(input_dir, filename)
        
        # 构造 PDF 文件的名称
        pdf_filename = os.path.splitext(filename)[0] + '.pdf'
        pdf_file_path = os.path.join(output_dir, pdf_filename)
        
        # 读取 HTML 文件内容
        with open(html_file_path, 'r', encoding='utf-8') as file:
            html_content = file.read()
        
        # 将 HTML 文件转换为 PDF 文件
        try:
            # 使用 options 禁止加载远程资源
            options = {
                'disable-local-file-access': None,
                'load-error-handling': 'ignore',
            }
            # 注意html文件名不能含有中文
            pdfkit.from_string(html_content, pdf_file_path, options=options)
            print(f"{filename} 已转换为 {pdf_filename}")
        except Exception as e:
            print(f"转换 {filename} 时发生错误:{e}")

print("所有 HTML 文件已转换为 PDF 文件。")

运行结果

待完善的功能

  1. 本项目没有保存知乎文章中的图片,因为图片大小较难以控制;
  2. 知乎文章中的引用和脚注没能很好地处理。

以上问题有待解决。另外,这篇文章介绍了直接保存知乎网页文章的方法,值得参考。

相关推荐
好开心啊没烦恼8 分钟前
Python 数据分析:计算,分组统计1,df.groupby()。听故事学知识点怎么这么容易?
开发语言·python·数据挖掘·数据分析·pandas
lljss20201 小时前
Python11中创建虚拟环境、安装 TensorFlow
开发语言·python·tensorflow
空中湖1 小时前
tensorflow武林志第二卷第九章:玄功九转
人工智能·python·tensorflow
CodeCraft Studio2 小时前
CAD文件处理控件Aspose.CAD教程:使用 Python 将绘图转换为 Photoshop
python·photoshop·cad·aspose·aspose.cad
Python×CATIA工业智造4 小时前
Frida RPC高级应用:动态模拟执行Android so文件实战指南
开发语言·python·pycharm
onceco5 小时前
领域LLM九讲——第5讲 为什么选择OpenManus而不是QwenAgent(附LLM免费api邀请码)
人工智能·python·深度学习·语言模型·自然语言处理·自动化
狐凄5 小时前
Python实例题:基于 Python 的简单聊天机器人
开发语言·python
悦悦子a啊6 小时前
Python之--基本知识
开发语言·前端·python
笑稀了的野生俊8 小时前
在服务器中下载 HuggingFace 模型:终极指南
linux·服务器·python·bash·gpu算力
Naiva8 小时前
【小技巧】Python+PyCharm IDE 配置解释器出错,环境配置不完整或不兼容。(小智AI、MCP、聚合数据、实时新闻查询、NBA赛事查询)
ide·python·pycharm