Files
boss_dp/自动化.py
2026-03-06 01:33:11 +08:00

158 lines
5.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""
本地脚本:打开比特浏览器,并由 DrissionPage (DP) 接管控制。
运行前请确保1) 比特浏览器客户端已启动(默认 API 端口 543452) 已安装 DrissionPage。
"""
from __future__ import annotations
import random
import sys
import time
from pathlib import Path
from worker.bit_browser import BitBrowserAPI
# 保证从项目根目录运行时可导入 worker 包
_ROOT = Path(__file__).resolve().parent
if str(_ROOT) not in sys.path:
sys.path.insert(0, str(_ROOT))
# 比特浏览器 API 地址(与 worker 默认一致)
BIT_API_BASE = "http://127.0.0.1:54345"
# 要打开的浏览器None=第一个环境,或指定环境名称/备注
BROWSER_NAME = "测试2" # 例如 "第一个" 或 "主账号"
BROWSER_ID = None # 若已知窗口 ID可直接填
def do_recommend_filter(page):
"""
在推荐牛人页面:点开右上角筛选 -> 弹窗内完成筛选操作 -> 点击确认。
筛选 UI 在 iframe recommendFrame 内(推荐牛人 / recommend-v2
"""
time.sleep(1.5) # 等待 iframe 加载
# 获取推荐牛人 iframename=recommendFrame
frame = page.get_frame("@name=recommendFrame")
if not frame:
frame = page.get_frame(1) # fallback第一个 iframe
if not frame:
print("未找到推荐牛人 iframe跳过筛选")
return
# 1. 点击右上角「筛选」,打开弹窗
filter_btn = frame.ele("x://span[text()='筛选']", timeout=3) or frame.ele(
"x://*[contains(text(),'筛选')]", timeout=2
)
if not filter_btn:
print("未找到「筛选」按钮,跳过筛选")
return
filter_btn.click(by_js=True)
time.sleep(0.8)
# 2. 弹窗内完成筛选(按需在此增加具体筛选项点击,例如学历、经验、期望职位等)
# 若无需改任何条件,可保持默认,直接点确认即可。
# 3. 点击弹窗中的「确认」
confirm = (
frame.ele("x://span[text()='确认']", timeout=3)
or frame.ele("x://span[text()='确定']", timeout=2)
or frame.ele("x://*[contains(text(),'确认')]", timeout=2)
)
if not confirm:
print("未找到「确认」按钮")
return
confirm.click(by_js=True)
time.sleep(0.5)
print("推荐牛人筛选已确认")
def main():
from DrissionPage import ChromiumPage, ChromiumOptions
from DrissionPage.errors import NoRectError
print("正在连接比特浏览器 API...")
bit_api = BitBrowserAPI(BIT_API_BASE)
# 打开指定或第一个浏览器窗口
print("正在打开比特浏览器...")
cdp_addr, port, browser_id = bit_api.open_browser(
browser_id=BROWSER_ID,
name=BROWSER_NAME,
remark=None,
)
print(f"已打开浏览器 ID={browser_id}, CDP 端口={port}")
# DrissionPage 接管:先创建选项实例,再设置本地端口
co = ChromiumOptions().set_local_port(port=port)
page = ChromiumPage(addr_or_opts=co)
page.listen.start('wapi/zprelation/friend/getBossFriendListV2')
# 打开推荐牛人/聊天页
page.get("https://www.zhipin.com/web/chat/index")
res = page.listen.wait()
# 执行推荐牛人筛选:点开右上角筛选 -> 弹窗内完成筛选 -> 点击确认
do_recommend_filter(page)
for i in res.response.body["zpData"]["friendList"]:
print(i)
name = i["name"]
job_name = i["jobName"]
jobId = i["jobId"]
lastTime = i["lastTime"] # 最后一次上线
page.listen.start('wapi/zpchat/boss/historyMsg')
# 左侧联系人列表可能是虚拟滚动,直接用 actions.scroll 会 NoRectError先定位再 JS scrollIntoView再点击
name_sel = f'x://span[text()="{i["name"]}"]'
ele = page.ele(name_sel, timeout=2)
if not ele:
print(f" 跳过:未找到联系人 {i['name']}")
continue
try:
ele.run_js("this.scrollIntoView({block: 'center', behavior: 'auto'})")
except Exception:
pass
time.sleep(0.8)
try:
page.ele(name_sel, timeout=2).click(by_js=True)
except (NoRectError, Exception) as e:
print(f" 跳过:点击 {i['name']} 失败: {e}")
continue
res = page.listen.wait()
for i in res.response.body["zpData"]["messages"]:
print(i["body"])
body = i.get("body") or {}
try:
age = body["resume"]["age"] # 年龄
education = body["resume"]["education"] # 大专
position = body["resume"]["position"] # 期望职位
except:
pass
text = body.get("text") if body else None
if text and "手机号" in text:
break
if text and "微信号" in text:
break
else:
page.ele('x://*[@id="boss-chat-editor-input"]').input(
"后续沟通会更及时,您方便留一下您的微信号吗?我这边加您。")
time.sleep(random.randint(1, 3) + random.random())
page.ele('x://div[text()="发送"]').click()
time.sleep(random.randint(1, 5) + random.random())
page.ele('x://span[text()="换微信"]').click()
time.sleep(random.randint(1, 2) + random.random())
# 只点「交换微信」弹窗里的确定:先定位到“确定与对方交换微信吗?”所在 tooltip再点其下的确定按钮避免点到交换简历的确定
page.ele(
'x://span[contains(text(),"确定与对方交换微信吗?")]/../div[@class="btn-box"]/span[contains(@class,"boss-btn-primary")]').click(
by_js=True)
if __name__ == "__main__":
main()