解放双手,每天主动把博客信息更新至GitHub主页
背景
最近在弄GitHub主页丑化的时候,搞了一些感觉比拟好玩乏味的货色,有趣味的敌人能够看看
这里贴个我的主页地址:https://github.com/JS-banana,有趣味的能够看看~
过后在编辑个人信息介绍的时候,产生了一个想法:能够在我的GitHub主页同步我的博客更新状态吗?
当我更新博客的时候,我的GitHub主页会主动把我博客最新更新的内容同步过来,很棒啊有没有~
这是过后产生的一个想法,起初就钻研了一下。最开始是想用nodejs
写个爬虫搞一搞的,也没啥问题,不过这样搞会有很多缺点,我本人也只能搞个半成品,也不具备肯定的复用性,就排除了~
起初看到了Python的feedparser
库,感觉十分适合有没有啊。(feedparser
是python中最罕用的RSS程序库,应用它咱们可轻松地实现从任何 RSS 或 Atom 订阅源失去题目、链接和文章的条目。)
也看了下成果,感觉很不错,这样咱们只有做两件事即可:
- 实现 Atom 订阅源(供
feedparser
库应用) - 实现
README.md
文件的动静更新(获取到订阅信息后更新主页)
RSS、Atom 订阅源
RSS订阅咱们应该不生疏,咱们在浏览很多大佬博客的时候、出名网站和服务时会发现他们都提供有RSS/Atom订阅,那么什么是RSS?什么是Atom呢?
什么是 RSS?
- 指 Really Simple Syndication(真正繁难联结)
- 使您有能力聚合(syndicate)网站的内容
- 定义了非常简单的办法来共享和查看题目和内容
- 文件可被自动更新
- 容许为不同的网站进行视图的个性化
- 应用
XML
编写
为什么应用 RSS?
RSS 被设计用来展现选定的数据。
如果没有 RSS,用户就不得不每日都来您的网站查看新的内容。对许多用户来说这样太费时了。通过 RSS feed(RSS 通常被称为 News feed 或 RSS feed),用户们能够应用 RSS 聚合器来更快地查看您的网站更新(RSS 聚合器是用来汇集并分类 RSS feed 的网站或软件)。
RSS的将来倒退(Atom的诞生)
因为RSS 2.0的版权问题,该协定前途未卜
因为RSS前途未卜,而且RSS规范倒退存在诸多问题或有余,于是ATOM横空出世,能够先简略的了解为RSS的替代品。
FEED 是什么
FEED其实就是RSS(或ATOM)和订阅用户之间的“中间商”,起到帮忙零售传递信息的作用。所以,FEED的常见格局就是RSS和ATOM,网络上说的FEED订阅,更确切的说法应该依然是RSS或ATOM订阅。
什么是订阅
订阅跟一般大家订阅报刊相似,不过简直所有网站的RSS
/ATOM
订阅都是收费的,也有一些“非主流”一族要免费订阅的,当然FEED订阅只是网络上的信息传递,个别不波及实体材料传递,所以大家遇到喜爱的网站,并且也喜爱应用在线或离线浏览,尽可订阅,而且能够随时退订。
总结
RSS 和 Atom 具备类似的基于 XML
的格局。它们的根本构造是雷同的,只是在节点的表达式上有一点区别。咱们只有理解ATOM是对RSS2.0的改良就能够了。
生成本人网站的Atom订阅源
Atom订阅源 根本构造
理解 atom.xml
的根本格局和语法,看个最简略的demo
<!-- 头信息 --><?xml version="1.0" encoding="utf-8"?><!-- 主体 --><feed xmlns="http://www.w3.org/2005/Atom"> <!-- 根本信息 --> <title>小帅の技术博客</title> <link href="https://ssscode.com/atom.xml" rel="self"/> <link href="https://ssscode.com/"/> <updated>2021-08-28 16:25:56</updated> <id>https://ssscode.com/</id> <author> <name>JS-banana</name> <email>sss213018@163.com</email> </author> <!-- 内容区 --> <entry> <title>Webpack + React + TypeScript 构建一个标准化利用</title> <link href="https://ssscode.com/pages/c3ea73/" /> <id>https://ssscode.com/pages/c3ea73/</id> <published>2021-08-28 16:25:56</published> <update>2021-08-28 16:25:56</update> <content type="html"></content> <summary type="html"></summary> <category term="webpack" scheme="https://ssscode.com/categories/?category=JavaScript"/> </entry> <entry> ... </entry> ...</feed>
根本信息那一块齐全能够本人自定义配置好,而后,再去头去尾之后,能够发现咱们只有关怀 <entry> ... </entry>
标签内容即可,也就是每条博客文章的根本信息~
因而,咱们只有依照这个标准、格局、语法,齐全能够本人生成atom.xml
,nice~
不想本人写的能够试试这个 feed
编写 atom.xml 文件生成函数
因为我的博客是以vuepress
搭建的(webpack
+ vue2.x
),这里就以nodejs
为例
读取所有markdwon文件就不细说了,咱们拿到所有的列表数据,进行一下简略的解决,这里只填写一些咱们须要的数据即可,如果想浏览订阅源应用,也能够本人丰盛信息内容~
const DATA_FORMAT = 'YYYY-MM-DD HH:mm:ss';// posts 是所有的博客文章信息// xml 中的 & 符号须要替换为 & 否则会有语法错误function toXml(posts) { const feed = `<?xml version="1.0" encoding="utf-8"?> <feed xmlns="http://www.w3.org/2005/Atom"> <title>小帅の技术博客</title> <link href="https://ssscode.com/atom.xml" rel="self"/> <link href="https://ssscode.com/"/> <updated>${dayjs().format(DATA_FORMAT)}</updated> <id>https://ssscode.com/</id> <author> <name>JS-banana</name> <email>sss213018@163.com</email> </author> ${posts .map(item => { return ` <entry> <title>${item.title.replace(/(&)/g, '&')}</title> <link href="https://ssscode.com${item.permalink}" /> <id>https://ssscode.com${item.permalink}</id> <published>${item.date.slice(0, 10)}</published> <update>${item.date}</update> </entry>`; }) .join('\n')} </feed>`; fs.writeFile(path.resolve(process.cwd(), './atom.xml'), feed, function(err) { if (err) return console.log(err); console.log('文件写入胜利!'); });}
node
执行该文件,应该会在同级目录下生成一个 atom.xml
文件,能够看到
ok,atom订阅源搞定~
feedparser的简略用法
python feedparser,网上仿佛也有node版本的,这里就先不关怀了
把方才的demo内容片段复制到atom.xml
文件,简略测试下用法,看下返回值格局,为了更清晰的看构造,我把python执行的后果解决了一下
atom.xml
源文件
<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"> <title>小帅の技术博客</title> <link href="https://ssscode.com/atom.xml" rel="self"/> <link href="https://ssscode.com/"/> <updated>2021-08-28 16:25:56</updated> <id>https://ssscode.com/</id> <author> <name>JS-banana</name> <email>sss213018@163.com</email> </author> <entry> <title>Webpack + React + TypeScript 构建一个标准化利用</title> <link href="https://ssscode.com/pages/c3ea73/" /> <id>https://ssscode.com/pages/c3ea73/</id> <published>2021-08-28 16:25:56</published> <update>2021-08-28 16:25:56</update> </entry></feed>
main.py
脚本
import feedparserblog_feed_url = "./atom.xml"feeds = feedparser.parse(blog_feed_url)print (feeds)
输入后果大抵构造如下
{ bozo: 1, // entries entries: [ { title: "Webpack + React + TypeScript 构建一个标准化利用", title_detail: { type: "text/dplain", language: None, base: "", value: "Webpack + React + TypeScript 构建一个标准化利用", }, links: [{ href: "https://ssscode.com/pages/c3ea73/", rel: "alternate", type: "text/html" }], link: "https://ssscode.com/pages2/c3ea73/", id: "https://ssscode.com/pages/c3ea73/", guidislink: False, published: "2021-08-28 16:25:56", publoished_parsed: time.struct_time(), // 一个日期处理函数,参数比拟多,我删掉了,只看代码构造 update: "2021-08-28 16:25:56", }, ], // feed feed: { title: "小帅の技术博客", title_detail: { type: "text/plain", language: None, base: "", value: "小帅の技术博客" }, links: [ { href: "https://ssscode.com/atom.xml", rel: "self", type: "application/atom+xml" }, { href: "https://ssscode.com/", rel: "alternate", type: "text/html" }, ], link: "https://ssscode.com/", updated: "2021-08-28 16:25:56", updated_parsed: time.struct_time(), id: "https://ssscode.com/", guidislink: False, authors: [{ name: "JS-banana", email: "sss213018@163.com" }], author_detail: { name: "JS-banana", email: "sss213018@163.com" }, author: "JS-banana (sss213018@163.com)", }, headers: {}, encoding: "utf-8", version: "atom10", bozo_exception: SAXParseException("XML or text declaration not at start of entity"), namespaces: { "": "http://www.w3.org/2005/Atom" },}
能够看到,拿到所有的entries
即可,编写个函数,取一些咱们须要的内容
def fetch_blog_entries(): entries = feedparser.parse(blog_feed_url)["entries"] return [ { "title": entry["title"], "url": entry["link"].split("#")[0], "published": entry["published"].split("T")[0], } for entry in entries ]
替换markdown文件指定区域内容
剩下最初一步就是:怎么把咱们README.md
主页文件中指定的区域内容替换掉,而后在推送到GitHub实现更新即可
### Hello, 我是小帅! ......其余信息<!-- start --> 这里显示博客信息<!-- end -->
如上,除了指定的区域须要更新,其余中央是不须要变动的
这时就能够通过Python能够读取正文,而后应用正则解决替换,即可
咱们在 README.md
中标记正文
<!-- blog starts --> ...<!-- blog ends -->
代码:
def replace_chunk(content, marker, chunk, inline=False): r = re.compile( r"<!\-\- {} starts \-\->.*<!\-\- {} ends \-\->".format(marker, marker), re.DOTALL, ) if not inline: chunk = "\n{}\n".format(chunk) chunk = "<!-- {} starts -->{}<!-- {} ends -->".format(marker, chunk, marker) return r.sub(chunk, content)
最初,再联合接口申请、文件读取等,残缺代码如下
import feedparserimport jsonimport pathlibimport reimport osimport datetimeblog_feed_url = "https://ssscode.com/atom.xml"root = pathlib.Path(__file__).parent.resolve()def replace_chunk(content, marker, chunk, inline=False): r = re.compile( r"<!\-\- {} starts \-\->.*<!\-\- {} ends \-\->".format(marker, marker), re.DOTALL, ) if not inline: chunk = "\n{}\n".format(chunk) chunk = "<!-- {} starts -->{}<!-- {} ends -->".format(marker, chunk, marker) return r.sub(chunk, content)def fetch_blog_entries(): entries = feedparser.parse(blog_feed_url)["entries"] return [ { "title": entry["title"], "url": entry["link"].split("#")[0], "published": entry["published"].split("T")[0], } for entry in entries ]if __name__ == "__main__": readme = root / "README.md" readme_contents = readme.open(encoding='UTF-8').read() entries = fetch_blog_entries()[:5] entries_md = "\n".join( ["* <a href='{url}' target='_blank'>{title}</a> - {published}".format(**entry) for entry in entries] ) rewritten = replace_chunk(readme_contents, "blog", entries_md) readme.open("w", encoding='UTF-8').write(rewritten)
我对Python也不熟,不过跟着前人的脚步,模拟着应用也能达到预期成果,还行~
最近略微接触了一些Python相干的脚本库,发现还挺有意思的,感觉还是很有必要学习学习,日常应用中还是很有帮忙的,毕竟当初Python也是很炽热的嘛,就算当工具用,感觉也很强力~
配置 GitHub Action 定时工作
实现性能的脚本曾经搞定了,当初就是心愿在咱们实现博客更新后,脚本能够主动执行
这里咱们间接应用 GitHub Action 的定时工作即可
我的项目里增加文件 .github/workflows/ci.yml
name: Build READMEon: workflow_dispatch: schedule: - cron: "30 0 * * *" # 每天 0:30 时运行,北京工夫须要 + 8jobs: build: runs-on: ubuntu-latest steps: - name: Check out repo # 获取代码分支 uses: actions/checkout@v2 - name: Set up Python # python 环境 uses: actions/setup-python@v2 with: python-version: 3.8 - uses: actions/cache@v2 # 依赖缓存 name: Configure pip caching with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} restore-keys: | ${{ runner.os }}-pip- - name: Install Python dependencies # 装置依赖 run: | python -m pip install -r requirements.txt - name: Update README # 执行脚本 run: |- python build_readme.py cat README.md - name: Commit and push if changed # Git 提交 run: |- git diff git config --global user.email "sss213018@163.com" git config --global user.name "JS-banana" git pull git add -A git commit -m "Updated README content" || exit 0 git push
功败垂成~
看下成果:
这样脚本每天都会跑一次,同步博客相干信息~
结语
之前只晓得RSS订阅,齐全不分明还有这么些的细节,这次也算梳理搞清楚了一些,也尝试本人玩了一下,还是挺不错的~
感觉多会一门语言还是很棒的啊,有时会给你齐全不一样的思路,或者就会有更加好的计划~
扶我起来,我还能学~笑~
参考
- 订阅根底:RSS、ATOM、FEED、聚合、供稿、合烧与订阅
- RSS,ATOM,FEED是什么有什么区别
- feedparser
- jasonkayzk