Metadata-Version: 2.1
Name: dlm-li-cat
Version: 0.1.1
Summary: LinkedIn Search CLI - 基于 Typer 的 LinkedIn 搜索功能管理和执行工具
Author-email: Chandler <275737875@qq.com>
License: MIT
Requires-Python: >=3.7
Description-Content-Type: text/markdown
Requires-Dist: typer >=0.9.0
Requires-Dist: rich >=12.0.0
Requires-Dist: django <2,>=1.11
Requires-Dist: redis <5,>=4.0
Requires-Dist: requests >=2.31.0
Requires-Dist: pandas >=1.0
Requires-Dist: pymysql <2,>=1.0
Requires-Dist: django-redis <5,>=4.0
Requires-Dist: python-dotenv >=0.19

# dlm-li-cat

LinkedIn Search CLI Tool — 基于 Typer 构建的命令行应用程序，专门用于 LinkedIn 搜索功能的管理和执行。

## 项目概述

`dlm-li-cat` 是一个命令行工具，提供完整的 LinkedIn 搜索任务管理和执行能力。主要包含以下功能：

- **Cookie 管理** — 展示、测试、缓存 LinkedIn Cookie，确保搜索任务有可用账号
- **LinkedIn 搜索** — 根据关键词、地点、公司、职位等条件，遍历 268 个中文姓氏，批量搜索 LinkedIn 用户
- **项目信息查看** — 实时查看数据库中的 Cookie 状态、搜索词数量、候选人总数等统计信息
- **姓氏初始化** — 将配置文件中的姓氏列表写入 Redis，供搜索任务使用

工具使用 Rich 库提供彩色格式化输出、进度条和状态面板，用户体验友好。

## 环境要求

| 要求 | 说明 |
|------|------|
| **Python** | >= 3.7（推荐 3.7 ~ 3.11） |
| **操作系统** | Windows / macOS / Linux |
| **Django** | 1.11.x（项目依赖） |
| **MySQL** | 可访问的 MySQL 数据库（存储候选人数据） |
| **Redis** | 可访问的 Redis 服务（缓存 Cookie 和搜索状态） |
| **配置** | 数据库和 Redis 连接参数在 `django_settings.py` 中直接配置 |

## 安装步骤

### 1. 克隆项目

```bash
git clone <repository_url>
```

项目根目录结构应包含：

```
.
├── dlm-cli/              # dlm-li-cat 包目录（内嵌 linkedin API 模块）
├── web/                  # Django Web 应用（数据模型，运行时依赖）
├── utils/                # 工具模块（独立使用）
├── script/               # 原有脚本（独立使用）
├── django_settings.py    # Django 配置
└── requirements.txt      # Python 依赖
```

### 2. 安装系统依赖

确保已安装 MySQL 客户端库和 Redis 服务（如果是远程连接则无需本地安装）。

对于 Windows，安装 `pymysql` 即可满足 MySQL 连接需求，已在依赖中处理。

### 3. 使用 pip 安装

此方式将包以可编辑模式安装到当前 Python 环境，修改源码即时生效。

#### 从 PyPI 安装

```bash
pip install dlm-li-cat
```

### 4. 安装项目依赖

在项目根目录执行：

```bash
pip install -r requirements.txt
```

`requirements.txt` 包含以下核心依赖：

| 包 | 版本 | 用途 |
|------|---------|---------|
| Django | 1.11.29 | Web 框架、ORM、数据模型 |
| redis | 4.3.1 | Redis 缓存操作 |
| pymysql | >=1.0,<2.0 | MySQL 数据库驱动 |
| django-redis | >=4.0,<5.0 | Django Redis 缓存后端 |
| requests | 2.31.0 | HTTP 请求（LinkedIn API） |

### 5. 安装 typer 和 rich

`dlm-li-cat` 依赖 `typer` 和 `rich` 两个核心库。如果 pip 安装因 SSL 问题失败，推荐使用 conda 安装：

```bash
# 使用 conda-forge 通道安装（推荐，可避免 SSL 问题）
conda install -c conda-forge typer rich
```

或使用 pip：

```bash
pip install typer rich
```

### 6. 在 conda 环境中安装

```bash
# 创建 conda 环境
conda create -n linkedin_search python=3.7
conda activate linkedin_search

# 安装核心依赖（优先使用 conda）
conda install -c conda-forge typer rich

# 安装项目依赖
pip install -r requirements.txt



> **注意**：在 conda 环境中，如果遇到 pip SSL 错误，请优先使用 `conda install -c conda-forge` 安装包，而非 pip。

### 7. 配置数据库和 Redis 连接信息

数据库和 Redis 连接信息已在 `django_settings.py` 中预配置（详见下方[配置说明](#%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E)）。

## 配置说明

> **包内已内置默认配置**，当未找到项目级别的 `django_settings.py` 时自动回退使用。
> 优先使用项目根目录下的自定义配置（可通过 `--project-dir` 或 `DLM_CLI_PROJECT_DIR` 指定）。

所有数据库和 Redis 连接参数直接在 `django_settings.py` 中配置：

| 配置项 | 说明 | 默认值 |
|--------|------|--------|
| DATABASES | MySQL 连接（host、port、db、user、password） | host: `127.0.0.1`, db: `dlm` |
| REDIS_HOST | Redis 服务器地址 | `127.0.0.1` |
| REDIS_PASSWORD | Redis 密码 | `8899782song` |
| CACHES | Django Redis 缓存后端（连接池配置） | 基于 REDIS_HOST 和 REDIS_PASSWORD |

> 如需修改连接参数，直接编辑 `django_settings.py` 中的对应值即可。

---

### 项目路径探测

`dlm-li-cat` 会自动从当前工作目录向上查找包含 `django_settings.py` 的项目根目录。如果自动探测失败，可通过以下方式指定：

1. **`--project-dir` / `-d` 参数**：在每个命令中手动指定项目路径
2. **`DLM_CLI_PROJECT_DIR` 环境变量**：设置后无需每次指定

```bash
# 方式一：参数指定
dlm-li-cat --project-dir D:\LLMCode\2026\20260517 info

# 方式二：环境变量（推荐）
set DLM_CLI_PROJECT_DIR=D:\LLMCode\2026\20260517
dlm-li-cat info
```

### 姓氏列表

配置文件的 `FAMILY_NAMES` 定义了搜索时遍历的姓氏（共 268 个），包括单姓和复姓（如欧阳、百里、第五等）。可通过 `dlm-li-cat init-names` 命令同步到 Redis。

> **提示**：姓氏列表定义在 `django_settings.py` 的 `FAMILY_NAMES` 常量中，如需修改可在该文件中调整。

## 使用方法

### 全局帮助

```bash
dlm-li-cat --help
```

输出：

```
 Usage: dlm-li-cat [OPTIONS] COMMAND [ARGS]...

 dlm-li-cat - LinkedIn Search CLI Tool

 提供完整的 LinkedIn 搜索任务管理和执行能力。

 Options:
   -V, --version              显示版本信息
   -d, --project-dir TEXT     项目根目录路径（默认自动探测）[envvar: DLM_CLI_PROJECT_DIR]
   --help                     Show this message and exit.

 Commands:
   cookies      Cookie 管理：展示、测试、更新缓存
   init-names   初始化 Redis 中的家族姓氏列表
   info         显示项目环境信息
   search       执行 LinkedIn 搜索任务
```

### 查看版本

```bash
dlm-li-cat --version
```

输出：

```
dlm-li-cat v0.1.0
```

### `dlm-li-cat info` — 显示项目信息

查看项目的数据库连接状态、Redis 状态、Cookie 数量等关键统计信息。

```bash
dlm-li-cat info
```

示例输出：

```
┌─────────────────────────── 📊 项目信息 ───────────────────────────┐
│ 指标                     │ 数值                                   │
├───────────────────────────┼────────────────────────────────────────┤
│ 项目路径                 │ D:\LLMCode\2026\20260517               │
│ Cookie 总数              │ 153                                    │
│ 有效 Cookie              │ 139                                    │
│ 搜索词数                 │ 2577                                   │
│ 候选人总数               │ 1,344,180                              │
│ 待执行任务               │ 19597                                  │
│ 已完成任务               │ 31146                                  │
└────────────────────────────────────────────────────────────────────┘
┌──────────────┐
│ ✅ 环境正常  │
│ Django 配置、Redis 连接、数据库连接均正常。│
└──────────────┘
```

### `dlm-li-cat cookies show` — 显示 Cookie 列表

显示数据库中所有 Cookie 的详细信息，包括用户名、LinkedIn 名称、状态、活跃度等。

```bash
# 显示所有 Cookie（默认包含无效的）
dlm-li-cat cookies show

# 仅显示无效 Cookie
dlm-li-cat cookies show --show-invalid

# 以 JSON 格式输出
dlm-li-cat cookies show --json
```

参数说明：

| 参数 | 缩写 | 类型 | 说明 |
|------|------|------|------|
| `--show-invalid` | | flag | 显示已失效的 Cookie（默认全部显示） |
| `--json` | `-j` | flag | 以 JSON 格式输出 |

示例输出（表格格式）：

```
┌────────────────────────────── 📋 Cookie 列表 ──────────────────────────────┐
│ ID │ 用户名       │ LinkedIn 名称      │ 状态(模型) │ 活跃    │ 创建日期    │
├────┼──────────────┼────────────────────┼────────────┼─────────┼─────────────┤
│ 1  │ chandler     │ Chandler Liu       │ ✅ 有效    │ ✅      │ 2025-06-15  │
│ 2  │ alice        │ Alice Wang         │ ❌ 无效    │ ✅      │ 2025-07-20  │
│ 3  │ bob          │ Bob Zhang          │ ✅ 有效    │ ✅      │ 2025-08-01  │
│ ...│ ...          │ ...                │ ...        │ ...     │ ...         │
└────────────────────────────────────────────────────────────────────────────┘
总计: 153 条 Cookie 记录
```

### `dlm-li-cat cookies test` — 测试 Cookie 有效性

逐一测试数据库中 Cookie 的有效性，通过网络请求验证 LinkedIn 账号状态。

```bash
# 测试所有 Cookie
dlm-li-cat cookies test

# 测试指定 ID 的 Cookie
dlm-li-cat cookies test --cookie-ids 1,2,3

# 调整并发数
dlm-li-cat cookies test --concurrency 20
```

参数说明：

| 参数 | 缩写 | 类型 | 默认值 | 说明 |
|------|------|------|--------|------|
| `--cookie-ids` | `-i` | TEXT | 全部 | 指定要测试的 Cookie ID，逗号分隔 |
| `--concurrency` | `-c` | INT | 10 | 并发测试线程数（1~50） |

示例输出：

```
🔍 开始测试 153 个 Cookie 的有效性...

测试 Cookie... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 153/153

┌──────────────────────────── 📊 Cookie 测试结果 ────────────────────────────┐
│ ID │ 用户名       │ LinkedIn 名称      │ 状态    │ 错误信息                    │
├────┼──────────────┼────────────────────┼─────────┼─────────────────────────────┤
│ 1  │ chandler     │ Chandler Liu       │ ✅ 有效  │                             │
│ 2  │ alice        │ Alice Wang         │ ❌ 无效  │ 接口返回状态码: 401         │
│ 3  │ bob          │ Bob Zhang          │ ✅ 有效  │                             │
└────────────────────────────────────────────────────────────────────────────┘
┌───────────────────────────── 📈 测试汇总 ─────────────────────────────┐
│  ✅ 有效: 139    ❌ 无效: 14    总计: 153                            │
└───────────────────────────────────────────────────────────────────────┘
```

### `dlm-li-cat cookies update` — 更新 Redis 缓存

将验证通过的 Cookie 安全地存储到 Redis 缓存中，供搜索任务使用。

```bash
# 先测试再缓存（默认行为）
dlm-li-cat cookies update

# 跳过测试，直接缓存所有 Cookie
dlm-li-cat cookies update --skip-test

# 指定要缓存的 Cookie
dlm-li-cat cookies update --cookie-ids 1,3,5

# 调整并发测试数
dlm-li-cat cookies update --concurrency 20
```

参数说明：

| 参数 | 缩写 | 类型 | 默认值 | 说明 |
|------|------|------|--------|------|
| `--cookie-ids` | `-i` | TEXT | 全部有效 | 指定要缓存的 Cookie ID，逗号分隔 |
| `--skip-test` | | flag | False | 跳过有效性测试，直接缓存 |
| `--concurrency` | `-c` | INT | 10 | 并发测试线程数（1~50） |

更新完成后，Redis 中会存储两个 Key：

| Redis Key | 类型 | 说明 |
|-----------|------|------|
| `linkedin_cookies` | List | 有效 Cookie ID 列表（按序存储） |
| `COOKIES_LIST_SET` | Set | 有效 Cookie ID 集合 |

示例输出：

```
┌─────────── 📦 缓存更新结果 ───────────┐
│                                       │
│  ✅ 缓存更新完成                      │
│                                       │
│  • 有效 Cookie 数: 139                │
│  • Redis Key (list): linkedin_cookies │
│  • Redis Key (set):  COOKIES_LIST_SET │
└───────────────────────────────────────┘
```

### `dlm-li-cat search` — 执行 LinkedIn 搜索

执行完整的 LinkedIn 搜索任务，遍历姓氏列表搜索候选人。

```bash
# 基本用法（必须指定关键词）
dlm-li-cat search --keyword "Nvidia"

# 完整参数
dlm-li-cat search \
    --keyword "Software Engineer" \
    --location 103644278 \
    --job-title "Engineer OR Scientist" \
    --company "Nvidia" \
    --university "Stanford" \
    --family-name "wang" \
    --network F \
    --user-id 2 \
    --max-results 1000 \
    --cookie 1
```

参数说明：

| 参数 | 缩写 | 类型 | 必需 | 默认值 | 说明 |
|------|------|------|------|--------|------|
| `--keyword` | `-k` | TEXT | **是** | - | 搜索关键词，如公司名、职位名 |
| `--location` | `-l` | TEXT | 否 | 空 | 地理位置编码，如 `103644278`（美国） |
| `--job-title` | `-t` | TEXT | 否 | 空 | 职位关键词，支持 `OR` 逻辑 |
| `--company` | `-c` | TEXT | 否 | 空 | 公司名称 |
| `--university` | `-u` | TEXT | 否 | 空 | 学校名称 |
| `--family-name` | `-f` | TEXT | 否 | 空 | 指定搜索的姓氏，留空则遍历全部 |
| `--network` | `-n` | TEXT | 否 | 空 | 人脉范围：`F`=好友，`O`=非好友，留空=所有人 |
| `--user-id` | | INT | 否 | 2 | 用户 ID，用于关联搜索数据 |
| `--max-results` | `-m` | INT | 否 | 1000 | 每个姓氏最多获取的结果数 |
| `--cookie` | | INT | 否 | 随机选取 | 指定使用特定的 Cookie ID（v0.2.0 新增） |

> **注意**：`--network` 参数仅接受 `F`（好友）、`O`（非好友）或留空（所有人）。

搜索流程：

1. 初始化 Django 和 Redis 连接
2. 将姓氏列表写入 Redis（如果尚未初始化，可先运行 `dlm-li-cat init-names`）
3. 从 Redis 读取可用 Cookie 列表
4. 格式化搜索参数
5. 遍历姓氏，对每个姓氏执行搜索
6. 创建 `SearwordChineseTask` 任务记录
7. 搜索进度自动保存，支持断点续搜

示例输出：

```
┌────────────────────────── 📋 搜索参数 ──────────────────────────┐
│  🔍 LinkedIn 搜索任务                                           │
│                                                                 │
│  • 关键词:    Nvidia                                             │
│  • 地点:      103644278                                         │
│  • 职位:      (空)                                              │
│  • 公司:      (空)                                              │
│  • 大学:      (空)                                              │
│  • 姓氏:      (空)                                              │
│  • 人脉:      (空)                                              │
└─────────────────────────────────────────────────────────────────┘

✅ 已加载 268 个姓氏到 Redis
✅ 找到 139 个可用 Cookie

执行搜索... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 268/268

  ✅ 姓氏 'wang': 页面 5, 总数 45 (1/268)
  ✅ 姓氏 'li': 页面 8, 总数 72 (2/268)
  ✅ 姓氏 'zhang': 页面 3, 总数 28 (3/268)
  ...

┌─────────────────────────── 📊 搜索结果 ──────────────────────────┐
│  ✅ 搜索任务完成                                                 │
│                                                                  │
│  • 搜索词:     keyword:Nvidia_CN_NAME                            │
│  • 待执行任务: 356                                               │
│  • 已完成任务: 0                                                 │
│  • 姓氏范围:   268 个                                            │
└──────────────────────────────────────────────────────────────────┘
```

### `dlm-li-cat init-names` — 初始化姓氏列表

将 `django_settings.py` 中的 `FAMILY_NAMES` 姓氏列表写入 Redis，供搜索任务遍历使用。

```bash
dlm-li-cat init-names
```

示例输出：

```
┌────────────── 📝 初始化完成 ──────────────┐
│                                           │
│  ✅ 家族姓氏已成功写入 Redis              │
│                                           │
│  • Redis Key: name                        │
│  • 姓氏数量:  268 个                      │
│  • 范围:      wang ~ zeng                │
└───────────────────────────────────────────┘
```

## 快捷键（别名）

`dlm-li-cat` 提供了两个入口点命令：

```bash
# 完整命令
dlm-li-cat [command] [options]

# 简短别名
dlm [command] [options]
```

两个命令完全等价，可以根据习惯选择使用。

```bash
dlm info
dlm cookies show
dlm search --keyword "Google"
```

## 故障排除

### 1. 找不到项目配置文件

**错误信息**：`❌ 无法找到项目配置文件`

**解决方案**：

```bash
# 在项目根目录下执行
cd D:\LLMCode\2026\20260517

# 或指定项目路径
dlm-li-cat --project-dir D:\LLMCode\2026\20260517 info

# 或设置环境变量
set DLM_CLI_PROJECT_DIR=D:\LLMCode\2026\20260517
```

### 2. Django 导入失败

**错误信息**：`❌ Django 导入失败: No module named django`

**解决方案**：

```bash
# 确认已激活正确的 Python 环境
python --version

# 安装依赖
pip install -r requirements.txt
```

### 3. Redis 连接失败

**错误信息**：`❌ Redis 连接失败`

**解决方案**：

- 确认 Redis 服务是否正常运行
- 检查 `django_settings.py` 中的 `REDIS_HOST` 和 `REDIS_PASSWORD` 配置是否正确
- 确认网络可以访问 Redis 服务器（如果是远程 Redis）

### 4. MySQL 连接失败

**错误信息**：`❌ django.db.utils.OperationalError: (2003, "Can't connect to MySQL server")`

**解决方案**：

- 确认 MySQL 服务是否正常运行
- 检查 `django_settings.py` 中的数据库配置
- 确认网络可以访问 MySQL 服务器
- 确保 `pymysql` 已安装：`pip install pymysql`

### 5. Cookie 测试全部失败

**错误信息**：`❌ 无效: 153` 等全部失败结果

**解决方案**：

- 检查 LinkedIn 账号是否过期（LI_AT 和 JSESSIONID 通常在 1 年后过期）
- 确认 Redis 中存在 Cookie 数据
- 尝试重新登录 LinkedIn 并更新 Cookie

### 6. 搜索无结果

**问题描述**：搜索完成后待执行任务数为 0

**可能原因**：

- Cookie 已失效，无法通过 LinkedIn API 获取数据
- 搜索条件过于严格，无匹配用户
- LinkedIn API 返回空结果

### 7. conda 环境下 pip SSL 错误

**错误信息**：`Could not fetch URL https://pypi.org/simple/... There was a problem confirming the ssl certificate`

**解决方案**：

```bash
# 优先使用 conda 安装
conda install -c conda-forge <package_name>

# 或使用 --trusted-host 参数
pip install <package_name> --trusted-host pypi.org --trusted-host files.pythonhosted.org
```

### 8. 模块未找到

**错误信息**：`ModuleNotFoundError: No module named 'dlm_cli'`

**解决方案**：

```bash
# 确认已安装 dlm-li-cat
pip list | findstr dlm-li-cat  # Windows
# 或
pip list | grep dlm-li-cat     # Linux/macOS

```

### 9. "No pyvenv.cfg file" 错误

**错误信息**：`Fatal error in launcher: Unable to create process using '"..."' No pyvenv.cfg file`

**解决方案**：

- 该错误通常由损坏的虚拟环境引起
- 删除项目目录下的 `venv/` 目录（如果存在）
- 确保使用正确的 Python 环境执行命令

## 注意事项

### 数据库连接

- 本项目使用远程 MySQL 数据库，请确保网络连接稳定
- 候选人表 `CandidateList` 已有超过 134 万条记录，查询和写入时注意性能
- 不要在高峰时段执行大规模搜索任务，避免对数据库造成压力

### Redis 连接

- Redis 用于存储 Cookie 缓存和搜索进度状态
- 搜索过程中会在 Redis 中记录当前进度，支持断点续搜
- 如果 Redis 连接中断，搜索任务将无法继续
- 搜索完成后 Redis 中的进度数据会被保留，如需重新搜索需手动清除

### Cookie 管理

- LinkedIn Cookie（LI_AT 和 JSESSIONID）通常有效期为 1 年左右
- 建议定期使用 `dlm-li-cat cookies test` 检查 Cookie 有效性
- 使用 `dlm-li-cat cookies update` 将有效 Cookie 同步到 Redis
- 搜索任务会自动从 Redis 随机选取 Cookie，避免单个账号请求过于频繁

### 搜索任务

- 搜索会遍历 268 个姓氏，每个姓氏都会发起一次请求
- 请求间隔固定为 2 秒，避免触发 LinkedIn 反爬机制
- 搜索结果以 `SearwordChineseTask` 记录保存，状态包括"待执行"和"已完成"
- 如果搜索词已存在且进度为 100%，工具会自动跳过，避免重复搜索
- 支持断点续搜：如果搜索中断，重新执行会从上次位置继续

### conda 环境

- 推荐在 conda 环境中运行本项目，便于管理依赖
- 安装依赖时，优先使用 `conda install -c conda-forge`，pip 仅作为备用
- 使用 `pip install` 时若遇 SSL 错误，可使用 `--no-build-isolation` 参数

### 安全

- 数据库和 Redis 密码等敏感信息直接配置在 `django_settings.py` 中，请勿将该文件提交到公共版本控制系统
- **dlm-li-cat v0.2.0 起内置默认配置**，当未找到项目级 `django_settings.py` 时自动回退使用包内配置
- 如需自定义配置，可通过 `--project-dir` 参数或 `DLM_CLI_PROJECT_DIR` 环境变量指定包含 `django_settings.py` 的目录
- LinkedIn Cookie 涉及账号安全，请勿泄露



