早期实现
豆瓣观影清单、书架的功能之前也做过,当时用过好几个方案
- 当时找的一个教程,不过不记得出处了,不过我写了一篇日志记录这个事情,里面记录了实现过程,原理其实很现在这个类似
- 另外一个是当时一个叫mufeng还是布克牧为的大佬搞了一个douban的数据站,可以缓存你豆瓣的观影数据,不过好像也停止服务了
这两个方案都或多或少的出现问题了,我后来懒也就一直没有修过,所以之前导航上一直没有书架和豆瓣的链接。
其他方案
但是在空着的这段时间我有时候也找过解决方案,有一次在木木木木木 大佬的博客里发现了一个hugo的实现方案,功能非常齐全,可以实现清单的分类筛选、时间筛选、评分筛选、排序等功能。
当时一下就心动了。
大佬博客也有一篇日志提到了这个功能是谁写的,并且附上了链接。
来自于 @怡红公子 的自制轮子:doumark-action ,豆瓣书影音同步 GitHub Action。
我当时尝试着弄了一下,虽然成功通过doumark-action 缓存了我的豆瓣数据,但是后续的页面渲染把我卡住了,hugo的模板渲染用到了一些hugo特有的函数,我当时也看不太懂,所以就暂时搁置了。
后来有些时候想起了会忽然研究一下怎么处理,但是一直没落实代码实现上面。
不过今天终于下定决心要把这个功能给实现出来。
仔细研究了hugo的渲染代码,我发现其实前端的渲染完全可以用我目前渲染Memos的方式实现,只需要把数据处理成和hugo用到的格式就行了。
后来我又研究了一下doumark-action,发现可以把数据缓存成JSON,而且因为GitHub又raw格式的链接,可以提供外链。所以我就灵机一动:我可不可前端请求JSON数据,然后把JSON转换成hugo渲染用到的那种格式?
经过测试后发现确实可以实现数据转换,所以就有了今天这个方案。
var temp = { movies : [] }
$.getJSON('https://jsd.cdn.zzko.cn/gh/rebron1900/doumark-action@master/data/douban/movie.json',function(r){
$(r).each(function(){
temp.movies.push({id : this.id,
title : this.subject.title,
subtitle : this.subject.card_subtitle,
poster: this.subject.pic.large,
pubdate: this.subject.pubdate[0],
url: this.subject.url,
rating: this.subject.rating.value,
genres: this.subject.genres.join(','),
star: this.subject.rating.star,
comment: this.comment,
tags: this.tags.join(','),
star_time: this.create_time
})
})
})
实现开始
缓存豆瓣数据
这里我就不写了,引用@怡红公子 大佬的教程,唯一的区别是我更改了 format
为 json
。
使用其实很简单,在你的博客仓库中新建 .github/workflows/douban.yml
文件,以观影为例添加如下内容。它实现了每小时自动抓取你的豆瓣观影记录并更新到文件中,如果发现文件有更新则触发 commit 提交。
name: douban
on:
schedule:
- cron: "30 * * * *"
jobs:
douban:
name: Douban mark data sync
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: movie
uses: lizheming/doumark-action@master
with:
id: lizheming
type: movie
format: json
dir: ./douban
- name: Commit
uses: EndBug/add-and-commit@v8
with:
message: 'chore: update douban data'
add: './douban'
该 workflow 总共分为三步,
- 第一步初始化 Git 仓库;
- 第二步调用 doumark-action 同步豆瓣账号
lizheming
的movie
类型数据到./douban
文件夹下,并保存为json
格式文件; - 最后一步则是当
./douban
文件夹下有更新则调用插件提交修改。
转化数据
完整代码在下面
- 在你的主题里添加一个新页面
page-movies.hbs
并添加页面常规代码 - 这里我添加了一个主题自定义判断,如果设置了json数据文件的地址才做数据转换
- 定义一个临时变量
temp
用于存放最终转换后的数据 - 通过JQuery
getJSON
方法请求json文件。 - 通过
each
方法遍历数据,并从JSON数据里拿去到想要的数据,按hugo那边的格式组成JSON
对象,并存在变量temp.movies
里。 - 因为取到的分类数据是
剧情,动画
这种带,
号分隔符的,而之后筛选需要用到单独标签名称,所以需要做下处理,我这里重新遍历了movies
对象,如果有多个标签的则用split
做分割,并且通过indexOf
避免重复,如果有了就不再重复添加。 - 另外这里也顺带处理了一下
year
字段,原因和分类一样,之后筛选要用到,所以要去重复,并且做了截取处理。 - 通过javascript-template来渲染数据
添加样式和模板代码
在 page-movies.hbs
中添加样式代码,这里的代码我都是直接复制hugo实现那边的,可以完美使用,不需要做任何改动。
渲染筛选器和电影信息
这里我是按着hugo的代码逻辑,用tmpl做了实现,都是输出数据而已,就不细说了。其中 year
部分做了一下空值判断。
<script type="text/x-tmpl" id="tmpl-movies">
{% for (var i=0; i<o.movies.length; i++) { %}
<div
class="sc-gKAaRy dfdORB hint--top hint--medium"
data-year="{%= typeof(o.movies[i].pubdate) == "undefined" ? "":o.movies[i].pubdate.substring(0,4) %}"
data-star="{%= o.movies[i].star %}"
data-rating="{%= o.movies[i].rating %}"
data-genres="{%= o.movies[i].genres %}"
aria-label="{%= o.movies[i].comment %}"
>
<a rel="link" href="{%= o.movies[i].url %}" target="_blank">
<div class="sc-hKFxyN HPRth">
<div class="lazyload-wrapper ">
<img class="avatar" src="{%= o.movies[i].poster %}" referrer-policy="no-referrer" loading="lazy" alt="{%= o.movies[i].title %}" width="150" height="220">
</div>
</div>
<div class="sc-iCoGMd kMthTr">{%= o.movies[i].title %}</div>
<div class="sc-fujyAs eysHZq">
<span class="sc-jSFjdj jcTaHb">
{% for (var b=0; b<5; b++) { %}
<svg viewBox="0 0 24 24" width="24" height="24" class="sc-dlnjwi {% if (b < o.movies[i].star) { %} lhtmRw {% }else{ %} gaztka {% } %} ">
<path fill="none" d="M0 0h24v24H0z"></path>
<path fill="currentColor" d="M12 18.26l-7.053 3.948 1.575-7.928L.587 8.792l8.027-.952L12 .5l3.386 7.34 8.027.952-5.935 5.488 1.575 7.928z"></path>
</svg>
{% } %}
</span>
<span class="sc-pNWdM iibjPt">{%= o.movies[i].rating %}</span>
</div>
</a>
</div>
{% } %}
</script>
<script type="text/x-tmpl" id="tmpl-genres">
<a href="javascript:void 0;" class="sc-gtsrHT kEoOHR" data-search="genres" data-method="contain" data-value="">全部</a>
{% for (var i=0; i<o.length; i++) { %}
<a href="javascript:void 0;" class="sc-gtsrHT dvtjjf" data-search="genres" data-method="contain" data-value="{%= o[i] %}">{%= o[i] %}</a>
{% } %}
</script>
<script type="text/x-tmpl" id="tmpl-fyear">
<a href="javascript:void 0;" class="sc-gtsrHT kEoOHR" data-search="year" data-method="equal" data-value="">全部</a>
{% for (var i=0; i<o.length; i++) { %}
<a href="javascript:void 0;" class="sc-gtsrHT dvtjjf" data-search="year" data-method="equal" data-value="{%= o[i] %}">{%= o[i] %}</a>
{% } %}
</script>
完整代码请查看Github,或者查看 page-movies.hbs
https://github.com/rebron1900/attila/blob/master/page-movies.hbs