利用Python實(shí)現(xiàn)招聘平臺(tái)自動(dòng)投遞功能
引言
在自動(dòng)化招聘投遞的場(chǎng)景中,傳統(tǒng)的基于 DOM 樹的瀏覽器自動(dòng)化(如 Selenium/Playwright)往往面臨極高的維護(hù)成本與嚴(yán)格反爬風(fēng)控。一旦平臺(tái)更新頁面結(jié)構(gòu),腳本就會(huì)立刻失效。
與之相對(duì)的另一種解決方案是:降維打擊,采用純視覺與鍵鼠模擬的 UI 自動(dòng)化。這種模式與人類肉眼看屏幕、用手點(diǎn)鼠標(biāo)的邏輯完全一致,平臺(tái)極難從流量特征上辨別。
核心技術(shù)棧
這類框架主要只依賴幾個(gè)標(biāo)準(zhǔn)庫協(xié)同:
opencv-python:用于圖像色彩分析、輪廓提取。pyautogui/pyscreeze:提供底層的鼠標(biāo)點(diǎn)擊、滾輪滑動(dòng)以及基礎(chǔ)截圖找圖。pyperclip:用于繞過鍵鼠輸入的字符限制(負(fù)責(zé)中文文本和表情發(fā)送)。keyboard:系統(tǒng)級(jí)全局鍵盤鉤子,用于在發(fā)生異常時(shí)緊急中斷。
所謂的自動(dòng)化其實(shí)就三步走“截圖 ? 找圖 ? 點(diǎn)擊”;
在這里最容易導(dǎo)致程序停止的就是“找圖”這個(gè)關(guān)鍵!
網(wǎng)速不穩(wěn)定的解決方案
現(xiàn)象:點(diǎn)擊崗位后,詳情頁有時(shí) 0.1 秒加載好,有時(shí)卡 3 秒。如果硬寫 time.sleep(3) 效率極低;寫短了會(huì)找不到按鈕而報(bào)錯(cuò)崩潰。
動(dòng)態(tài)輪詢與超時(shí)棄權(quán)機(jī)制(動(dòng)態(tài)找圖點(diǎn)擊)。 不使用固定等待,通過高頻捕捉屏幕元素,一旦出現(xiàn)馬上動(dòng)作,到了時(shí)限依然沒有就靜默跳過。
import time
import pyautogui
def click_with_timeout(img_path, confidence=0.8, timeout=3.0):
start_time = time.time()
# 在 timeout 秒內(nèi)不斷重試尋找目標(biāo)圖
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
# 加一點(diǎn)小的 Jitter 避免 CPU 跑滿
time.sleep(0.2)
# 徹底超時(shí)后不要報(bào)錯(cuò)讓程序崩潰,返回 False 進(jìn)行降級(jí)處理
print(f"[{img_path}] 未出現(xiàn),跳過。")
return False
不同投遞按鈕的解決方案
現(xiàn)象:招聘平臺(tái)的按鈕是動(dòng)態(tài)的。找人溝通時(shí),它可能是“立即溝通”,如果是聊過的 HR 則變成了“繼續(xù)溝通”。如果當(dāng)日配額用完,直接彈拉窗告訴你“到達(dá)上限”。這就要求我們有一套非線性的決策機(jī)制。
If-Else 兜底分支與全局哨兵(決策樹抽象)。
import sys
def execute_apply_action():
# 1. 哨兵監(jiān)測(cè)點(diǎn):如果出現(xiàn)了達(dá)到上限的提示,說明不能再跑了
if click_with_timeout("img_limit_reached.png", timeout=1.0):
print("今日溝通達(dá)上限,直接停止任務(wù)。")
sys.exit(0)
# 2. 常規(guī)決策樹兜底分支
if click_with_timeout("img_chat_now.png", timeout=2.0):
print("發(fā)現(xiàn)[立即溝通]按鈕,已點(diǎn)擊!")
elif click_with_timeout("img_continue_chat.png", timeout=2.0):
print("發(fā)現(xiàn)[繼續(xù)溝通]按鈕,此前聊過了,已點(diǎn)擊!")
else:
print("未能識(shí)別當(dāng)前的投遞按鈕,為了防止亂點(diǎn),直接放棄當(dāng)前職位。")
辨別已投遞的解決方案
現(xiàn)象:找圖庫 locateOnScreen 雖然能找元素,但無法理解業(yè)務(wù)上下文。比如列表里某些崗位是昨天看過的,字體顏色變灰了;而新崗位是深色的。如果無法分辨,程序就會(huì)在原地?zé)o限重復(fù)點(diǎn)擊第一張卡片。
OpenCV 色彩空間均值分析(特征截取法)。 我們可以把一塊區(qū)域抓取下來,轉(zhuǎn)換并計(jì)算它的發(fā)色偏向(比如 RGB 通道平均亮度)。
import cv2
import numpy as np
def is_job_unread(cropped_image_path):
"""
判斷該卡片圖片區(qū)域中的標(biāo)題是否沒看過。
(假設(shè)深色字體是未讀,淺灰色字體是已讀)
"""
# 1. 讀取截圖
img = cv2.imread(cropped_image_path)
# 2. 計(jì)算 B, G, R 單個(gè)通道的全局均值
mean_val = cv2.mean(img)
mean_b, mean_g, mean_r = mean_val[0], mean_val[1], mean_val[2]
# 3. 簡(jiǎn)單的特征判定法:如果 RGB 值整體偏高(發(fā)白/淺灰),說明已經(jīng)看過
# 具體閾值可根據(jù)實(shí)際平臺(tái)的色號(hào)校準(zhǔn)
if mean_b > 150 and mean_g > 150 and mean_r > 150:
print("該崗位為已瀏覽狀態(tài)(灰色),跳過。")
return False
print("該崗位標(biāo)題偏暗/全黑,未訪問過,準(zhǔn)備點(diǎn)擊。")
return True
停止方案
現(xiàn)象:由于程序是通過操控系統(tǒng)光標(biāo)來運(yùn)行的,一旦發(fā)生死循環(huán)(如由于縮放問題點(diǎn)空了),人類用戶試圖去點(diǎn)關(guān)閉按鈕,光標(biāo)下一秒就被代碼搶走了——完全失去了控制權(quán)。
全局異步監(jiān)聽鉤子:(異步監(jiān)聽)。
import keyboard
import os
# 這個(gè)標(biāo)志可以讓我們的 while 循環(huán)提前結(jié)束
RUNNING = True
def emergency_stop():
global RUNNING
RUNNING = False
print("【攔截】檢測(cè)到 ESC 鍵,緊急制動(dòng)!")
os._exit(0) # 強(qiáng)殺進(jìn)程,無論線程在阻塞什么
# 注冊(cè)系統(tǒng)最高優(yōu)先級(jí)的熱鍵
keyboard.add_hotkey('esc', emergency_stop)
def main_loop():
while RUNNING:
print("我正在自動(dòng)執(zhí)行投遞...")
# 執(zhí)行投遞動(dòng)作 ...
time.sleep(2)
以上就是利用Python實(shí)現(xiàn)招聘平臺(tái)自動(dòng)投遞功能的詳細(xì)內(nèi)容,更多關(guān)于Python招聘平臺(tái)自動(dòng)投遞的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python使用pypdf2實(shí)現(xiàn)pdf文檔解密
Pandas操作兩個(gè)Excel實(shí)現(xiàn)數(shù)據(jù)對(duì)應(yīng)行的合并
python str()如何將參數(shù)轉(zhuǎn)換為字符串類型

