BOSS直聘自动打招呼油猴脚本🐒

1,858 阅读3分钟

背景

boss直聘每天打招呼次数是100次。每次都点击太麻烦了(🙃主要是每天精挑细选,勤勤恳恳的投递,回应的就没几个,干脆自动化听天由命吧🥲)。 写个油猴脚本自动打招呼~

功能

  • 可填写:薪资、hr是否在线、打招呼数量
  • 自动到职位详情页打招呼,自动关闭
  • 列表自动翻页
  • 微信消息推送

先上效果图😸

需要先搜索职位,到搜索结果页再使用哈

职位搜索列表页:
image.png

自动进入详情页:
image.png

点击完立即沟通,自动关闭当前页:
image.png

操作完后:
image.png

微信推送通知:
image.png

安装油猴扩展🙈

谷歌商店链接:chromewebstore.google.com/detail/%E7%…

image.png

开启扩展:chrome://extensions/

image.png

右上角会有猴子图标

image.png

新建脚本

image.png

脚本源码👻

写完脚本开启后,访问boss直聘网站就会自动执行下面的脚本,出现UI界面了。

// ==UserScript==
// @name         boss直聘自动打招呼
// @namespace    lz
// @version      1.0
// @description  输入打招呼数量和要求薪资自动打招呼
// @author       迷途小码农
// @match        https://www.zhipin.com/*
// @grant        none
// ==/UserScript==
// 请先到 https://www.zhipin.com/web/geek/job 页面搜索职位再使用该脚本
// 微信推送:https://www.pushplus.plus/ 扫码登录拿到token替换pushPlusToken即可
(function() {
    'use strict';

    // 配置项
    let state = {
        limitMax: 10, // 最大沟通数量 boss限制1天100份
        hasUsed: 0, // 已沟通数量
        mustOnline: false, // 只沟通在线的,基本很少
        minSalary: 0, // k为单位
        pushPlusToken: '', // 微信推送,不填则不推送。
        waitClickList: [],
        hidden:false, // 详情页标题修改和加遮罩层,掩人耳目
    }
    let endTimeText = null;
    let timer = null;

    // 收集列表项
    async function getList() {
        const jobListItems = document.querySelectorAll('.job-list-box .job-card-wrapper');
        for (const item of jobListItems) {
            const jobName = item.querySelector('.job-name').textContent;
            const salary = item.querySelector('.salary').textContent;
            //在线标签
            const online = item.querySelector('.boss-online-tag');
            // 获取详情链接
            const aLink = item.querySelector('.job-card-left');
            const [min, max] = salary.split('K')[0].split('-').map(x => parseInt(x))
            // 必须在线和薪资达标
            if (state.mustOnline && !online) {
                continue;
            }
            if (max < state.minSalary) {
                continue;
            }
            state.waitClickList.push(aLink)
        }
        for (const ele of state.waitClickList) {
            // 机会耗尽了
            let todayNoCount = localStorage.getItem("todayNoCount")
            if(todayNoCount){
                finish("【机会耗尽了】")
                return
            }
            // 如果达标了
            state.hasUsed = localStorage.getItem("hasUsed") || 0
            if (state.hasUsed >= state.limitMax) {
                finish()
                return
            }
            // 防止沟通操作频繁
            await new Promise((resolve,reject)=>{
                ele.click()
                setTimeout(()=>{
                    resolve()
                },2000)
            })
        }
        // 一秒后下一页
        const urlParams = new URLSearchParams(window.location.search);
        const pageParam = urlParams.get('page');
        // 最后一页
        if(pageParam==10){
            finish()
            return
        }
        setTimeout(() => {
            nextPage().then(x => {
                state.waitClickList = []
                getList()
            })
        }, 1000)
    }

    // 下一页
    async function nextPage() {
        return new Promise((resolve, reject) => {
            const optionsPages = document.querySelector('.options-pages');
            const nextBtn = optionsPages.lastElementChild;
            if (nextBtn) {
                nextBtn.click()
                resolve()
            } else {
                reject()
            }
        })
    }
    // 已完成打招呼
    function finish(msg=""){
        endTimeText.textContent =  `结束时间:${new Date().toLocaleString()}`
        setTimeout(()=>{
            state.hasUsed = localStorage.getItem("hasUsed")||0
            // 发送微信推送消息
            state.pushPlusToken && fetch(`https://www.pushplus.plus/send?token=${state.pushPlusToken}&title=boss自动打招呼&content=打招呼数量:${state.hasUsed} 要求hr在线:${state.mustOnline?'是':'否'} ${msg} &template=html`)
            clearInterval(timer)
        },1000)
        return
    }
    // 绘制ui
    function drawUI() {
        // 创建一个 <div> 元素作为卡片容器
        const cardContainer = document.createElement('div');
        cardContainer.style.position = 'fixed';
        cardContainer.style.top = '200px';
        cardContainer.style.left = '10px';
        cardContainer.style.backgroundColor = 'white';
        cardContainer.style.padding = '10px';
        cardContainer.style.borderRadius = '8px';
        cardContainer.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.1)';
        cardContainer.style.width = '210px';
        cardContainer.style.zIndex = '999';

        // 创建已打招呼数量展示
        const titleText = createDisplay('自动打招呼');
        // 创建打招呼数量输入框
        const deliveryInput = createInput('打招呼数量', 'number');
        // 创建薪资输入框
        const salaryInput = createInput('最低薪资K', 'text');

        // 创建选择框
        const onlineCheckbox = createCheckbox('online', 'HR必须在线');
        // 已打招呼数量
        const countText = createDisplay('本轮已打招呼数量:');
        // 开始时间
        const startTimeText = createDisplay('开始时间:');
        // 结束时间
        endTimeText = createDisplay('结束时间:');
        // 创建开始打招呼按钮
        const submitButton = createButton('开始打招呼', '#00bebd');
        // 创建刷新重置按钮
        const resetButton = createButton('刷新重置', '#a2a3a9');

        // 添加输入框、展示和按钮到卡片容器中
        cardContainer.appendChild(titleText);
        cardContainer.appendChild(deliveryInput);
        cardContainer.appendChild(salaryInput);

        cardContainer.appendChild(onlineCheckbox);

        cardContainer.appendChild(countText);
        cardContainer.appendChild(startTimeText);
        cardContainer.appendChild(endTimeText);
        cardContainer.appendChild(submitButton);
        cardContainer.appendChild(resetButton);

        // 将卡片容器添加到页面中
        document.body.appendChild(cardContainer);

        let sendCount = 0;

        // 点击开始打招呼按钮时的事件处理程序
        submitButton.addEventListener('click', () => {
            state.limitMax = parseInt(deliveryInput.value);
            state.minSalary =  parseInt(salaryInput.value);
            state.mustOnline = onlineCheckbox.querySelector('input').checked;
            startTimeText.textContent =  `开始时间:${new Date().toLocaleString()}`
            localStorage.removeItem("hasUsed");
            localStorage.removeItem("todayNoCount");
            getList();
            timer = setInterval(()=>{
                countText &&  (countText.textContent = `本轮已打招呼数量:${localStorage.getItem("hasUsed") || 0}` );
            },10)
        });

        // 点击刷新重置按钮时的事件处理程序
        resetButton.addEventListener('click', () => {
            location.href = location.href.replace(/[\?|&]page=[^&]+/, '');
        });
    }

    // 创建输入框的辅助函数
    function createInput(placeholder, type) {
        const input = document.createElement('input');
        input.type = type;
        input.placeholder = placeholder;
        input.style.width = '100%';
        input.style.padding = '8px';
        input.style.marginBottom = '10px';
        input.style.border = '1px solid #ccc';
        input.style.borderRadius = '4px';
        return input;
    }

    // 创建展示信息的辅助函数
    function createDisplay(label) {
        const display = document.createElement('div');
        display.textContent = label;
        display.style.marginBottom = '10px';
        return display;
    }

    // 创建按钮的辅助函数
    function createButton(text, backgroundColor) {
        const button = document.createElement('button');
        button.textContent = text;
        button.style.marginTop = '10px';
        button.style.width = '100%';
        button.style.padding = '8px';
        button.style.backgroundColor = backgroundColor;
        button.style.color = 'white';
        button.style.border = 'none';
        button.style.borderRadius = '4px';
        button.style.cursor = 'pointer';
        return button;
    }

    // 创建选择框
    function createCheckbox(name, label) {
        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.name = name;
        checkbox.style.marginRight = '5px';
        const checkboxLabel = document.createElement('label');
        checkboxLabel.textContent = label;
        const container = document.createElement('div');
        container.appendChild(checkbox);
        container.appendChild(checkboxLabel);
        return container;
    }

    // 隐藏页面
    function hidden(){
        // 删除标题
        document.title = "测试";
        // 删除图标
        var favicon = document.querySelector("link[rel='icon']");
        if (favicon) {
            favicon.parentNode.removeChild(favicon);
        }
        // 创建遮挡层
        var overlay = document.createElement("div");
        overlay.style.position = "fixed";
        overlay.style.top = "0";
        overlay.style.left = "0";
        overlay.style.width = "100%";
        overlay.style.height = "100%";
        overlay.style.backgroundColor = "white";
        overlay.style.zIndex = "9999";
        // 将遮挡层添加到文档中
        document.body.appendChild(overlay);
    }

    // 主页
    if (location.pathname == '/web/geek/job') {
        drawUI();
    }

    // 详情页
    if (location.pathname.includes('/job_detail/')) {
        state.hidden && hidden()
        let btn = document.querySelector('.btn-startchat');
        if (btn && btn.innerText == '立即沟通') {
            btn.click();
            setTimeout(()=>{
               let diologP = document.querySelector('.dialog-con p')
               if(!diologP){
                   let hasUsed = localStorage.getItem("hasUsed") || 0;
                   localStorage.setItem("hasUsed", ++hasUsed);
               }
               if(diologP.textContent=='今日沟通人数已达上限,请明天再试')
                   localStorage.setItem("todayNoCount", true);
            },500)
            setTimeout(()=>{window.close()},1000)
        }
    }

})();