前言
掘金有在看各位的很多优秀的专栏,我一直在思考,如何把这些专栏的文章内容整合在一起呢?
对,生成PDF文件,数据聚合,方便你我她他它。
Don't worry! 实现的方法方式都很简单,一共不到200行代码。
在线预览:我的掘金前端周栏.pdf
效果演示
代码执行
PDF文档效果
基本思路
- 收集API信息和关联
- 下载专栏数据
- 生成html代码 (markdown转html)
- 生成pdf文件
收集API信息和关联
数据是一切的根源,所以先分析如何获取掘金专栏数据。
其实三个API就满足需求:
- 专栏摘要信息
作用: 获取专栏的摘要信息,主要是专栏ID和专栏名称
API地址:api.juejin.cn/content_api… - 专栏文章列表
作用: 获取专栏文章列表,主要是文章ID,一个中间商罢了。
API地址:api.juejin.cn/content_api… - 文章详情
作用: 获取文章详情,主要是文章标题和MarkDown格式的文章内容
API地址: api.juejin.cn/content_api…
整体流程如下:
获取专栏信息
API地址: api.juejin.cn/content_api…
请求参数
QueryString
- column_id 专栏ID
数据结构
有用的就是 title
字段,生成html和pdf时需要。
{ column_id:""6979380367216082957" data: { "column_version": { "title": "前端基础进阶“ // 专栏标题 } } } 复制代码
获取专栏文章列表
API 地址https://api.juejin.cn/content_api/v1/column/articles_cursor
请求参数
{ "column_id":"6979380367216082957", // 专栏ID "cursor":"0", // 当前下标 "limit":20, // 一页大小 "sort":0 // 0 发布事件从近到远,反之从远到近 } 复制代码
数据结构有用的其实就 artcile_id
{ "err_no": 0, "err_msg": "success", "cursor": "2", "count": 5, "has_more": false, "data": [ { "article_id": "6989391487200919566", ..................... } ] } 复制代码
获取文章详情
API地址:
https://api.juejin.cn/content_api/v1/article/detail
请求参数:
{ "article_id": "6989391487200919566" // 文章ID } 复制代码
返回结果:
data
属性中的mark_content
字段就是markdown语法的原始内容。
{ "data": { "article_id": "6989391487200919566", "article_info": { "mark_content": "---\ntheme: channing-cyan\nhighlight: a11y-dark\n---\n\n\n## 前言\n\n本文收录在 **[前端基础进阶](https://juejin.cn/column/6979380367216082957)** 专栏" } }, "err_no": 0, "err_msg": "success", } 复制代码
下载专栏数据
我们选择Python里面比较有名的requests
库,虽然不支持异步,不过问题不大。
基本顺序:
- 下载专栏信息
- 下载专栏文章列表信息
- 下载单篇文章信息
注意点:
- 我们会按照专栏ID创建文件夹,把下载下来的JSON格式的文件都放到下面
至于为什么? 21世纪什么最重要, 数据!!
有了数据,你可以自己生成网页,做成word, pdf,亦或其他,无线的选择。
本着本文为Python类别,还是贴一段主流程代码: 更多细节查看源码 JueJinColToPdf
def downloadColumn(cid): column = getColumn(cid); print("获取专栏信息成功,专栏名称:", column["data"]["column_version"]["title"]); saveColumn(cid, json.dumps(column["data"])) articleList = getArticleList(cid) saveArticleList(cid, json.dumps(articleList["data"])) articleIds = list(map(lambda item: item["article_id"], articleList["data"])) print("获取专栏文章列表成功:", articleIds) for artId in articleIds: artContent = getArticleContent(artId) saveArticleContent(cid, artId, json.dumps(artContent["data"])) print("文章ID为 %s 的文章下载完毕" % artId) 复制代码
生成Html代码
直接说一些问题
如何把markdown格式转为html代码
巨人的肩上markdown
库
html += markdown.markdown( removeScheme(article["article_info"]["mark_content"]), extensions=extensions) 复制代码
如何高亮代码
Pygments
库,
pygmentize -S default -f html -a .codehilite > code.css 复制代码
然后设置一个markdown
库的extensions
extensions = [ # 根据不同教程加上的扩展 'markdown.extensions.extra', 'markdown.extensions.codehilite', # 代码高亮扩展 'markdown.extensions.toc', 'markdown.extensions.tables', 'markdown.extensions.fenced_code', ] html += markdown.markdown( removeScheme(article["article_info"]["mark_content"]), extensions=extensions) 复制代码
去掉掘金主题和代码风格
如果你选择了主题或者代码高亮,markdown头部会多出如下的内容。
--- theme: github highlight: a11y-light --- 复制代码
方案:正则替换或者字符串截取
如何自定义样式
新建一个 extend.css
* { font-size: 30px; // 默认字体 } img{ display: block; min-width: 50%; // 图片至少50% } 复制代码
如何生成一个大的html文件
- 创建一个html文件,
core.css
和extend.css文件
写入html的style标签里面- 写入头部的html,
- 写入markdown转换后的html,
- 最后写入尾部的html。
如果文章太多,怎么办
以一定文章数量分割,比如20篇
以一定文字数量分割,比如5万字
在笔者的代码中是未实现的,不过问题不大,我之前有用html生成400多页的pdf也妥妥的。
转为pdf文件
借助 wkhtmltopdf.exe, 这款神奇可以把网络地址或者本地html文件直接转换成为pdf文件。
最重要的是其完美的支持目录。
从官方下载安装,然后配置一下环境变量就可以,代码嘛就下面这点。
def genPdf(title): # TODO:: 需要配置全局路径 exePath = "wkhtmltopdf.exe" sourcePath = "./htmls/%s.html" % title targetPath = "./pdfs/%s.pdf" % title cmd = '"%s" --outline-depth 2 --footer-center [page] "%s" "%s"' % ( exePath, sourcePath, targetPath) print(cmd) subprocess.call(cmd) 复制代码
写在最后
写作不易,你的一赞一评,就是我最大的动力。