用Bash和Automator实现mac自动更换在线壁纸

Windows Store上有一款叫做老司機鎖屏的应用,可以自动从yande.re下载最新图片并设置为桌面或锁屏壁纸。除了默认的yande.re开车路线外,也支持用自定义地址与XPath创建其他路线。可惜,这个有趣的应用在macOS上并没有类似的替代品。不过通过编写Automator(自动操作)中运行的bash脚本完全可以实现和这个应用相同的功能。

设定行车路线

本文以老司機鎖屏内置的默认yande.re路线为例进行编写,当然用同样的道理也可以做“必应每日壁纸”等类似的应用,在这里推荐一个Chrome插件XPath Helper,可以很方便的查看网页元素的XPath。

安装依赖的命令行工具

mac的命令行内置了几乎全部需要使用的工具,只需要多安装wget,具体方法就不多说了。

开车开车

设置环境变量

Automator中的bash环境并不包含~/.bashrc,所以如果wget安装在/usr/local/bin之类的位置就会报命令不存在的错误。因此脚本的第一步就是得设置环境变量:

1
PATH=$PATH:/usr/local/bin

设置程序参数

1
2
3
4
5
6
export http_proxy=http://127.0.0.1:1087
export https_proxy=http://127.0.0.1:1087
download_path="$HOME/wallpaper_dir"
image_limit=10
mkdir -p $download_path
search_query="rating:s score:>5 -bikini -bra -pantyhose -bikini_armor"

头两行属于科学上网(原因众所周知),不过一般来说不加问题也不大,只会略微增大翻车频率。第3行指定了壁纸保存的位置,第4行设置了保留壁纸数量的上限。search_query这个参数为图片的搜索条件,具体可以参考yande.re上的说明

等待系统加载

Finder在系统刚启动的时候无法接受osascript的指令,会导致设置壁纸失败。同时科学上网工具也需要时间启动,所以这里需要加一个延迟,具体时长可以根据实际情况修改。

1
sleep 15

下载搜索页面

1
2
encoded_query=`python -c "import sys, urllib as ul; print ul.quote_plus(sys.argv[1])" "$search_query"`
list_html=`curl https://yande.re/post\?tags\=$encoded_query\&commit\=Search 2>/dev/null`

首先借助python标准库中的工具将搜索条件进行URL编码,然后使用curl获取搜索结果页面并保存在变量中。

XPath解析出图片页面

1
pids=(`echo $list_html|xmllint --html --xpath "//ul[@id='post-list-posts']/li[count(a/span[2][substring-before(text() , 'x') >= substring-after(text() , 'x')]) > 0]//a[@class='thumb']/@href" - 2>/dev/null`)

借助xmllint,可以很容易使用XPath解析HTML字符串。这里的XPath来自老司機鎖屏应用。最后结果以数组形式保存在pids中。

随机选择图片

这个操作只是为了和老司機鎖屏应用保持相同的逻辑,不过也可以实现每次登录都更换壁纸的效果(当然也得看人品)。最后选出来的图片ID保存在pid中。

1
2
3
pid_count="${#pids[@]}"
rand_idx="$(( ( RANDOM % pid_count ) + 1 ))"
pid=`echo ${pids[rand_idx]}|awk 'BEGIN { FS = "show\/" } ; { print $2 }'|awk 'BEGIN { FS = "\"" } ; { print $1 }'`

下载图片详情页面并解析出图片地址

1
2
purl="https://yande.re/post/show/$pid"
picurl=`curl $purl 2>/dev/null|grep '"original-file-changed"'|awk 'BEGIN { FS = "href=\"" } ; { print $2 }'|awk 'BEGIN { FS = "\">" } ; { print $1 }'`

杀鸡焉用牛刀?由于我们需要的图片链接只有一个,这里提取地址就没必要使用XPath了,所以使用更简单的grepawk

下载图片

1
2
3
ext=`echo $picurl|awk 'BEGIN { FS = "." } ; { print $NF }'`
picpath="$download_path/$pid.$ext"
wget $picurl -O $picpath 2>/dev/null

设置壁纸

1
osascript -e "tell application \"Finder\" to set desktop picture to POSIX file \"$picpath\""

这里就属于mac特色了。当然经过修改也能在Linux上实现相同的功能。

行车记录仪

开车怎能不带行车记录仪?为了追踪历史使用的图片,这里将图片地址及时间戳写入文件中:

1
2
3
4
5
6
7
ret=$?
if [ $ret -eq 0 ]
then
echo "$(date '+%Y-%m-%d %H:%M:%S'): $purl" >> $download_path/wallpaper.log
else
echo "$(date '+%Y-%m-%d %H:%M:%S'): $purl Failed $ret" >> $download_path/wallpaper.log
fi

完整代码

接下来是完整的代码,可以直接在Automator中封装成app并添加启动项。具体操作教程一大把,这里就不赘述了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/bin/bash
PATH=$PATH:/usr/local/bin
# Parameters
export http_proxy=http://127.0.0.1:1087
export https_proxy=http://127.0.0.1:1087
download_path="$HOME/wallpaper_dir"
image_limit=10
mkdir -p $download_path
## Query, reference: https://yande.re/help/cheatsheet
search_query="rating:s score:>5 -bikini -bra -pantyhose -bikini_armor"

# Wait for system loading
sleep 15

# Search for images
encoded_query=`python -c "import sys, urllib as ul; print ul.quote_plus(sys.argv[1])" "$search_query"`
list_html=`curl https://yande.re/post\?tags\=$encoded_query\&commit\=Search 2>/dev/null`

# Get URLs via XPath
pids=(`echo $list_html|xmllint --html --xpath "//ul[@id='post-list-posts']/li[count(a/span[2][substring-before(text() , 'x') >= substring-after(text() , 'x')]) > 0]//a[@class='thumb']/@href" - 2>/dev/null`)

# Randomly select an image
pid_count="${#pids[@]}"
rand_idx="$(( ( RANDOM % pid_count ) + 1 ))"
pid=`echo ${pids[rand_idx]}|awk 'BEGIN { FS = "show\/" } ; { print $2 }'|awk 'BEGIN { FS = "\"" } ; { print $1 }'`

# Download image detail page
purl="https://yande.re/post/show/$pid"
picurl=`curl $purl 2>/dev/null|grep '"original-file-changed"'|awk 'BEGIN { FS = "href=\"" } ; { print $2 }'|awk 'BEGIN { FS = "\">" } ; { print $1 }'`

# Download image
ext=`echo $picurl|awk 'BEGIN { FS = "." } ; { print $NF }'`
picpath="$download_path/$pid.$ext"
wget $picurl -O $picpath 2>/dev/null

# Set wallpaper
osascript -e "tell application \"Finder\" to set desktop picture to POSIX file \"$picpath\""

# Remove old wallpapers
ls -1t $download_path/*.jpg | tail -n +$(($image_limit + 1)) | xargs rm

# Log
ret=$?
if [ $ret -eq 0 ]
then
echo "$(date '+%Y-%m-%d %H:%M:%S'): $purl" >> $download_path/wallpaper.log
else
echo "$(date '+%Y-%m-%d %H:%M:%S'): $purl Failed $ret" >> $download_path/wallpaper.log
fi

文章目录
  1. 1. 设定行车路线
  2. 2. 安装依赖的命令行工具
  3. 3. 开车开车
    1. 3.1. 设置环境变量
    2. 3.2. 设置程序参数
    3. 3.3. 等待系统加载
    4. 3.4. 下载搜索页面
    5. 3.5. XPath解析出图片页面
    6. 3.6. 随机选择图片
    7. 3.7. 下载图片详情页面并解析出图片地址
    8. 3.8. 下载图片
    9. 3.9. 设置壁纸
    10. 3.10. 行车记录仪
  4. 4. 完整代码
|