目录

  • 前言
  • 计划路线
  • 优劣对比
  • 代码
  • python实现自动签到功能
  • shell脚本文件
  • 方案一:selenium+launchctl
  • 方案二:selenium+sleepwatcher


前言

做这个小功能的起因是因为最近家里换了新电视,为了能获得最好的观影体验,需要下载许多动辄几十G的4k电影,而让我花钱冲会员或者买蓝光盘自然是不可能的,我就找到了免费的资源网站,需要签到用积分购买电影资源(当然也可以充钱)

ios自动签到快捷指令 苹果自动化签到_chrome


可是每天手动签到很麻烦,又可能经常忘,就想自己搞一个脚本自动化签到

计划路线

我最初的方案是,使用python的selenium库来实现网站模拟点击的操作,使用launchctl定时运行shell脚本执行py文件。但是由于我电脑launchctl功能的未知错误(查遍了google百度也没能找到解决方法)我最终实现的途径是通过sleepwatcher来实现电脑唤醒时自动执行。

优劣对比

方案一
编写plist文件来实现定时任务是当下mac官方最推荐的方法。灵活性也很高,可以任意定时,精确到秒,灵活至单独工作日。相比Linux的crontab有一个优点:当电脑在规定时间在休眠状态的话,在唤醒后依然可以补执行任务,而crontab只会等待下一轮指定运行时间。但是launchctl权限问题可能会导致很多错误,这点使用上可能会有些困扰。
方案二
sleepwatcher可以说使用起来十分简单,但是只能在唤醒时或者休眠时执行任务,使用场景较单一,需要在脚本文件中写额外的代码来避免反复执行任务

下面,我会将两种实现途径都介绍一下

代码

python实现自动签到功能

在项目目录里创建code.py

所需导入

from selenium import webdriver
import time
from selenium.webdriver.chrome.options import Options

要使用chrome浏览器,所以需要下载电脑中对应版本的chrome驱动chromedriver文件,版本号可以在chrome的关于中看到。比如我的是87.0.4280.88,在此网址可以下载对应的驱动,下载后将其放在code.py同一路径。

ios自动签到快捷指令 苹果自动化签到_selenium_02


设置浏览器的选项设置,第一行这个很关键,如果不取消掉会在执行的时候蹦出来通知权限的通知框,会使后续的操作失败,值得注意的一点是headless这个选项在调试阶段最好注释掉,为了方便测试需要看整个自动化的执行流程,当程序没有问题后将整个签到动作隐藏在后台将会十分的优雅,没有任何痕迹得完成签到。

option = Options()

    option.add_argument("--disable-infobars") # 取消通知提醒
    # option.add_argument("start-maximized")
    option.add_argument("--disable-extensions") # 取消扩展
    option.add_argument('headless')  # 后台运行
    # Pass the argument 1 to allow and 2 to block
    option.add_experimental_option("prefs", {
        "profile.default_content_setting_values.notifications": 2
    })

设置提前注册好的账号密码,可以实现多组账号密码依次签到

username = ['xxx@126.com', 'xxxx@126.com']
password = ['xxxx', 'xxxxxx']

这里的find_element_by_xpath是为了指定页面元素并进行填充,点击等操作。
xpath的获得是在chrome里先打开网页,然后F12进入检查,再在想定位的元素上右键检查,选择full xpath,就可以获得对应元素的xpath
获得指定网址的实例化对象,并完成点击等操作。

chrome_driver = '/Users/yao/Documents/PersonalProjects/AutoCheckin/chromedriver'  #chromedriver的文件位置
    browser = webdriver.Chrome(options=option, executable_path=chrome_driver)
    browser.get('https://www.hao4k.cn/qiandao/')

    browser.find_element_by_xpath('//*[@id="JD_sign"]').click()

    time.sleep(1)
    # 输入账号密码 点击登录

    browser.find_element_by_xpath('/html/body/div[10]/div/div/div[2]/div[2]/div[6]/div[1]/div/form/div/div[1]/table/tbody/tr/td/input').send_keys(username)
    browser.find_element_by_xpath('/html/body/div[10]/div/div/div[2]/div[2]/div[6]/div[1]/div/form/div/div[2]/table/tbody/tr/td/input').send_keys(password)
    browser.find_element_by_xpath('/html/body/div[10]/div/div/div[2]/div[2]/div[6]/div[1]/div/form/div/div[5]/label/input').click()
    browser.find_element_by_xpath('/html/body/div[10]/div/div/div[2]/div[2]/div[6]/div[1]/div/form/div/div[6]/button').click()

    windows = browser.window_handles
    browser.switch_to.window(windows[-1])
    time.sleep(1)

如果已签到或者有任何错误导致签到失败就会打印FAILED,这步是为了后续输出log.txt中可以看到每次执行的记录

browser.get('https://www.hao4k.cn/qiandao/')

    try:
        browser.find_element_by_xpath('/html/body/div[9]/div[2]/div[1]/div[1]/a').click()
        time.sleep(1)
        browser.quit()
        print(username+' SUCCEED ', end='')
    except:
        time.sleep(1)
        browser.quit()
        print(username + ' FAILED ', end='')

将上述代码封装进autocheckin函数,调用

for u, p in zip(username,password):
    autocheckin(u,p)

shell脚本文件

在同一路径下,创建autocheckin.sh脚本文件

#!/bin/bash
cd /Users/yao/Documents/PersonalProjects/AutoCheckin
lastlog=$(tail -n -1 log.txt)
if ((${lastlog%% *}==$(date "+%Y-%m-%d"))) && ! [[ $lastlog =~ FAILED ]];then
exit 0
else
res=$(/Users/yao/opt/anaconda3/bin/python3 /Users/yao/Documents/PersonalProjects/AutoCheckin/code.py)
time=$(date "+%Y-%m-%d %H:%M:%S")
echo "$time $res" >> /Users/yao/Documents/PersonalProjects/AutoCheckin/log.txt
fi

log.txt中的数据是以这样的形式储存的:
2020-12-30 15:25:51 xxx@126.com SUCCEED xxxx@126.com SUCCEED

lastlog=$(tail -n -1 log.txt)读取log.txt中的最后一行数据, 如果记录中的最后一条数据日期是当天且没有FAILED记录就退出脚本程序,反之则执行后续签到程序
=~符号用于返回是否包含字符串布尔值

方案一:selenium+launchctl

在~/Library/LaunchAgents路径下新建plist文件com.yaoMacBook.autocheckin.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
	<key>Label</key>
	<string>com.yaoMacBook.autocheckin</string>
    	<key>ProgramArguments</key>
	<array>
	    <string>/Users/yao/Documents/PersonalProjects/AutoCheckin/autocheckin.sh</string>
	</array>
	<key>StartCalendarInterval</key>
  	<dict>
        	    <key>Minute</key>
        	    <integer>10</integer>
        	    <key>Hour</key>
        	    <integer>12</integer>
  	</dict>
	<key>RunAtLoad</key>  
    	<true/>
	<key>KeepAlive</key>
	<false/>
	<key>WorkingDirectory</key> 
    	<string>/Users/yao/Documents/PersonalProjects/AutoCheckin</string>
    </dict>
</plist>

Label是全局唯一的标志,是进程名
ProgramArgument是运行的程序和输入参数,如果只有一个就默认运行第一个参数程序
StartCalendarInterval表示在哪天几时几分运行,这里表示每天12点10分运行
RunAtLoad表示是否开启服务时自动运行,默认false
KeepAlive表示是否进程一直在后台运行,默认false
WorkingDirectory表示指定的工作路径

对于脚本文件也需要更改权限,可以执行 chmod +x autocheckin.sh增加所有用户的执行权限。

然后在~/Library/LaunchAgents路径下启动进程

launchctl load com.yaoMacBook.autocheckin.plist

使用unload停止进程

launchctl unload com.yaoMacBook.autocheckin.plist

start可以单次运行进程来查看是否正确运行

launchctl start com.yaoMacBook.autocheckin.plist

我在我的电脑(MacOS BigSur 11.1)上出现错误,系统日志显示错误代号126,如有朋友知道原因欢迎交流!

方案二:selenium+sleepwatcher

第一条路走不通后,我找了另一个方法曲线救国,使用sleepwatcher来实现每次电脑唤醒便执行脚本
具体实现方法参考了这篇文章的sleepwatcher配置部分,
\

  • 安装并设置自启动
> brew install sleepwatcher
> brew services start sleepwatcher
  • 查看进程是否启动,如果启动可以看到其中有两个内容。分别是 .sleep 和 .wakeup,分别对应睡眠和唤醒
> ps aux | grep sleepwatcher
  • 编写配置脚本 在 ~ 目录下创建文件 .sleep 和 .wakeup 并赋予权限 777,权限这块不了解的话可以自行查阅
> cd ~
> touch .sleep
> touch .wakeup
> sudo chmod 777 .sleep
> sudo chmod 777 .wakeup

然后编辑.wakeup

> vim .wakeup

i进入编辑模式插入脚本的完整路径

ios自动签到快捷指令 苹果自动化签到_python_03


:wq保存退出

然后就大功告成,可以合盖试一下脚本是否正确执行,log.txt中是否有正确的签到记录