Pi Store
更多

Alfred Workflow 进阶指南:以少数派标签搜索为例

2023 年 11 月 07 日

前言Alfred是受Mac用户广泛喜爱的经典自动化工具,其付费功能Workflow更是提高效率的利器。不过,很多朋友或许主要都以下载别人的成品为主,一旦遇到没有现成方案、或者方案过时的情况,就只能遗憾 ...


前言

Alfred 是受 Mac 用户广泛喜爱的经典自动化工具,其付费功能 Workflow 更是提高效率的利器。不过,很多朋友或许主要都以下载别人的成品为主,一旦遇到没有现成方案、或者方案过时的情况,就只能遗憾放弃。

本文中,我希望以本站读者可能感兴趣的一个常见需求——搜索少数派特定标签下的最新文章为例,从头到尾演示如何自己制作一个 Alfred Workflow,旨在抛砖引玉,希望能让更多朋友掌握 Alfred Workflow,创造出有趣、实用、流畅的工作流。

成品效果演示

输入 ssp 的关键词激活 SSPAI Search Workflow,后面跟着需要搜索的关键词,回车即可打开对应的文章页面。

成品下载和代码

sspai-search-alfredworkflow

原型搭建

获取少数派标签列表接口

打开少数派主页和 Chrome 的网络调试工具,切换到网络子菜单,并将过滤的文件请求类型设置为「Fetch/XHR」,然后刷新一个效率标签页面,就会有请求记录被捕获到了。我通过经验一眼就看出肯定是 limit=10&&offset=0 这条请求获取的文章数据,点击预览查看,正是需要的文章列表数据。

(如果不是使用 MVC 模型来构建,而是直接将所有的数据先在后端渲染,然后返回整个网页文件的话,就需要读者自己去解析这个网页的内容了。对于这种情况,在以往的文章里也曾举例介绍过,请见《通用状态监控通知脚本,订阅状态通知》。)

如果是刚入门的新手,还有两种办法来确定哪一条请求是返回了需要的数据。

第一是可以逐条查看返回的数据来确定,此处刷新网页之后只有九条请求,逐一查看也不会太费时间。

第二种方法是在请求页面,使用快捷键 ⌘+F 呼出关键词搜索框,然后页面上显示的任意一篇文章标题,大概率也能找到具体的数据来源。还有一篇之前的文章可供参考《Charles 抓包实战指南——以获取新浪彩票 API 并制作捷径为例》。

理解链接中的参数

在上一步获取了正确的文章列表接口地址之后,接着就可以开始研究一下这个接口参数了,先把链接拆开:

https://sspai.com/api/v1/article/tag/page/get?
limit=12
&offset=0
&tag=效率

可以看到这个接口一共有四个参数,经验告诉我limitoffset 是分页参数,规定了每次读取多少条数据,从哪个位置开始读取。最后的 tag 就是要查询的标签了。

很多人可能认为只需要把 limit 参数调大,就能实现一次查询更多的数据。实际上这个 limit 数字并不是无限大的,多数网站都会给这个参数设置一个最大值,超过这个最大值之后,就不会按照用户输入的 limit 去返回了,而是用网站定义的最大值。否则别人一个请求就把用户的所有文章信息都爬走了。所以这个这一步就是测试最大的 limit 值。

此处使用 curl 命令向 API 接口发送查询请求,然后使用 jq 工具解析返回的文章列表数组长度,命令如下:

curl 'https://sspai.com/api/v1/article/tag/page/get?limit=10&offset=0&tag=效率'|jq '.data|length'

经过测试,可以看出,在 limit=40 的时候,返回的文章列表数组长度就不会再变动了,接下来无论把 limit 改为多大,单次都只返回 40 条数据了。

接着就是理解 offset 参数的用法,一般译为偏移量,上面发的请求偏移量都是 0,说明这是从最新发表的文章向前查询 40 条记录。如果设置 value=40,它就会跳过最新的 40 篇文章,从第 41 篇文章开始再查询 40 篇数据返回。

如下图所示,左边的 offset 是 0,右边是 40,所以两个请求返回了不同的文章列表。这个参数接下来的 Python 代码里也会使用到,此处只要知道它的功能即可。

curl 'https://sspai.com/api/v1/article/tag/page/get?limit=40&offset=0&tag=效率'|jq '.data[]|.title'
curl 'https://sspai.com/api/v1/article/tag/page/get?limit=40&offset=40&tag=效率'|jq '.data[]|.title'

通过这一段对接口的分析,我们已经能理解少数派标签列表接口的地址和相关参数,接下来就可以正式开始准备制作 Workflow了。

(如果想实现首页或是用户检索,方法基本相同,有兴趣的读者可以自己练习。)

搭建基本框架

接着打开 Alfred 切换到 Workflows 界面,点击左下角的「+」,创建一个「Blank Workflow」。

在弹出的页面里填写 Workflow 的基本信息,其中 Bundle Id 的格式可以参考:「com.作者名.项目名」这样的 reverse DNS 结构,Workflow 的图标是少数派 App 的图标,此处可以参考这篇文章来获取合适的图标。

接着我们在 Workflow 编辑页面右键,添加一个 Script Filter 的 Input 输入来源。这里我们会选择 Python,这是一种相对流行编程语言,即使没有任何的学习,普通读者也能借助 GPT 对代码进行解释和调整。

添加了 Script Filter 之后,在弹出的窗口中填写这个脚本的基本配置信息。将 Script 中的代码修改为:python3 sspai.py "$1"

意思是,当使用关键词 ssp 触发了这个 Workflow 之后,使用 Python 3 去执行 sspai.py 脚本,并把用户的输入作为 argv 参数传入。(我们会在之后的章节会详细解释。)

保存好之后,直接使用关键词去触发这个 Workflow,就可以看到基本的界面效果了。此时还没编写 sspai.py 的逻辑代码,所以不会有其他的待选列表可供选择,但是也能看出在上图中设置的 keyword、Placeholder Title 和 Placeholder Subtext 生效了。

Python 环境准备

基本框架搭建好了之后,就可以开始编写 Python 代码了。

那么在哪里编写呢?再次点开 Script Filter,在左下角有一个文件夹的图标,点开就是这个 Workflow 的根目录了。接下来所有的代码、依赖库都会被安装在这里。

打开这个目录之后,可以看到这个目录下只有 icon.png 和 info.plist。icon.png 是图标文件,info.plist 是记录这个 Workflow 基本信息的格式化文件,刚才在「基本框架搭建」章节填写的信息,都记录在这个文件里了。

接下来就是要在这个目录下创建一个供 Workflow 执行的 sspai.py。可以直接将该工作目录拖入代码编辑器中,例如 Sublime Text 或者 VS Code 中,然后在左边文件列表中使用右键创建一个 sspai.py 文件即可。

Python 文件准备好了,就可以直接开始写代码了。使用 requests 向少数派文章接口发一个请求,然后再把返回的数据都打印出来。

但是此处可以看到,VS Code 在第一行的 import requests 位置显示了红色的波浪线,说明此处的导入是有问题的。此处就是 Alfred Workflow 的特殊之处了,Alfred Workflow 只认工作目录下的 Python 依赖,不会去其他地方查找。

为什么要这样设计?因为 Alfred Workflow 是可以导出分享给其他用户的,但是其他用户不可能所有人都预装了相关依赖,所以 Alfred 就有了这样的设计,所有的依赖都必须放在工作目录下,打包分享的时候会跟着分享文件一起带走。

所以我们要借助 pip 命令的 --target 的参数指定安装目录,把 Python 的依赖库安装到 Workflow 工作目录下。VS Code 中,选择「终端」子菜单,点击「新建终端」,输入命令在工作目录下安装 requests 依赖,命令如下:

pip3 install -U --target=. requests

安装前后工作目录对比如下,除了 requests 之外,还多了很多其他的依赖,因为 requests 需要配合这些其他的依赖,才能够正常工作,所以请不要随意删除这些文件夹。

测试 Workflow

重启 VS Code,此时就可以看到 requests 导入正常了,没有红色的波浪线报错了。回看我们刚才写的请求接口的代码,现在可以对它进行测试了。我在这里最后使用了 sys.stderr.write(),这是因为 Alfred 是通过标准输出,将返回的结果提供给打开 URL 组件去打开链接的。

如果记录日志和返回结果都使用 print() 去返回数据,Alfred 就无法区分哪个是日志信息,哪个是返回数据。所以为了区分两者,日志记录使用 sys.stderr.write(),返回数据使用 sys.stdout.write()

Alfred 给开发者提供了一个控制台的功能,可以通过控制台查看输出信息。打开「少数派搜索」Workflow,在右上角有一个虫子的图标,开发者可以在这里查看 Workflow 输出的日志信息。点击之后,就会提示开始记录日志了。

此时通过 ssp 的关键词 + 搜索内容去触发这个 Workflow,就能够执行 Python 代码了。可以看到下面的控制台就已经成功输出了获取到的 JSON 数据。

调整数据结构

请求测试成功后,我们就要调整数据结构,让 Alfred 可以返回标准的数据并呈现出来。Alfred 定义了一个数据结构,只有根据它规定的格式去返回数据,才能让数据显示为可选项:

{
  "items": [
    {
      "uid": "desktop",
      "type": "file",
      "title": "Desktop",
      "subtitle": "~/Desktop",
      "arg": "~/Desktop",
      "autocomplete": "Desktop",
      "icon": {
        "type": "fileicon",
        "path": "~/Desktop"
      }
    }
  ]
}

但是在这个例子中,我们只需要:

{
  "items": [
    {
      "title": "标题",
      "subtitle": "子标题",
      "arg": "打开的链接",
      "autocomplete": "自动补全",
      "icon": {
        "path": "图标地址"
      }
    }
  ]
}

代码整合

现在有了 requests 请求拿到的数据,结合上面的返回数据结构,就可以写出一个简单版的查询了。

不过光有标题还不够,我们还需要大概知道文章讲了什么,以及对应 ID 来帮助跳转。这里我们要对文章列表里的每个标题,使用 for 循环来读取文章数据。

curl 'https://sspai.com/api/v1/article/tag/page/get?limit=1&offset=6&tag=效率'|jq

整合之后的代码如下所示,使用 requests 向 API 接口发送请求,然后使用 for 循环读取 response['data'] 里面的每个元素,将它们转为 Alfred 可解析的 JSON 格式。然后使用 json.dumps() 函数,将它转为文本,最后使用 sys.stdout.write() 标准输出返回给 Workflow。

会员专属文章,欢迎加入少数派会员。
优质内容
权益周边
会员社群
power+
评论区
精彩评论0
成为少数派会员方可评论,立即加入 。若已是少数派会员,点击登录
还没有评论,来发表第一个评论吧
精彩评论
还没有评论,来发表第一个评论吧
成为少数派会员方可评论,立即加入 。若已是少数派会员,点击登录
会员新功能
内容侧边栏
点击这里拉开侧边栏,即可查看会员内容列表,快速切换内容。