Compare commits

...
6 Commits
3 changed files with 40 additions and 67 deletions
+12 -4
View File
@@ -1,11 +1,15 @@
name: CET Monitor name: CET Monitor
on: on:
schedule: schedule:
- cron: "17 * * * *" - cron: '*/30 6-18 * * *'
workflow_dispatch: workflow_dispatch:
inputs:
force_push:
description: "强制推送当前公告"
required: false
default: "false"
jobs: jobs:
@@ -27,12 +31,16 @@ jobs:
- name: Run monitor - name: Run monitor
env: env:
PUSH_TOKEN: ${{ secrets.PUSH_TOKEN }} PUSH_TOKEN: ${{ secrets.PUSH_TOKEN }}
FORCE_PUSH: ${{ github.event.inputs.force_push }}
run: python main.py run: python main.py
- name: Commit state - name: Commit state UTC
run: | run: |
git config user.name "gitea-actions" git config user.name "gitea-actions"
git config user.email "actions@localhost" git config user.email "actions@localhost"
git add data/state.json git add data/state.json
git diff --cached --quiet || git commit -m "update cet state"
git diff --cached --quiet || git commit -m "update cet state $(date -u '+%Y-%m-%dT%H:%M:%SZ')"
git push git push
+1 -21
View File
@@ -3,123 +3,103 @@
{ {
"title": "中国教育考试网", "title": "中国教育考试网",
"url": "//www.neea.edu.cn/", "url": "//www.neea.edu.cn/",
"category": "📝 考试安排",
"hash": "cf41a21ad8b1fb90b1afa528fe0ca2b382be41176ba04bf796133f909e8ca201" "hash": "cf41a21ad8b1fb90b1afa528fe0ca2b382be41176ba04bf796133f909e8ca201"
}, },
{ {
"title": "考试动态", "title": "考试动态",
"url": "/html1/category/16093/1124-1.htm", "url": "/html1/category/16093/1124-1.htm",
"category": "📝 考试安排",
"hash": "be0e11646e3f9c624d5facda8c80f848ac1864a5c0e05c95da1d88ce71575cd4" "hash": "be0e11646e3f9c624d5facda8c80f848ac1864a5c0e05c95da1d88ce71575cd4"
}, },
{ {
"title": "CET委员会", "title": "CET委员会",
"url": "/html1/folder/19081/5123-1.htm", "url": "/html1/folder/19081/5123-1.htm",
"category": "📢 其他",
"hash": "e2fdf6b7ed34f4439e1ae488f34f406fbef851da0a69ceec918d357bc9ed73eb" "hash": "e2fdf6b7ed34f4439e1ae488f34f406fbef851da0a69ceec918d357bc9ed73eb"
}, },
{ {
"title": "考试大纲", "title": "考试大纲",
"url": "/html1/folder/16113/1588-1.htm", "url": "/html1/folder/16113/1588-1.htm",
"category": "📝 考试安排",
"hash": "8117ca68e3c80bab0270ed37d66f0d6cc0d5faa96bc78a894c6839a0e0ee006e" "hash": "8117ca68e3c80bab0270ed37d66f0d6cc0d5faa96bc78a894c6839a0e0ee006e"
}, },
{ {
"title": "2026年上半年全国大学英语四、六级考试报名工作启动", "title": "2026年上半年全国大学英语四、六级考试报名工作启动",
"url": "/html1/report/2603/2-1.htm", "url": "/html1/report/2603/2-1.htm",
"category": "📝 报名",
"hash": "29ec94196f15fa6268836c3717f68f9c6b1b30438f78ae6f50aeb172758b22be" "hash": "29ec94196f15fa6268836c3717f68f9c6b1b30438f78ae6f50aeb172758b22be"
}, },
{ {
"title": "2025年下半年全国大学英语四、六级考试(CET)成绩查询有关安排", "title": "2025年下半年全国大学英语四、六级考试(CET)成绩查询有关安排",
"url": "/html1/report/2602/55-1.htm", "url": "/html1/report/2602/55-1.htm",
"category": "📊 成绩",
"hash": "8d698177e736f98ff0fbec5f3cadd4281d37db2983fd4f273bb151870a31c9af" "hash": "8d698177e736f98ff0fbec5f3cadd4281d37db2983fd4f273bb151870a31c9af"
}, },
{ {
"title": "2025年下半年全国大学英语四、六级考试报名工作启动", "title": "2025年下半年全国大学英语四、六级考试报名工作启动",
"url": "/html1/report/2509/26-1.htm", "url": "/html1/report/2509/26-1.htm",
"category": "📝 报名",
"hash": "678fceb9259545140b334dbfde975713a554a482520d234fc1600f031f32e9b4" "hash": "678fceb9259545140b334dbfde975713a554a482520d234fc1600f031f32e9b4"
}, },
{ {
"title": "CET笔试", "title": "CET笔试",
"url": "/html1/folder/16113/1586-1.htm", "url": "/html1/folder/16113/1586-1.htm",
"category": "📢 其他",
"hash": "79eee32cf9c97911824e4662f86bbc9afc8aea9daba2f807541df051cfb9ca6c" "hash": "79eee32cf9c97911824e4662f86bbc9afc8aea9daba2f807541df051cfb9ca6c"
}, },
{ {
"title": "CET口试", "title": "CET口试",
"url": "/html1/folder/16113/1587-1.htm", "url": "/html1/folder/16113/1587-1.htm",
"category": "📢 其他",
"hash": "b869b0e2f1055c0a61ee9b51d230ca319d87dcd16dfe689eed6088f5fcfedf65" "hash": "b869b0e2f1055c0a61ee9b51d230ca319d87dcd16dfe689eed6088f5fcfedf65"
}, },
{ {
"title": "在线报名", "title": "在线报名",
"url": "http://cet-bm.neea.edu.cn/", "url": "http://cet-bm.neea.edu.cn/",
"category": "📝 报名",
"hash": "364aa4633a1367162c75f6498e686e5a1fd74ebabb2c4733debf471998a51167" "hash": "364aa4633a1367162c75f6498e686e5a1fd74ebabb2c4733debf471998a51167"
}, },
{ {
"title": "成绩查询", "title": "成绩查询",
"url": "//cet.neea.edu.cn/cet/", "url": "//cet.neea.edu.cn/cet/",
"category": "📊 成绩",
"hash": "903607d3b97b81ceee311b7204bfdf0c495009e9c033c217a1e01c142c0da057" "hash": "903607d3b97b81ceee311b7204bfdf0c495009e9c033c217a1e01c142c0da057"
}, },
{ {
"title": "补办成绩证明", "title": "补办成绩证明",
"url": "//bbcjzm.neea.edu.cn/", "url": "//bbcjzm.neea.edu.cn/",
"category": "📊 成绩",
"hash": "bc56f9653c65bdfe0add8bdfd70af699b51bc0c192a96b5c62ea2ea7b347efb9" "hash": "bc56f9653c65bdfe0add8bdfd70af699b51bc0c192a96b5c62ea2ea7b347efb9"
}, },
{ {
"title": "成绩验证", "title": "成绩验证",
"url": "//www.neea.edu.cn/html1/folder/21033/658-1.htm", "url": "//www.neea.edu.cn/html1/folder/21033/658-1.htm",
"category": "📊 成绩",
"hash": "842cbf459d0325ed6e44da417542a717c47ce69f63fe0fb7a4ae60814e1bfb4a" "hash": "842cbf459d0325ed6e44da417542a717c47ce69f63fe0fb7a4ae60814e1bfb4a"
}, },
{ {
"title": "成绩核查", "title": "成绩核查",
"url": "/html1/folder/19081/5179-1.htm", "url": "/html1/folder/19081/5179-1.htm",
"category": "📊 成绩",
"hash": "aaf8378d7ebeed08fdef16746859583234c36ced0135e67d75ac6e88ee81303f" "hash": "aaf8378d7ebeed08fdef16746859583234c36ced0135e67d75ac6e88ee81303f"
}, },
{ {
"title": "成绩证明", "title": "成绩证明",
"url": "/html1/folder/19081/5180-1.htm", "url": "/html1/folder/19081/5180-1.htm",
"category": "📊 成绩",
"hash": "9537685c4d115a38a34f4d014ccd56eb8e3c83a17b9179664e6858051720b4d1" "hash": "9537685c4d115a38a34f4d014ccd56eb8e3c83a17b9179664e6858051720b4d1"
}, },
{ {
"title": "省级教育考试机构", "title": "省级教育考试机构",
"url": "javascript:", "url": "javascript:",
"category": "📝 考试安排",
"hash": "7572327808ffd1f0a342f16085605f502025944baee9c4a89dbbb3b99dc950bb" "hash": "7572327808ffd1f0a342f16085605f502025944baee9c4a89dbbb3b99dc950bb"
}, },
{ {
"title": "北京教育考试院", "title": "北京教育考试院",
"url": "http://www.bjeea.cn/", "url": "http://www.bjeea.cn/",
"category": "📝 考试安排",
"hash": "5300448f8adf5442261f5ceaa1255869f179a0d7117ec3d30466e593f7f908cf" "hash": "5300448f8adf5442261f5ceaa1255869f179a0d7117ec3d30466e593f7f908cf"
}, },
{ {
"title": "天津市教育招生考试院", "title": "天津市教育招生考试院",
"url": "http://www.zhaokao.net", "url": "http://www.zhaokao.net",
"category": "📝 考试安排",
"hash": "cb06a7f19bc2231b010e287c44d16f48332efade1b6819999a7472930ce28c14" "hash": "cb06a7f19bc2231b010e287c44d16f48332efade1b6819999a7472930ce28c14"
}, },
{ {
"title": "河北省教育考试院", "title": "河北省教育考试院",
"url": "http://www.hebeea.edu.cn", "url": "http://www.hebeea.edu.cn",
"category": "📝 考试安排",
"hash": "24491947d9152a979d94a8344867668b5be94022beb7c3c55008b33ca0b85a61" "hash": "24491947d9152a979d94a8344867668b5be94022beb7c3c55008b33ca0b85a61"
}, },
{ {
"title": "山西省招生考试管理中心", "title": "山西省招生考试管理中心",
"url": "http://www.sxkszx.cn", "url": "http://www.sxkszx.cn",
"category": "📝 考试安排",
"hash": "6084abd031ee4d800065b9648e665982dce30b0de38d553af6df7b3f828a0d3e" "hash": "6084abd031ee4d800065b9648e665982dce30b0de38d553af6df7b3f828a0d3e"
} }
], ],
"last_check": "2026-08-05T04:02:36.173896+00:00" "last_check_utc": "2026-08-05T04:16:50.540062+00:00"
} }
+26 -41
View File
@@ -10,22 +10,18 @@ from bs4 import BeautifulSoup
URL = "https://cet.neea.edu.cn/" URL = "https://cet.neea.edu.cn/"
STATE_FILE = "data/state.json" STATE_FILE = "data/state.json"
PUSH_URL = "https://push.showdoc.com.cn/server/api/push"
def fetch_notices(): def fetch_notices():
headers = { headers = {"User-Agent": "Mozilla/5.0"}
"User-Agent": "Mozilla/5.0"
}
for i in range(3): for retry in range(3):
try: try:
r = requests.get(URL, headers=headers, timeout=20) r = requests.get(URL, headers=headers, timeout=20)
r.encoding = "utf-8" r.encoding = "utf-8"
soup = BeautifulSoup(r.text, "lxml") soup = BeautifulSoup(r.text, "lxml")
result = []
notices = []
for a in soup.find_all("a"): for a in soup.find_all("a"):
title = a.get_text(strip=True) title = a.get_text(strip=True)
@@ -35,15 +31,15 @@ def fetch_notices():
"四六级", "CET", "成绩", "四六级", "CET", "成绩",
"报名", "考试", "准考证" "报名", "考试", "准考证"
]): ]):
notices.append({ result.append({
"title": title, "title": title,
"url": href "url": href
}) })
return notices[:20] return result[:20]
except Exception as e: except Exception as e:
print(f"请求失败 {i+1}/3:", e) print(f"获取失败 {retry + 1}/3:", e)
return None return None
@@ -68,22 +64,10 @@ def save_state(items):
with open(STATE_FILE, "w", encoding="utf-8") as f: with open(STATE_FILE, "w", encoding="utf-8") as f:
json.dump({ json.dump({
"items": items, "items": items,
"last_check": datetime.now(timezone.utc).isoformat() "last_check_utc": datetime.now(timezone.utc).isoformat()
}, f, ensure_ascii=False, indent=2) }, f, ensure_ascii=False, indent=2)
def category(title):
if "报名" in title:
return "📝 报名"
if "成绩" in title:
return "📊 成绩"
if "准考证" in title:
return "🎫 准考证"
if "考试" in title:
return "📅 考试安排"
return "📢 其他"
def push(items): def push(items):
token = os.getenv("PUSH_TOKEN") token = os.getenv("PUSH_TOKEN")
@@ -95,16 +79,17 @@ def push(items):
for item in items: for item in items:
content += ( content += (
f"{category(item['title'])}\n"
f"{item['title']}\n" f"{item['title']}\n"
f"{item['url']}\n\n" f"{item['url']}\n\n"
) )
# ShowDoc Push token 在 URL 路径中
url = f"https://push.showdoc.com.cn/server/api/push/{token}"
try: try:
r = requests.post( r = requests.post(
PUSH_URL, url,
data={ data={
"token": token,
"title": "四六级新通知", "title": "四六级新通知",
"content": content "content": content
}, },
@@ -114,7 +99,7 @@ def push(items):
print("Push status:", r.status_code) print("Push status:", r.status_code)
print("Push response:", r.text) print("Push response:", r.text)
return r.ok return r.status_code == 200
except Exception as e: except Exception as e:
print("Push异常:", e) print("Push异常:", e)
@@ -122,10 +107,10 @@ def push(items):
def main(): def main():
current = fetch_notices() notices = fetch_notices()
if current is None: if notices is None:
print("获取公告失败,本轮跳过") print("获取公告失败")
return return
state = load_state() state = load_state()
@@ -135,26 +120,26 @@ def main():
for x in state.get("items", []) for x in state.get("items", [])
} }
force = os.getenv("FORCE_PUSH", "false").lower() == "true"
new_items = [] new_items = []
for item in current: for item in notices:
item["hash"] = make_hash(item) item["hash"] = make_hash(item)
if item["hash"] not in old_hash: if force or item["hash"] not in old_hash:
new_items.append(item) new_items.append(item)
if not new_items: if new_items:
print("没有新公告") print("发现通知:", len(new_items))
save_state(current)
return
print("发现新公告:", len(new_items))
if push(new_items): if push(new_items):
print("推送成功,保存状态") print("推送成功")
save_state(current) save_state(notices)
else: else:
print("推送失败,不更新状态,等待下次重试") print("推送失败,不更新状态")
else:
print("无新增")
if __name__ == "__main__": if __name__ == "__main__":