Metadata-Version: 2.4
Name: spiderWei-TecDo
Version: 2.1.0
Summary: 爬虫脚手架框架 - 快速创建和运行爬虫任务
Author: Spider Team
License-Expression: MIT
Project-URL: Homepage, https://github.com/your-org/spiderWei-TecDo
Keywords: spider,crawler,framework,scraping
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
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: Topic :: Internet :: WWW/HTTP :: Indexing/Search
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.25.0
Provides-Extra: db
Requires-Dist: psycopg>=3.0.0; extra == "db"
Provides-Extra: kafka
Requires-Dist: kafka-python>=2.0.0; extra == "kafka"
Provides-Extra: video
Requires-Dist: yt-dlp>=2023.0.0; extra == "video"
Provides-Extra: obs
Requires-Dist: esdk-obs-python>=3.0.0; extra == "obs"
Provides-Extra: oss
Requires-Dist: oss2>=2.15.0; extra == "oss"
Provides-Extra: all
Requires-Dist: psycopg>=3.0.0; extra == "all"
Requires-Dist: kafka-python>=2.0.0; extra == "all"
Requires-Dist: yt-dlp>=2023.0.0; extra == "all"
Requires-Dist: esdk-obs-python>=3.0.0; extra == "all"
Requires-Dist: oss2>=2.15.0; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: black>=22.0.0; extra == "dev"

# spiderWei_TecDo 爬虫框架 v2.1.0

快速创建和运行爬虫任务的脚手架框架。

## 功能特性

- 命令行一键生成爬虫脚手架，统一项目结构与入口
- 统一配置管理（Apollo / 本地直配），支持配置覆盖与环境切换
- 内置数据库、Kafka、OBS/OSS、代理、下载队列等能力
- 支持并发执行与循环执行（按间隔 / 每日时间点）
- 重型依赖懒加载，按需安装（仅 requests 为必装依赖）
- 线程安全的数据库客户端与计数器
- 标准 logging 日志系统
- 信号处理支持优雅退出

## 安装

运行环境要求：Python >= 3.8

```bash
# 基础安装（仅含 HTTP 请求能力）
pip install spiderWei-TecDo

# 按需安装额外功能
pip install "spiderWei-TecDo[db]"      # 数据库 (psycopg)
pip install "spiderWei-TecDo[kafka]"   # Kafka
pip install "spiderWei-TecDo[video]"   # 视频提取 (yt-dlp)
pip install "spiderWei-TecDo[obs]"     # 华为云 OBS
pip install "spiderWei-TecDo[oss]"     # 阿里云 OSS

# 全部安装
pip install "spiderWei-TecDo[all]"

# 开发模式安装（推荐本地开发）
cd spiderWei
pip install -e ".[all]"
```

## 快速开始

### 1. 创建爬虫

```bash
# 在当前目录创建爬虫
spiderWei_TecDo start my_spider

# 在指定目录创建
spiderWei_TecDo start my_spider -o ./spiders
```

### 2. 查看配置说明

```bash
spiderWei_TecDo list
```

### 3. 编辑生成的爬虫文件

打开生成的 `my_spider.py`，修改以下内容：

1. **Apollo 配置** - 在脚本顶部全局获取 Apollo 配置

```python
import os, json, logging
from spiderWei_TecDo import run_spider, SpiderSettings, ConfigHelper

is_test = os.getenv("ISTEST", "1") == "1"

# 获取 Apollo 配置（不需要 Apollo 时改为 apollo = {}）
apollo = ConfigHelper().fetch_apollo_config(
    is_test=is_test,
    apollo_id='Your-Apollo-ID',
    apollo_url_test='http://your-test-apollo.com',
    apollo_url_prod='http://your-prod-apollo.com',
)
```

2. **配置 settings** - 在 settings 中直接引用 `apollo.get("key")`，不想用 Apollo 的配置项直接写值

```python
settings = SpiderSettings(
    apollo_enable=False,             # 已在上方手动获取，无需框架内部重复获取
    configurations=apollo,           # 传入 Apollo 配置，app.configurations 可访问

    thread_num=20,

    # 代理: 从 Apollo 取，或直接写 proxy_list=["ip1:port"]
    enable_proxy=True,
    proxy_list=json.loads(apollo.get("IPlist", "[]")),

    # 数据库: 从 Apollo 取，或直接写 db_host='your-host' ...
    enable_db=True,
    db_host=apollo.get("holoHost", ""),
    db_port=apollo.get("holoPort", ""),
    db_name=apollo.get("holoDBname", ""),
    db_user=apollo.get("holoUser", ""),
    db_password=apollo.get("holoPassword", ""),
    db_table_name='your_table_name',

    # Kafka: 从 Apollo 取，或直接写 kafka_address=["host:9092"]
    enable_kafka=True,
    kafka_address=json.loads(apollo.get("kafkaAddress", "[]")),
    # 关闭 kafka-python 连接 INFO 日志（默认 WARNING；想看详细可设为 logging.INFO；不覆盖则设 None）
    kafka_log_level=logging.WARNING,
    # Kafka 稳定性参数（P0）
    kafka_acks=1,
    kafka_retries=3,
    kafka_linger_ms=50,
    kafka_batch_size=65536,
    kafka_compression_type="gzip",
    kafka_request_timeout_ms=15000,
    kafka_delivery_timeout_ms=30000,
    kafka_max_block_ms=10000,
    # Kafka flush 策略（P1）
    kafka_flush_interval_seconds=2,
    kafka_flush_max_messages=1000,

    # 推送背压（P2）：push_queue 达到上限后，业务线程 put 会阻塞等待
    push_queue_maxsize=5000,

    # OSS: 从 Apollo 取，或直接写 obs_ak='xxx' ...
    enable_obs=True,
    obs_provider='aliyun',
    obs_ak=apollo.get("AliOSS_AK", ""),
    obs_sk=apollo.get("AliOSS_SK", ""),
    obs_endpoint=apollo.get("AliOSS_Endpoint", ""),
    obs_bucket_name=apollo.get("AliOSS_BucketName", ""),
    obs_link_prefix=apollo.get("AliOSS_Link", ""),
)
```

3. **实现 `getexeList(app)` 函数** - 构造任务列表

```python
def getexeList(app):
    # 从数据库读取
    results = app.holo_client.execute_sql_query("SELECT id FROM table LIMIT 100")
    return [{"id": row[0]} for row in results]
    # 或静态列表
    # return [{"id": 1}, {"id": 2}, {"id": 3}]
```

4. **实现 `main(arg, app)` 函数** - 编写采集逻辑

```python
def main(arg, app):
    result = app.crawl.crawl(f"https://api.example.com/{arg['id']}")
    data = json.loads(result['html'])
    app.push_queue.put({"id": arg['id'], "data": data})
```

### 4. 运行爬虫

```bash
python my_spider.py
```

### 5. 配置循环执行（可选）

```python
settings = SpiderSettings(
    loop_enable=True,
    loop_mode="interval",           # 'interval' 或 'daily_time'
    loop_interval_seconds=1800,     # interval 模式：间隔秒数
    # loop_daily_times=["00:00", "12:00"],  # daily_time 模式
)
```

## 配置项说明

### Apollo 配置

Apollo 配置在**脚本顶部全局获取**，得到 `apollo` 字典后在 `SpiderSettings` 中按需引用。

| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| apollo_enable | bool | True | 是否由框架内部获取 Apollo（已外部获取时设为 False） |
| apollo_id | str | 'Creatives-spider' | Apollo 应用ID |
| apollo_url_test | str | | 测试环境 Apollo 地址 |
| apollo_url_prod | str | | 生产环境 Apollo 地址 |
| configurations | dict | None | 外部传入的 Apollo 配置字典（传入后框架跳过内部 fetch） |

### 基础配置

| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| is_test | bool | 从 ISTEST 环境变量获取 | True=测试环境，False=生产环境 |
| thread_num | int | 1 | 并发线程数 |

### 代理配置

| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| enable_proxy | bool | False | 是否启用代理 |
| proxy_list | list | None | 代理列表，如 `json.loads(apollo.get("IPlist", "[]"))` |

### 数据库配置

| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| enable_db | bool | False | 是否连接数据库 |
| db_host | str | '' | 如 `apollo.get("holoHost", "")` |
| db_port | str | '' | 如 `apollo.get("holoPort", "")` |
| db_name | str | '' | 如 `apollo.get("holoDBname", "")` |
| db_user | str | '' | 如 `apollo.get("holoUser", "")` |
| db_password | str | '' | 如 `apollo.get("holoPassword", "")` |
| db_table_name | str | '' | 数仓表名（与 db_topic_name 二选一） |
| db_topic_name | str | '' | Kafka Topic（与 db_table_name 二选一） |
| db_primary_key | str | '' | 主键名，冲突时更新（支持 "col1,col2"） |

### Kafka 配置

| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| enable_kafka | bool | False | 是否需要 Kafka |
| kafka_address | list | None | 如 `json.loads(apollo.get("kafkaAddress", "[]"))` |
| download_topic_name | str | '' | 下载器 Topic |
| kafka_log_level | int/None | WARNING | kafka-python 会打印大量 INFO 连接日志；默认压到 WARNING；设为 None 表示不覆盖外部日志配置 |
| kafka_acks | int | 1 | Kafka ACK 级别，默认 1 平衡可靠性与吞吐 |
| kafka_retries | int | 3 | 发送失败重试次数 |
| kafka_linger_ms | int | 50 | 聚合发送等待时间（毫秒） |
| kafka_batch_size | int | 65536 | 批次大小（字节） |
| kafka_compression_type | str | gzip | 压缩方式，降低网络带宽压力 |
| kafka_request_timeout_ms | int | 15000 | 单请求超时（毫秒） |
| kafka_delivery_timeout_ms | int | 30000 | 消息投递总超时（毫秒） |
| kafka_max_block_ms | int | 10000 | `send` 最长阻塞时间（毫秒） |
| kafka_flush_interval_seconds | int | 2 | flush 时间阈值（秒） |
| kafka_flush_max_messages | int | 1000 | flush 条数阈值 |

> 说明：你看到的 `BrokerConnection ... connecting/connected` 之类输出来自 `kafka-python` 的 `logging`，不是 `print`。
> - 用框架：在 `SpiderSettings` 里设置 `kafka_log_level=logging.WARNING`（默认就是 WARNING）
> - 或脚本里一行：`logging.getLogger("kafka").setLevel(logging.WARNING)`

### OBS/OSS 配置

| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| enable_obs | bool | False | 是否需要对象存储 |
| obs_provider | str | 'aliyun' | 云厂商: 'huawei' 或 'aliyun' |
| obs_ak | str | '' | 如 `apollo.get("AliOSS_AK", "")` |
| obs_sk | str | '' | 如 `apollo.get("AliOSS_SK", "")` |
| obs_endpoint | str | '' | 如 `apollo.get("AliOSS_Endpoint", "")` |
| obs_bucket_name | str | '' | 如 `apollo.get("AliOSS_BucketName", "")` |
| obs_link_prefix | str | '' | 如 `apollo.get("AliOSS_Link", "")` |

> 华为云 OBS 对应 Apollo key: `HWOBS_AK`, `HWOBS_SK`, `HWOBS_Endpoint`, `HWOBS_BucketName`, `HWOBS_Link`

### 调试配置

| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| print_item | bool | False | 是否打印推送数据 |

### 背压配置

| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| push_queue_maxsize | int | 5000 | `app.push_queue` 最大长度；达到上限时 `put` 阻塞（0=不限制） |

### 循环执行配置

| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| loop_enable | bool | False | 是否循环执行 |
| loop_mode | str | 'interval' | 循环模式: 'interval' 或 'daily_time' |
| loop_interval_seconds | int | 3600 | interval 模式间隔秒数 |
| loop_daily_times | list | None | daily_time 模式时间点列表 |

## 配置覆盖优先级

配置优先级（高 → 低）：

1. `SpiderSettings` 中直接指定的配置值
2. Apollo 配置（通过 `apollo.get()` 在脚本中引用）
3. 框架内部兜底（仅在 settings 值为空且 `configurations` 中有对应 key 时生效）

## 环境变量

```bash
# Windows
set ISTEST=0    # 0=生产环境, 1=测试环境

# Linux/Mac
export ISTEST=0
```

## app 对象属性

在 `main(arg, app)` 函数中，`app` 对象提供以下属性：

| 属性 | 说明 |
|------|------|
| `app.push_queue` | 数据推送队列 |
| `app.download_queue` | 下载器队列 |
| `app.holo_client` | 数据库客户端 |
| `app.obs_helper` | OBS/OSS 客户端 |
| `app.videoOp` | 视频操作工具 |
| `app.fileOp` | 文件操作工具 |
| `app.crawl` | HTTP 请求工具 |
| `app.configurations` | Apollo 配置 |

## 依赖

核心依赖（必装）：
- requests>=2.25.0

可选依赖（按需安装）：
- psycopg>=3.0.0 (`[db]`)
- kafka-python>=2.0.0 (`[kafka]`)
- yt-dlp>=2023.0.0 (`[video]`)
- esdk-obs-python>=3.0.0 (`[obs]`)
- oss2>=2.15.0 (`[oss]`)

## 开发依赖（可选）

```bash
pip install "spiderWei-TecDo[dev]"
```

- pytest>=7.0.0
- black>=22.0.0
