使用Zotero软件可以非常方便的将一个文件夹中的数据转换成bib后缀的文件。而如果我们想要在jekyll中发布我们的论文列表,则需要转换成jekyll支持的比如yaml、json格式的数据。因此,我使用python脚本写了一个转换的脚本,暂且将转换过程设计的主要代码说明如下:

安装python包

首先我们需要安装bibtexparser包,该包可以非常方便的加载bib文件,使用pandas将数据转换成Dataframe,就可以进行下一步处理了。

with open("./papers.bib", encoding='utf-8') as bibtex_file:
    bib_database = bibtexparser.load(bibtex_file)

df = pd.DataFrame(bib_database.entries)

格式化数据

  • 生成子集

由于bib文件包含了一些冗余的信息,如果不是很想要,可以Copy一个Dataframe出来,然后选择目标字段。

# 由于df_sel后续需要执行赋值,因此必须是df的copy版本
df_sel = df.loc[:, ['author', 'title', 'booktitle', 'journaltitle', 'date', 'volume', 'number', 'pages', 'doi']].copy()

# 将null值复制为空字符串
df_sel.fillna('', inplace=True)

需要注意的是,必须使用loc索引以及copy函数,否则后面df_sel进行再次处理的时候会产生SettingwithCopy错误。

  • 格式化列数据
for k, v in df_sel.items():
    if k == 'date':
        df_sel[k] = df_sel[k].apply(lambda p: p.split('-')[0])
    if k == 'author':
        df_sel[k] = df_sel[k].apply(lambda p: re.sub(r'(Xing, [a-zA-Z-]+)', r"<u>\1</u>", p))
    if k == 'pages':
        df_sel[k] = df_sel[k].apply(lambda p: re.sub(r'[-]+', '-', p))
    if k == 'title' or k == 'booktitle':
        df_sel[k] = df_sel[k].apply(lambda p: re.sub(r'(\{|\}|\\)', '', p))
    if k == 'journaltitle':
        df_sel[k] = df_sel[k].apply(lambda p: re.sub(r'\\', '', p))

apply类似map函数,可以方便的将列数据当做数组进行处理。其中author列的操作主要是将当前作者的名字下划线处理。

  • 分组以及转换成json数据
js = df_sel.groupby('date').apply(lambda x: json.loads(x.to_json(orient='records'))).sort_index(ascending=False)

groupby之后,如果不apply,则每个date对应的是一个字数穿列表,使用apply之后就是一个json列表。

  • 保存数据
js.to_json('./papers.json', indent=4, force_ascii=False)

至此,一个按照年份分组的JSON格式的文献引用数据文件就生成了。

引用文件

将该文件放在jekyll网站目录的_data文件夹中,就可以使用json格式的数据了,这些数据可以在markdown、html文件中使用,只需要使用liquid代码即可。下面是一个示例的格式化代码。


<h4>{{kp[0]}}</h4>
{% for paper in kp[1] %}
    <li style="margin-bottom: 10px;line-height: 1.5em;">
    {{paper.author}}, 
    {% if paper.doi =="" %}
        <i>{{paper.title}}</i>
    {% else %}
        <a href="https://doi.org/{{ paper.doi }}" target="_blank"><i>{{paper.title}}</i></a>
    {% endif %}. 
    {{paper.journaltitle}}
    {{paper.booktitle}}, 
    {{paper.date||date: "%Y"}}. 
    <b>{{paper.volume}}</b>
    {% if paper.number != "" %}
        ({{paper.number}})
    {% endif %}: p{{paper.pages}}
    </li>
{% endfor %}
{% endfor %}

如果展示Liquid模板内容,参考:https://www.jasongaylord.com/blog/2020/05/31/displaying-liquid-templates-in-jekyll-code-blocks