如何通过 Python 实现招聘平台自动投递

如何通过 Python 实现招聘平台自动投递

在自动化招聘投递的场景中,传统的基于 DOM 树的浏览器自动化(如 Selenium/Playwright)往往面临极高的维护成本与严格反爬风控。一旦平台更新页面结构,脚本就会立刻失效。

与之相对的另一种解决方案是:降维打击,采用纯视觉与键鼠模拟的 UI 自动化。这种模式与人类肉眼看屏幕、用手点鼠标的逻辑完全一致,平台极难从流量特征上辨别。

核心技术栈

这类框架主要只依赖几个标准库协同:

  • opencv-python:用于图像色彩分析、轮廓提取。
  • pyautogui / pyscreeze:提供底层的鼠标点击、滚轮滑动以及基础截图找图。
  • pyperclip:用于绕过键鼠输入的字符限制(负责中文文本和表情发送)。
  • keyboard:系统级全局键盘钩子,用于在发生异常时紧急中断。

所谓的自动化其实就三步走"截图 ➔ 找图 ➔ 点击";

在这里最容易导致程序停止的就是"找图"这个关键!

网速不稳定的解决方案

现象 :点击岗位后,详情页有时 0.1 秒加载好,有时卡 3 秒。如果硬写 time.sleep(3) 效率极低;写短了会找不到按钮而报错崩溃。

动态轮询与超时弃权机制(动态找图点击)。 不使用固定等待,通过高频捕捉屏幕元素,一旦出现马上动作,到了时限依然没有就静默跳过。

python 复制代码
import time
import pyautogui

def click_with_timeout(img_path, confidence=0.8, timeout=3.0):
    start_time = time.time()
    
    # 在 timeout 秒内不断重试寻找目标图
    while time.time() - start_time < timeout:
        try:
            pos = pyautogui.locateCenterOnScreen(img_path, confidence=confidence)
            if pos:
                pyautogui.click(pos)
                return True
        except pyautogui.ImageNotFoundException:
            pass
        
        # 加一点小的 Jitter 避免 CPU 跑满
        time.sleep(0.2)
        
    # 彻底超时后不要报错让程序崩溃,返回 False 进行降级处理
    print(f"[{img_path}] 未出现,跳过。")
    return False

不同投递按钮的解决方案

现象 :招聘平台的按钮是动态的。找人沟通时,它可能是"立即沟通",如果是聊过的 HR 则变成了"继续沟通"。如果当日配额用完,直接弹拉窗告诉你"到达上限"。这就要求我们有一套非线性的决策机制

If-Else 兜底分支与全局哨兵(决策树抽象)。

python 复制代码
import sys

def execute_apply_action():
    # 1. 哨兵监测点:如果出现了达到上限的提示,说明不能再跑了
    if click_with_timeout("img_limit_reached.png", timeout=1.0):
        print("今日沟通达上限,直接停止任务。")
        sys.exit(0)

    # 2. 常规决策树兜底分支
    if click_with_timeout("img_chat_now.png", timeout=2.0):
        print("发现[立即沟通]按钮,已点击!")
    elif click_with_timeout("img_continue_chat.png", timeout=2.0):
        print("发现[继续沟通]按钮,此前聊过了,已点击!")
    else:
        print("未能识别当前的投递按钮,为了防止乱点,直接放弃当前职位。")

辨别已投递的解决方案

现象 :找图库 locateOnScreen 虽然能找元素,但无法理解业务上下文。比如列表里某些岗位是昨天看过的,字体颜色变灰了;而新岗位是深色的。如果无法分辨,程序就会在原地无限重复点击第一张卡片。

OpenCV 色彩空间均值分析(特征截取法)。 我们可以把一块区域抓取下来,转换并计算它的发色偏向(比如 RGB 通道平均亮度)。

python 复制代码
import cv2
import numpy as np

def is_job_unread(cropped_image_path):
    """
    判断该卡片图片区域中的标题是否没看过。
    (假设深色字体是未读,浅灰色字体是已读)
    """
    # 1. 读取截图
    img = cv2.imread(cropped_image_path)
    
    # 2. 计算 B, G, R 单个通道的全局均值
    mean_val = cv2.mean(img)
    mean_b, mean_g, mean_r = mean_val[0], mean_val[1], mean_val[2]
    
    # 3. 简单的特征判定法:如果 RGB 值整体偏高(发白/浅灰),说明已经看过
    # 具体阈值可根据实际平台的色号校准
    if mean_b > 150 and mean_g > 150 and mean_r > 150:
        print("该岗位为已浏览状态(灰色),跳过。")
        return False
        
    print("该岗位标题偏暗/全黑,未访问过,准备点击。")
    return True

停止方案

现象:由于程序是通过操控系统光标来运行的,一旦发生死循环(如由于缩放问题点空了),人类用户试图去点关闭按钮,光标下一秒就被代码抢走了------完全失去了控制权。

全局异步监听钩子:(异步监听)。

python 复制代码
import keyboard
import os

# 这个标志可以让我们的 while 循环提前结束
RUNNING = True 

def emergency_stop():
    global RUNNING
    RUNNING = False
    print("【拦截】检测到 ESC 键,紧急制动!")
    os._exit(0) # 强杀进程,无论线程在阻塞什么

# 注册系统最高优先级的热键
keyboard.add_hotkey('esc', emergency_stop)

def main_loop():
    while RUNNING:
        print("我正在自动执行投递...")
        # 执行投递动作 ...
        time.sleep(2)
相关推荐
狼爷1 小时前
短视频播放量(Views)计数系统实现方案:高并发、不丢数的工业级实践
后端·架构
其实防守也摸鱼2 小时前
CTF密码学综合教学指南--第九章
开发语言·网络·python·安全·网络安全·密码学·ctf
砚底藏山河2 小时前
Python量化开发:2026最佳实时股票数据API接口推荐与对比
开发语言·windows·python
苍何3 小时前
我用 Tabbit 浏览器搭了一套内容创作全自动流水线,太香了!
后端
研究点啥好呢3 小时前
专为求职者开发的“面馆”!!!摆脱面试焦虑!!!
python·面试·开源·reactjs·求职招聘·fastapi
苍何3 小时前
全网首测,TRAE SOLO 的 AI 麦克风!
后端
IT_陈寒3 小时前
Redis这个内存杀手,差点让我们运维半夜追杀我
前端·人工智能·后端
苍何3 小时前
用 Agent 团队来做知识管理,非常顶!
后端
苍何3 小时前
WPS多维表格,给开发者铺了条新路!
后端