Where is the end of the humain?

白嫖微软服务器:全自动监控法国 ANEF 居留申请状态

在法国的小伙伴都知道,ANEF(外管局)的居留申请状态更新极其佛系。每天手动登录那个加载缓慢、经常报错的官网去查看进度,简直是一种精神折磨。

之前我尝试过在自己的小内存 VPS 上跑无头浏览器监控,结果内存分分钟爆满。最终,我走通了一条高大上的路子——利用 GitHub Actions 免费服务器进行全自动监控,每天准时发邮件播报状态。

本文将手把手教你如何搭建这套零内耗、零成本的监控系统。

核心原理:为什么选择 GitHub Actions?

GitHub Actions 是微软推出的 CI/CD 服务,它允许你在其托管的虚拟机上运行自定义脚本。

对于我们这个需求,它的优势简直是完美的:

  1. 完全免费:私有仓库每个月有 2000 分钟的免费额度,每天跑一次监控任务(约消耗 1 分钟),根本用不完。
  2. 零内耗:不需要占用你自己服务器的任何 CPU 或内存。
  3. 环境标准:微软提供的 Ubuntu 环境极其标准,Playwright(无头浏览器)运行非常稳定。
  4. 反爬虫友好:ANEF 的防火墙(如 Cloudflare)对小厂 VPS 的 IP 非常敏感,但对大厂(微软)的 IP 段相对宽容。不过,这也是唯一的潜在风险点:如果微软云的 IP 被防火墙拉黑,脚本就会失效。目前来看,值得一试。

核心挑战:ANEF 精确登录

ANEF 的登录系统使用的是 Keycloak 单点登录(SSO)。传统的账号密码模拟往往会因为动态 Token 或加载缓慢而失败。

为了提高稳定性,我深入分析了 ANEF 的 SSO 授权链,找到了直接访问底层授权直链的方法,跳过了主页花里胡哨的动画,直接访问登录表单,大大提高了成功率。

部署指南:10 分钟彻底解放

第一步:准备发件邮箱(以 Gmail 为例)

为了保证邮件能 100% 发送成功,建议使用 Gmail、QQ 邮箱、163 邮箱等主流邮箱作为发件箱。由于 GitHub Actions 的安全性限制,你绝对不能在代码里使用你的原密码,必须使用 应用专用密码 (App Password)

  • Gmail 用户:登录谷歌账户 -> 安全 (Security) -> 开启两步验证 -> 搜索 “应用密码” -> 生成一个名为 anef-monitor 的密码,复制那一串 16 位字母。
  • QQ/163 邮箱用户:进入邮箱设置 -> 账户 -> 开启 SMTP 服务 -> 会获得一串授权码。

第二步:创建 GitHub 私有仓库

  1. 登录你的 GitHub 账号。
  2. 新建一个仓库(Repository),名字随便起(比如 anef-visa-monitor)。
  3. 【最重要的一步】 仓库可见性务必选择 Private(私有)!否则你的账号密码、API 数据都会被公开。

第三步:配置 Secrets 环境变量

这是为了将你的账号密码安全地存入 GitHub 的加密库中,脚本能读取到,但外人看不到。

  1. 在仓库主页点击 Settings
  2. 左侧菜单展开 Secrets and variables -> Actions
  3. 点击 New repository secret,依次添加以下 5 个机密变量:
Secret 名字Value (填写内容)说明
ANEF_EMAILyour_anef_email@xxx.com您登录 ANEF 的账号
ANEF_PWDyour_anef_password您登录 ANEF 的密码
SMTP_USERsender@gmail.com发信邮箱账号(比如您的 Gmail)
SMTP_PWDabcd efgh ijkl mnop刚刚获取的邮箱应用密码/授权码
NOTIFY_EMAILreceiver@xxx.com您自己用来接收通知的邮箱(可以和发信邮箱相同)

第四步:编写 Python 自动化脚本 (monitor.py)

在仓库主页点击 Add file -> Create new file,文件名输入 monitor.py,然后粘贴以下精确定位的优化代码:

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import os
import time
import smtplib
from email.mime.text import MIMEText
from playwright.sync_api import sync_playwright

# 1. 从 GitHub Secrets 中读取机密变量
ANEF_EMAIL = os.environ.get("ANEF_EMAIL")
ANEF_PWD = os.environ.get("ANEF_PWD")
SMTP_USER = os.environ.get("SMTP_USER")
SMTP_PWD = os.environ.get("SMTP_PWD")
NOTIFY_EMAIL = os.environ.get("NOTIFY_EMAIL")

# 发件服务器配置 (此处以 Gmail 为例)
SMTP_SERVER = "smtp.gmail.com"
SMTP_PORT = 465

# 登录直链与目标 API
SSO_LOGIN_URL = "喝咖啡备注联系方式发送"
API_URL = "喝咖啡备注联系方式发送"

def send_email(content, subject="【ANEF 居留状态通知】"):
"""邮件发送模块"""
msg = MIMEText(content, 'plain', 'utf-8')
msg['Subject'] = subject
msg['From'] = SMTP_USER
msg['To'] = NOTIFY_EMAIL
try:
server = smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT)
server.login(SMTP_USER, SMTP_PWD)
server.sendmail(SMTP_USER, [NOTIFY_EMAIL], msg.as_string())
server.quit()
print("邮件通知发送成功!")
except Exception as e:
print(f"邮件发送失败: {e}")

def run_monitor():
"""监控核心模块"""
with sync_playwright() as p:
# 启动浏览器
browser = p.chromium.launch(headless=True)
# 伪装请求头,避免被防火墙拦截
context = browser.new_context(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
locale="fr-FR",
timezone_id="Europe/Paris"
)
page = context.new_page()

try:
print("1. 正在访问 ANEF SSO 登录直链...")
page.goto(SSO_LOGIN_URL, timeout=60000)

print("2. 正在精确定位表单并填写账号密码...")
# Keycloak 登录页的邮箱和密码输入框 name 属性分别是 username 和 password
page.wait_for_selector("input[name='username']", timeout=20000)
page.fill("input[name='username']", ANEF_EMAIL)
page.fill("input[name='password']", ANEF_PWD)

print("3. 点击登录按钮提交表单...")
# 明确点击 type='submit' 的按钮
page.click("button[type='submit']")

print("4. 正在智能等待重定向归位...")
# 监听网址是否跳回了 /usagers/,证明授权成功
page.wait_for_url("**/usagers/**", timeout=30000)

# 缓冲几秒,确保本地 Cookie 写入完成
time.sleep(3)

print("5. 身份校验成功!直调核心数据 API...")
page.goto(API_URL)

# 获取页面的纯文本(JSON 数据)
result_data = page.locator("body").inner_text()

if "error" in result_data.lower() or "forbidden" in result_data.lower():
send_email(f"API 拒绝访问,可能防火墙拦截,返回原始内容:\n\n{result_data}", "【异常】ANEF 监控接口失效")
else:
send_email(f"恭喜,成功获取居留申请最新数据:\n\n{result_data}", "【更新】ANEF 居留申请状态播报")

except Exception as e:
send_email(f"自动化脚本执行遇到未知错误,可能是网页改版或遭遇图形验证码:\n\n{str(e)}", "【崩溃】监控脚本执行失败")
finally:
browser.close()

if __name__ == "__main__":
run_monitor()

第五步:配置定时任务 (daily-check.yml)

最后,我们需要告诉 GitHub Actions 在每天什么时候跑这个脚本。

在仓库里点击 “Add file” -> “Create new file”。

在文件名的框里完整输入:.github/workflows/daily-check.yml (注意路径和点,这会让 GitHub 识别为标准的工作流控制文件)。

粘贴以下工作流代码:

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
name: Daily ANEF Monitor

# 触发条件
on:
schedule:
# 每天世界标准时间(UTC)上午 07:00 运行(即巴黎夏季时间上午09:00,冬季上午08:00)
- cron: '0 7 * * *'
workflow_dispatch: # 开启手动触发按钮,方便在网页上随时测试跑

jobs:
run-monitor:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.10'

- name: Install Dependencies
run: |
pip install playwright
playwright install chromium

- name: Run Monitor Script
env:
ANEF_EMAIL: ${{ secrets.ANEF_EMAIL }}
ANEF_PWD: ${{ secrets.ANEF_PWD }}
SMTP_USER: ${{ secrets.SMTP_USER }}
SMTP_PWD: ${{ secrets.SMTP_PWD }}
NOTIFY_EMAIL: ${{ secrets.NOTIFY_EMAIL }}
run: python monitor.py

祝顺利下卡!
提交保存完成后,你就可以在 Actions 标签页下点击 “Run workflow” 来强行触发测试了。

如果一切顺利,从今天起,你将彻底告别 ANEF 那个卡顿的登录界面,在每天早餐时分,安静地等待邮件通知最新的居留申请状态。祝你的居留申请早日收到卡!

© 2026 iattachの小站

Elegant theme by Shiro · Made by Acris with ❤️