Skip to content

使用日历app轻松订阅各大OJ平台上的比赛(ics格式)

Posted on:2023年2月18日 at 16:47

本文是一篇连载文章,系列“工具推荐”,同样系列的文章还有这些


cover

前言

有时候,我们想多打几场比赛,却苦于没有提前在每个平台上找而错过,明明关注了邮件,却因为邮件的提醒时间太短而来不及安排。

今天,这个问题彻底被解决了!

大家应该都知道windows的日历,里面的日程功能用的人不多,但是它真的非常好用。

我写了一个小程序,自动抓取更新每天的比赛并转化为订阅格式。

首先放上地址,如果想听原理可以往后看。

安装方法

outlook网页版

  1. 点击日历视图
  2. 点击添加日历 - 从web订阅
  3. 粘贴链接

outlook

  1. 点击日历视图
  2. 右键任意一个日历组(如我的日历)
  3. 点击添加日历 - 从internet
  4. 输入刚刚的地址
  5. 进行最后的配置,完成

windows 日历应用

我强烈推荐你使用outlook或它的网页版,因为这个日历的同步有些问题,我也在添加日历那里转了很久进不去。

IOS 日历

  1. 点击添加日历 - 添加订阅日历
  2. 粘贴链接
  3. 进行自定义设置,完成

其他日历软件

有两种方法,一是在outlook网页版直接用微软账户登录添加日历,然后在日历应用里添加这个账户。

或者这个应用直接支持订阅,就可以直接粘贴链接进去。

无论如何,我强烈推荐在所有地方使用一个日历账户,这样的话创建的日程可以同步。

原理

本质上来说,这个订阅链接背后就是一个文件,我只需要用现有的库和爬虫就可以处理。

比如说这是洛谷的获取脚本:

import requests
import re
from bs4 import BeautifulSoup
import datetime
import urllib
import json

headers = {
    'UserAgent''Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE'
}
def getcontest():
  res = requests.get('https://www.luogu.com.cn/contest/list'headers=headers)

  mat = re.findall(r'JSON\.parse\(decodeURIComponent\("(\S+)"\)',res.text)[0]
  mat = json.loads(urllib.request.unquote(mat))

  rt = []

  for t in mat['currentData']['contests']['result']:
    title = t['name']
    startTime = datetime.datetime.fromtimestamp(t['startTime'])
    endTime = datetime.datetime.fromtimestamp(t['endTime'])
    startTime = startTime + datetime.timedelta(hours=-8)
    endTime = endTime + datetime.timedelta(hours=-8)
    rt.append({
       "title":title,
       "start":startTime,
       "end":endTime
    })
  return rt

if __name__ == '__main__':
  for res in getcontest():
    # change UTC time to local time(UTC+8)
    res["start"= res["start"].replace(tzinfo=datetime.timezone(datetime.timedelta(hours=8)))
    res["end"= res["end"].replace(tzinfo=datetime.timezone(datetime.timedelta(hours=8)))
    print(res['title'],res['start'],res['end'])

然后最后需要一个主程序把这些脚本一起调用生成日历:

import luogu
import atcoder
import codeforces

import ics
import upload
import requests

class tmpfile:
  def __init__(self,data):
    self.data = data
  def read(self,a):
    print(a)
    return self.data

def main_func(a='a',b='b'):
  try:
    registered = [
      luogu.getcontest(),
      atcoder.getcontest(),
      codeforces.getcontest()
      ]

    calendar = ics.Calendar()

    for dat in registered:
      if dat!=None:
        for res in dat:
            print(res['title'],'|', res['start'],'|', res['end'])

            e = ics.Event()
            e.name = res['title']
            e.begin = res['start']
            e.end = res['end']
            calendar.events.add(e)

    upd = tmpfile(data=calendar.serialize())
    upload.upload(upd)
    # open('a.ics','w',encoding='utf-8').write(upd.read(0))

if __name__ == '__main__':
  main_func()

最后再把这些文件和依赖打包上传到腾讯云的scf云函数,设置定期执行就好了。

结尾

科技极大地方便了我们的生活,它的门槛也在逐步降低,相信未来的世界会因为科技变得更好!



在 Rickyxrc's blog 出现的文章,若无特殊注明,均采用 CC BY-NC-SA 4.0 协议共享,也就是转载时需要注明本文章的地址,并且引用本文章的文章也要使用相同的方式共享。