Metadata-Version: 2.4
Name: maimai_cat
Version: 0.1.2
Summary: A Python API wrapper for maimai (脉脉) platform, supporting talent search, profile retrieval, group management, bookmarking, and recruitment workflow automation.
Author-email: Chandler <275737875@qq.com>
License-Expression: MIT
Keywords: maimai,api,tool
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Natural Language :: Chinese (Simplified)
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests
Requires-Dist: colorama
Dynamic: license-file

# maimai_cat

`maimai_cat` 是脉脉（maimai）平台的 Python API 封装工具库，提供候选人搜索、详情查询、分组管理、星标、点评、联系记录、项目关联、备注、统计数据、标签、动态及求职意向等完整功能，帮助招聘团队高效管理人才资源。

---

## 功能特性

- **候选人搜索**：按关键词搜索候选人，支持分页，结果可打印或保存到本地
- **候选人详情**：获取基本简历信息（姓名、公司、职位、教育经历等）
- **点评列表**：查看其他人对候选人的点评内容
- **联系记录**：获取团队成员与候选人的历史联系记录
- **项目关联**：查询候选人所在的招聘项目列表
- **同事备注**：获取团队成员对候选人的备注信息
- **统计数据**：查看候选人的查看次数、沟通次数等综合指标
- **个人标签**：获取候选人的平台标签信息
- **动态记录**：获取候选人的查看记录与消息动态
- **求职意向**：查询候选人的看机会状态与期望岗位
- **分组管理**：创建、查询、删除分组，将候选人添加到指定分组
- **星标管理**：对候选人进行星标或取消星标
- **好友申请**：向目标用户发送脉脉好友申请
- **搜索自动保存**：关键词全量搜索自动翻页，按 UID 保存候选人为 JSON 文件
- **自定义姓氏批量搜索**：支持自定义姓氏列表进行「公司 + 姓氏」组合批量搜索

---

## 安装和环境配置

### 安装

```shell
pip install maimai_cat
```

### 前置条件：导出脉脉 Cookie

`maimai_cat` 通过 Cookie 完成身份认证，使用前需导出你的脉脉登录 Cookie：

1. 在 Chrome 浏览器中登录 [maimai.cn](https://maimai.cn)
2. 安装 Chrome 扩展 [EditThisCookie](https://chrome.google.com/webstore/detail/editthiscookie/fngmhnnpilhplaeedifhccceomclgfbg)
3. 打开脉脉任意页面，点击 EditThisCookie 图标，选择 **导出** → 导出为 JSON 格式
4. 将导出的内容保存为 `cookies.json` 文件，放置在你的脚本同级目录

> **注意**：Cookie 具有时效性，若请求返回未登录错误，请重新导出 Cookie。

---

## 使用示例

### 初始化

```python
from maimai.api import MaimaiAPI

# 默认读取同目录下的 cookies.json
api = MaimaiAPI().connect()
```

如果 `cookies.json` 不在脚本同级目录，可在 `LoginManager` 中指定路径（或子类传入）：

```python
# 目前通过直接修改 cookies_file 路径实现
from maimai.api import MaimaiAPI, Group, User, Search

group = Group(cookies_file="/path/to/cookies.json")
```

---

### 候选人搜索

```python
# 关键词搜索，page 从 0 开始，最大 30 页
result = api.search.keyword("LLM", page=0)
api.pretty_print(result)

# 搜索并在控制台格式化打印每位候选人信息
api.search.extract_search_result(api.search.keyword("Google", page=0))

# 搜索并将每位候选人数据保存为 JSON 文件到 ./profile_data 目录
api.search.save_search_result(api.search.keyword("Google", page=0), folder="./profile_data")

# 使用 search_api 接口搜索（另一种搜索方式，返回联系人列表）
contacts = api.search.search_api(keyword="张三", page=1)
print(contacts)

# 搜索并保存到本地文件夹
api.search.search_api_save_file(keyword="张三", page=1, folder="./search_api")

# 查询某关键词搜索结果总数
total = api.search.search_api_total_page(keyword="LLM")
print(f"搜索总条数: {total}")
```

---

### 候选人详情

```python
uid = 41962985
trackable_token = "xxxxxx"
# 获取候选人基本简历（姓名、公司、职位、教育经历等）
api.pretty_print(api.user.read(uid,trackable_token))

# 获取其他人对该候选人的点评列表
api.pretty_print(api.user.get_comments(uid))

# 获取团队成员与该候选人的联系记录
api.pretty_print(api.user.get_contact_status(uid))

# 获取候选人所在的招聘项目列表
api.pretty_print(api.user.get_projects(uid))

# 获取团队成员对该候选人的备注（page 从 0 开始，size 每页条数）
api.pretty_print(api.user.get_remarks(uid, page=0, size=5))

# 获取候选人综合统计数据（查看次数、沟通次数等）
api.pretty_print(api.user.get_stats(uid))

# 获取候选人的个人标签列表
api.pretty_print(api.user.get_tags(uid))

# 获取候选人的查看记录与消息动态
api.pretty_print(api.user.get_dynamic(uid))

# 获取候选人的求职意向（看机会状态、期望岗位等）
api.pretty_print(api.user.get_job_preference(uid, page=0, size=20))
```

---

### 分组管理

```python
# 创建新分组
api.pretty_print(api.group.create("LLM"))

# 查询所有分组列表（默认返回最多 100 个）
api.pretty_print(api.group.read())

# 将候选人添加到指定分组（user_group_ids 为分组 ID 列表）
uid = 123456
group_id = 123456
api.pretty_print(api.group.add_user_to_group(uid=uid, user_group_ids=[group_id]))

# 删除指定分组
api.pretty_print(api.group.delete(group_id=123456))
```

---

### 星标管理

```python
uid = 123456
# 星标候选人
api.pretty_print(api.group.star(uid))

# 取消星标
api.pretty_print(api.group.unstar(uid))
```

---

### 好友申请

```python
# 向指定用户发送好友申请
uid = 123456
api.pretty_print(api.message.add_friend(uid))
```

---

### Demo：关键词全量搜索（自动翻页）

`search_keyword_all_pages` 自动从第 0 页开始遍历所有结果页，每页等待指定秒数后翻页，结果格式化打印到控制台。

```python
from maimai.api import MaimaiAPI
from maimai.demo.search_demo import search_keyword_all_pages

api = MaimaiAPI().connect()

# 搜索「大模型 训练」，每页间隔 5 秒，结果保存到 ./results 目录
# 预期输出：逐页打印候选人姓名、公司、职位等信息
# 当所有页面遍历完毕后打印「已遍历所有页面，搜索完成」
search_keyword_all_pages(api, keyword="大模型 算法", delay=5, folder="./results")
```

参数说明：

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `api` | MaimaiAPI | — | 已初始化的 API 实例 |
| `keyword` | str | — | 搜索关键词 |
| `delay` | int | 5 | 翻页间隔秒数，建议 ≥ 3 |
| `folder` | str | `""` | 结果保存目录，为空则不保存 |

---

### Demo：公司 + 百家姓批量搜索（断点续传）

`company_family_search` 通过「公司名 + 百家姓」穷举组合搜索目标公司员工，支持断点续传，不重复请求已完成的关键词。

```python
from maimai.api import MaimaiAPI
from maimai.demo.search_demo import company_family_search

api = MaimaiAPI().connect()

# 搜索字节跳动员工，结果保存到 ./google 目录
# 断点日志记录到 google_log.txt，每次请求随机等待 3~8 秒
# 预期输出：[搜索] Goolge 赵 第 1 页 → 保存 {uid}.json
# 若中断后重新运行，已处理的关键词会自动跳过
company_family_search(
    api,
    company_name="Google",
    folder="./google",
    log_file="google_log.txt",
    delay_range=(3, 8),
)

# 搜索某公司员工（使用默认参数）
company_family_search(api, company_name="Google", folder="./google")

# 使用自定义姓氏列表搜索
company_family_search(
    api,
    company_name="google",
    family_names=["张", "王", "李"],
    folder="./google",
)
```

参数说明：

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `api` | MaimaiAPI | — | 已初始化的 API 实例 |
| `company_name` | str | `"Google"` | 目标公司名称 |
| `folder` | str | `"./search_result"` | 搜索结果保存目录 |
| `log_file` | str | `"log.txt"` | 断点续传日志文件路径 |
| `delay_range` | tuple | `(3, 8)` | 每次请求随机等待区间（秒） |
| `family_names` | list | `None` | 自定义姓氏列表，未传入时使用默认百家姓 |

---

### Demo：从本地文件夹批量获取完整简历

`fetch_profiles_from_folder` 读取 `company_family_search` 生成的本地 JSON 文件，按公司名过滤后，批量调用 API 获取完整简历并保存，自动跳过已下载的文件。

```python
from maimai.api import MaimaiAPI
from maimai.demo.profile_demo import fetch_profiles_from_folder

api = MaimaiAPI().connect()

# 从 ./google 文件夹读取，仅处理公司字段包含「Google」的用户
# 完整简历保存到 ./google_profiles，每次请求间隔 3 秒
# 预期输出：[匹配] 姓名: 张三 | 公司: Google | UID: 12345678
#           [保存] 12345678.json 保存成功（共保存 N 份）
fetch_profiles_from_folder(
    api,
    folder_path="./google",
    save_folder="./google_profiles",
    company_filter="Google",
    delay=3,
)

# 不设置 company_filter，处理文件夹中全部用户
fetch_profiles_from_folder(
    api,
    folder_path="./google",
    save_folder="./google_profiles",
)
```

参数说明：

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `api` | MaimaiAPI | — | 已初始化的 API 实例 |
| `folder_path` | str | — | 本地搜索结果 JSON 文件所在目录 |
| `save_folder` | str | `"./profiles"` | 完整简历保存目录 |
| `company_filter` | str | `""` | 公司名过滤关键词，为空则处理全部 |
| `delay` | int | 3 | 每次请求间隔秒数，建议 ≥ 2 |

---

## API 接口说明

### `api.user` — 候选人相关

| 方法 | 参数 | 说明 |
|------|------|------|
| `read(to_uid)` | `to_uid: int` | 获取候选人基本简历信息 |
| `get_comments(user_id)` | `user_id: int` | 获取其他人对候选人的点评列表 |
| `get_contact_status(to_uid)` | `to_uid: int` | 获取团队成员与候选人的联系记录 |
| `get_projects(to_uid)` | `to_uid: int` | 获取候选人关联的招聘项目列表 |
| `get_remarks(to_uid, page, size)` | `to_uid: int`, `page: int=0`, `size: int=5` | 获取团队成员对候选人的备注列表 |
| `get_stats(to_uids)` | `to_uids: int` | 获取候选人综合统计数据 |
| `get_tags(tagu)` | `tagu: int` | 获取候选人的个人标签信息 |
| `get_dynamic(to_uids)` | `to_uids: int` | 获取候选人的查看记录与消息动态 |
| `get_job_preference(to_uid, page, size)` | `to_uid: int`, `page: int=0`, `size: int=20` | 获取候选人的求职意向 |

### `api.group` — 分组管理

| 方法 | 参数 | 说明 |
|------|------|------|
| `create(name)` | `name: str` | 创建新分组 |
| `read(page, size)` | `page: int=0`, `size: int=100` | 查询分组列表 |
| `delete(group_id)` | `group_id: int` | 删除指定分组 |
| `add_user_to_group(uid, user_group_ids)` | `uid: int`, `user_group_ids: list` | 将候选人添加到分组 |
| `star(uid)` | `uid: int` | 星标候选人 |
| `unstar(uid)` | `uid: int` | 取消星标候选人 |

### `api.search` — 搜索相关

| 方法 | 参数 | 说明 |
|------|------|------|
| `keyword(keyword, page, **kwargs)` | `keyword: str`, `page: int=0` | 企业版关键词搜索 |
| `search_api(keyword, page, user)` | `keyword: str`, `page: int=1` | 公开搜索接口 |
| `search_api_save_file(keyword, page, user, folder)` | `keyword: str`, `folder: str` | 搜索并保存结果到本地 |
| `search_api_total_page(keyword, page, user)` | `keyword: str` | 查询搜索结果总条数 |
| `extract_search_result(json_data)` | `json_data: dict` | 在控制台格式化打印搜索结果 |
| `save_search_result(json_data, folder)` | `json_data: dict`, `folder: str` | 将搜索结果保存为本地 JSON 文件 |

### `api.message` — 消息与好友

| 方法 | 参数 | 说明 |
|------|------|------|
| `add_friend(to_uids)` | `to_uids: int\|str` | 向目标用户发送好友申请 |

---

## 免责声明

1. **本工具仅供学习交流使用**，不作为任何商业用途。
2. **禁止用于任何未经授权的数据爬取、抓取行为**，请严格遵守脉脉平台的用户协议及相关法律法规。
3. **使用者需自行承担所有法律责任**，因使用本工具产生的任何后果与开发者无关。
4. **开发者不对任何不当使用造成的后果负责**，包括但不限于账号封禁、数据泄露、法律纠纷等。

---

## 贡献指南与许可证

### 贡献指南

欢迎提交 Issue 或 Pull Request。贡献代码时请确保：

1. 代码符合 Python PEP 8 规范
2. 新增方法须包含完整的中文 docstring（参数类型、返回值说明）
3. 提交前在本地完成基本功能测试

### 许可证

本项目基于 [MIT License](LICENSE) 开源，允许自由使用、修改和分发。
