Quote Reader

By on

这大概是很久之前的一个想法了……可以追溯到 2020 年吧,当时看到一些爽哥语录(不),就想着能不能做一个语录提取器出来。

QQ 本体 (macOS/Windows) 确实存在表情快捷键这个说法,但 OCR 识别率不甚理想的同时也将手机端排除在外、也比较难实现语录的聚合;本项目预定实现多平台和便于聚合语录的特性。

规划

我们现在所拥有的是一些语录图片,存放于文件夹中;前期需要做的准备工作是利用 Python 脚本生成 json 文件、将每个图片中的语录全文、关键字提取出来,对应到路径。

后期需要做的工作是利用 Vue.js 编写前端实现语录图片的筛选与复制。

本项目不使用任何数据库。

前期工作

首先是找到一个合格的 OCR 库。考虑到现实情况,显然不太可能自己去训练模型;本项目中使用的是 PaddleOCR,模型体积较小、输出结果较理想。

本文将不会详细介绍脚本具体工作原理与相关事项,具体请参阅项目Quote_ocr

基本框架

getJson.py是脚本入口,利用 PaddleOcr 批量识别/imgs/图片中的文字并且输出到 json 中。

getQuote.py是读取 Json 的脚本,可以利用该脚本实现初步的语录筛选、构建词云。

使用前请先利用 requirement.txt 安装相关的依赖,具体使用步骤与相关脚本下载、存在问题等请参阅 Quote_ocr

输出文件

输出的是一个 json 文件,其中对象有以下几个属性:

  • id

    用于生成每一个图片特有的 id,不一定与图片名称相关。

  • info

    语录全文

  • keyword

    语录关键字

  • path

    语录图片的路径

准备好输出文件与对应语录即可开始构建前端界面。

后期工作

笔者考虑到服务器租赁费用,不排除使用 Electron 构建本地应用的可能、同时打算使用 Vue3;因此使用了 Vite 一把梭,工程化处理本项目。

初稿绘制

采用了 figma 作前端界面的大致绘制。项目链接

整体上由三个部分组成:

  • 顶栏

    为后期开发多页面而保留的导航栏。

  • 描述性图文

    Logo 与标题、应用的具体描述。

  • 主表格

    用于存放语录相关条目与搜索栏。

所有的内容均纵向排布,字体与相关配色方案将采用固定的组件库。

组件库选用

本项目使用Element Plus作为本项目的组件库。

克隆了element-plus-vite-starter仓库,在此基础上作进一步开发。

界面开发

根据前一阶段初稿绘制的成果,抽象出四种元素:菜单、按钮、段落图文、表格。

按照官方文档将相关元素依序写入即可。

布局

根据初稿绘制结果,给出详细布局。

结构

总体界面由

  • BaseHeader.vue
  • QuoteReader.vue
  • BaseBottom.vue

三个文件组成,分别对应布局图中的顶栏、主容器、脚注。

文件内容如下:

BaseHeader

顶栏。利用的是 el-menu 组件,修改为深色配色方案以符合初稿。

QuoteReader

主容器。分为两个部分,图文段落与主表格、分别装入不同的 div 中。对于主表格,采用的是 el-table 组件;引入了搜索框与查看按钮的相关例程以实现对应功能。

BaseBottom

脚注,单独一个 div 装入文本。

业务逻辑

主要由两部分组成:表格数据填充与图片预览。

表格数据填充

首先明确:本项目中的表格数据填充,是通过双向绑定来进行的。

具体而言,监控搜索框内数据是否变动(用户是否输入了搜索关键词);若是,则过滤掉无关内容、将数据实时更新到表格内。

若用户什么也不输入(或初始状态),则不过滤、将所有数据装入到表格内。

因此需要编写接口让 Computed 调用:

const tableData = quoteJson;  //上文提到的 json
interface Quote {
  id: number;
  info: string;
  keyWord: string[];
  path: string;
}
const filterTableData = computed(() =>
  tableData.filter(
    (data) => !search.value || data.keyWord.includes(search.value)
  )
);

HTML 中需要标注数据源:

<el-table :data="filterTableData" max-height="450">

图片预览

这是本项目的核心功能,应用到的组件是v-viewer

首先需要传入对应条目的数据。注意到相关 HTML 代码中有:

<template #default="scope">
    <el-button size="small" @click="show(scope.row)"
        >查看
    </el-button>
</template>

将表格中特定行的数据(也就是上文提到的接口)传入到 show 函数当中。

接着,利用 Quote 中的 path 属性即可拿到对应条目的路径。将其传递到 api 当中,使用对应方法即可预览。

  methods: {
    show(row: Quote) {
      this.$viewerApi({
        images: [row.path],
      });
    },
  },

打包分发

一般情况下利用yarn build命令即可打包完毕。

要利用 Electron 产生本地应用且实时调试,需要繁琐配置;本文暂不包括相关内容。

验证成果

使用yarn dev --host命令即可在局域网内调试。

(考虑到隐私问题图片暂不放出)

目前的问题有:

  • Logo 不能适应多端设备,有些情形下过于模糊

暂时不能解决,唯一的办法是重新设计 logo。

  • Electron 打包文件过大

暂时不能解决,似乎是通病。