Files
boss_dp/1.py

189 lines
6.7 KiB
Python
Raw Normal View History

2026-03-06 00:43:40 +08:00
# -*- coding: utf-8 -*-
"""
本地脚本 DrissionPage (DP) 控制浏览器本地谷歌 Chrome 或比特浏览器
- 使用本地谷歌USE_LOCAL_CHROME = True会启动/连接本机 Chrome
- 使用比特浏览器USE_LOCAL_CHROME = False需先启动比特浏览器客户端API 端口 54345
"""
from __future__ import annotations
import random
import sys
import time
2026-03-06 01:33:11 +08:00
2026-03-06 00:43:40 +08:00
from pathlib import Path
# 保证从项目根目录运行时可导入 worker 包
_ROOT = Path(__file__).resolve().parent
if str(_ROOT) not in sys.path:
sys.path.insert(0, str(_ROOT))
# ---------- 选择控制对象 ----------
2026-03-06 01:33:11 +08:00
USE_LOCAL_CHROME = True # True=本地谷歌 ChromeFalse=比特浏览器
2026-03-06 00:43:40 +08:00
# 本地谷歌 Chrome 配置(仅当 USE_LOCAL_CHROME=True 时生效)
CHROME_DEBUG_PORT = 9222 # 调试端口;若为 None 则由脚本自动启动 Chrome
2026-03-06 01:33:11 +08:00
CHROME_PATH = None # 例如 r"C:\Program Files\Google\Chrome\Application\chrome.exe"None 用系统默认
2026-03-06 00:43:40 +08:00
# 比特浏览器配置(仅当 USE_LOCAL_CHROME=False 时生效)
BIT_API_BASE = "http://127.0.0.1:54345"
BROWSER_NAME = "测试2"
BROWSER_ID = None
def _connect_local_chrome():
"""连接或启动本地谷歌 Chrome返回 ChromiumPage。"""
from DrissionPage import ChromiumPage, ChromiumOptions
co = ChromiumOptions()
if CHROME_PATH:
co.set_browser_path(CHROME_PATH)
if CHROME_DEBUG_PORT is not None:
# 连接已开启调试端口的 Chrome需先手动启动chrome --remote-debugging-port=9222
co.set_local_port(CHROME_DEBUG_PORT)
print(f"正在连接本机 Chrome调试端口 {CHROME_DEBUG_PORT}...")
page = ChromiumPage(addr_or_opts=co)
else:
# 由 DrissionPage 自动启动 Chrome
print("正在启动本地谷歌 Chrome...")
page = ChromiumPage(addr_or_opts=co)
print("已连接本地 Chrome。")
return page
def _connect_bit_browser():
"""通过比特浏览器 API 打开并连接,返回 ChromiumPage。"""
from worker.bit_browser import BitBrowserAPI
from DrissionPage import ChromiumPage, ChromiumOptions
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}")
co = ChromiumOptions().set_local_port(port=port)
return ChromiumPage(addr_or_opts=co)
2026-03-06 01:33:11 +08:00
def main(filters):
2026-03-06 00:43:40 +08:00
from DrissionPage.errors import NoRectError
if USE_LOCAL_CHROME:
page = _connect_local_chrome()
else:
page = _connect_bit_browser()
2026-03-06 01:33:11 +08:00
# 先启动监听再执行动作,否则拿不到数据包(见 DP 文档)
2026-03-06 00:43:40 +08:00
page.listen.start('wapi/zpjob/rec/geek/list')
2026-03-06 01:33:11 +08:00
if filters:
main2(page, filters)
# 有筛选时page.get 会触发第 1 个 geek/list点「确定」触发第 2 个;取最后一个才是筛选后的结果
packets = page.listen.wait(count=2, timeout=30)
res = packets[-1] if packets else None
else:
page.get("https://www.zhipin.com/web/chat/recommend")
res = page.listen.wait(timeout=30)
if not res:
raise RuntimeError("未捕获到目标请求 wapi/zpjob/rec/geek/list")
2026-03-06 00:43:40 +08:00
for i in res.response.body["zpData"]["geekList"]:
print(i)
2026-03-06 01:33:11 +08:00
geekName = i["geekCard"]["geekName"] # 姓名
2026-03-06 00:43:40 +08:00
geekDegree = i["geekCard"]["geekDegree"] # 学历
2026-03-06 01:33:11 +08:00
expectPositionName = i["geekCard"]["expectPositionName"] # 期待职位
2026-03-06 00:43:40 +08:00
expectLocationName = i["geekCard"]["expectLocationName"] # 地区
applyStatusDesc = i["geekCard"]["applyStatusDesc"] # 当前状态离职0随时到岗之类的
ageDesc = i["geekCard"]["ageDesc"] # 年龄
lowSalary = i["geekCard"]["lowSalary"] # 最低要求工资
highSalary = i["geekCard"]["highSalary"] # 最高要求工资
"""三个动作1. 找到姓名 2. 滚动到那里 3. 点击打招呼"""
try:
container = page.get_frame("recommendFrame")
except Exception:
container = page
# 1. 找到这个姓名
2026-03-06 01:33:11 +08:00
name_ele = container.ele(f'x://span[contains(text(),"{geekName}")]', timeout=5)
2026-03-06 00:43:40 +08:00
if not name_ele:
name_ele = container.ele(f'x://span[text()="{geekName}"]', timeout=2)
if not name_ele:
raise Exception(f"未找到姓名:{geekName}")
# 2. 滚动到那里
name_ele.run_js("this.scrollIntoView({block: 'center', behavior: 'auto'})")
time.sleep(0.8)
# 3. 点击打招呼(先在该人所在卡片内找)
parent = name_ele.parent()
greet_btn = None
for _ in range(8):
if not parent:
break
2026-03-06 01:33:11 +08:00
greet_btn = parent.ele('x://span[text()="打招呼"]', timeout=0.5) or parent.ele(
'x://*[contains(text(),"打招呼")]', timeout=0.5)
2026-03-06 00:43:40 +08:00
if greet_btn:
break
parent = parent.parent()
if not greet_btn:
2026-03-06 01:33:11 +08:00
greet_btn = container.ele('x://span[text()="打招呼"]', timeout=2) or container.ele(
'x://*[contains(text(),"打招呼")]', timeout=1)
2026-03-06 00:43:40 +08:00
if not greet_btn:
raise Exception("未找到「打招呼」按钮")
greet_btn.click(by_js=True)
2026-03-06 01:33:11 +08:00
def main1():
if USE_LOCAL_CHROME:
page = _connect_local_chrome()
else:
page = _connect_bit_browser()
page.listen.start('wapi/zpblock/recommend/filters')
# 示例:打开一个页面(可选)
page.get("https://www.zhipin.com/web/chat/recommend")
res = page.listen.wait()
filters = {}
for i in res.response.body["zpData"]["vipFilter"]["filters"]:
print(i)
if i["name"] == "年龄":
print(i["start"])
print(i["end"])
filters[i["name"]] = range(int(i["start"]), int(i["end"]) + 1)
else:
datas = []
for i1 in i["options"]:
print(i1["name"])
datas.append(i1["name"])
filters[i["name"]] = datas
print(filters)
def main2(page, filters):
"""在同一 page 上打开推荐页、点筛选、选条件、点确定;点击确定后会触发 wapi/zpjob/rec/geek/list由 main() 的 listen 捕获。"""
page.get("https://www.zhipin.com/web/chat/recommend")
page.ele("x://*[contains(text(),'筛选')]").click()
time.sleep(3)
for i in filters:
page.ele(f"x://*[contains(text(),'{i}')]").click()
time.sleep(random.random() * 2)
page.ele("x://*[contains(text(),'确定')]").click()
2026-03-06 00:43:40 +08:00
if __name__ == "__main__":
2026-03-06 01:33:11 +08:00
main(filters=["初中及以下", '离职-随时到岗'])
# main1()
# main2()