// ==UserScript== // @name Boss直聘JD/HR信息精准提取 (智能反混淆版) // @namespace http://tampermonkey.net/ // @version 2.3 // @description 深度破解 Boss 直聘 CSS 隐藏干扰词反爬,提取精准干净的 JD 与 HR 信息 // @author Padiya (Modified by Henry) // @match https://www.zhipin.com/web/geek/jobs* // @match https://www.zhipin.com/job_detail/* // @match https://www.zhipin.com/gongsi/job/* // @grant GM_setClipboard // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/573368/Boss%E7%9B%B4%E8%81%98JDHR%E4%BF%A1%E6%81%AF%E7%B2%BE%E5%87%86%E6%8F%90%E5%8F%96%20%28%E6%99%BA%E8%83%BD%E5%8F%8D%E6%B7%B7%E6%B7%86%E7%89%88%29.user.js // @updateURL https://update.greasyfork.icu/scripts/573368/Boss%E7%9B%B4%E8%81%98JDHR%E4%BF%A1%E6%81%AF%E7%B2%BE%E5%87%86%E6%8F%90%E5%8F%96%20%28%E6%99%BA%E8%83%BD%E5%8F%8D%E6%B7%B7%E6%B7%86%E7%89%88%29.meta.js // ==/UserScript== (function() { 'use strict'; // 1. 采用高容错率的相对类名选择器 const PAGE_CONFIGS = { 'job-recommend': { jdSelector: '.job-detail-box .job-detail-body .desc, .job-detail-body .job-sec-text', hrSelector: '.job-detail-box .job-boss-info .name, .job-boss-info h2', companyTitleSelector: '.job-detail-box .job-boss-info .boss-info-attr' }, 'job_detail': { jdSelector: '.job-sec-text', hrSelector: '.job-boss-info h2', companyTitleSelector: '.job-boss-info .boss-info-attr' }, 'gongsi': { jdSelector: '.job-detail-body .desc', hrSelector: '.job-detail-body .job-boss-info .name', companyTitleSelector: '.job-detail-body .job-boss-info .boss-info-attr' } }; function createStyle() { const style = document.createElement('style'); style.innerHTML = ` #boss-extractor-btn { position: fixed; bottom: 30px; right: 30px; z-index: 9999; padding: 12px 24px; background: linear-gradient(135deg, #00bebd, #00a6a7); color: white; border: none; border-radius: 50px; font-size: 16px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 15px rgba(0, 190, 189, 0.4); transition: all 0.3s ease; } #boss-extractor-btn:hover { transform: translateY(-3px); box-shadow: 0 6px 20px rgba(0, 190, 189, 0.6); } #boss-extractor-btn:active { transform: translateY(1px); } .boss-tooltip { position: fixed; bottom: 90px; right: 30px; z-index: 10000; padding: 12px 20px; background: #333; color: white; border-radius: 8px; font-size: 14px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); animation: fadeIn 0.3s, fadeOut 0.3s 2s forwards; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @keyframes fadeOut { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(-10px); } } `; document.head.appendChild(style); } function showTooltip(message) { let tooltip = document.querySelector('.boss-tooltip'); if (tooltip) tooltip.remove(); tooltip = document.createElement('div'); tooltip.className = 'boss-tooltip'; tooltip.textContent = message; document.body.appendChild(tooltip); setTimeout(() => tooltip.remove(), 2500); } function cleanHRName(text) { if (!text) return '未找到HR信息'; // 清除状态后缀并安全获取第一行 const cleanText = text.replace(/刚刚活跃|今日活跃|在线/g, ''); return cleanText.split('\n')[0].trim(); } function parseCompanyAndTitle(text) { if (!text) return { company: '未找到公司信息', title: '未找到头衔信息' }; const parts = text.trim().split('·').map(p => p.trim()).filter(p => p); if (parts.length >= 2) return { company: parts[0], title: parts[1] }; return { company: parts[0] || '未找到公司信息', title: '未找到头衔信息' }; } function getCurrentPageConfig() { const url = window.location.href; if (url.includes('gongsi')) return PAGE_CONFIGS['gongsi']; if (url.includes('job_detail')) return PAGE_CONFIGS['job_detail']; if (url.includes('job-recommend')) return PAGE_CONFIGS['job-recommend']; return PAGE_CONFIGS['job-recommend']; // 默认 fallback } // 核心反爬破解逻辑:动态解析 CSS,精准剔除隐藏词 function getCleanText(element) { if (!element) return '未找到信息'; const clone = element.cloneNode(true); // 1. 获取并解析植入的隐藏样式类名 const styles = clone.querySelectorAll('style'); const hiddenClasses = new Set(); styles.forEach(style => { const cssText = style.textContent; // 匹配 .类名 { ... display:none ... } 或 .类名 { ... visibility:hidden ... } const regex = /\.([a-zA-Z0-9_-]+)[^{]*\{[^}]*(?:display:\s*none|visibility:\s*hidden|width:\s*0|font-size:\s*0)[^}]*\}/gi; let match; while ((match = regex.exec(cssText)) !== null) { if (match[1]) hiddenClasses.add(match[1]); } style.remove(); // 解析完后移除 style 标签自身 }); // 2. 遍历所有 span,仅移除被判定为"隐藏类"的干扰标签,保留真实的单字标签 const spans = clone.querySelectorAll('span'); spans.forEach(span => { let isFake = false; span.classList.forEach(className => { if (hiddenClasses.has(className)) { isFake = true; } }); if (isFake) { span.remove(); // 靶向移除(如 "kanzhun", "直聘") } }); // 3. 将
替换为换行符,保证输出到剪贴板时的排版整洁 const brs = clone.querySelectorAll('br'); brs.forEach(br => br.replaceWith('\n')); // 4. 清理多余空行 return clone.textContent ? clone.textContent.replace(/\n\s*\n/g, '\n\n').trim() : '未找到信息'; } // 获取并组合第一页选中的工作内容 function getJobInfo() { const config = getCurrentPageConfig(); if (!config) return '当前页面不支持信息提取'; // 使用 querySelector 自动获取第一个匹配的节点 const jdElement = document.querySelector(config.jdSelector); const hrElement = document.querySelector(config.hrSelector); const companyTitleElement = document.querySelector(config.companyTitleSelector); const jdContent = getCleanText(jdElement); const hrContent = cleanHRName(getCleanText(hrElement)); const { company, title } = parseCompanyAndTitle(getCleanText(companyTitleElement)); return `【职位描述】\n${jdContent}\n\n【招聘员信息】\n${hrContent} / 职位:${title}\n\n【公司信息】\n${company}`; } function init() { createStyle(); const button = document.createElement('button'); button.id = 'boss-extractor-btn'; button.textContent = '📋 提取JD/HR信息'; document.body.appendChild(button); button.addEventListener('click', function() { const jobInfo = getJobInfo(); GM_setClipboard(jobInfo, 'text'); showTooltip('✅ 复制成功!结构与文字已精准解析'); }); } // 延迟一点点执行,确保页面 DOM 彻底加载完毕 setTimeout(init, 1000); })();