Metadata-Version: 2.4
Name: pyspider-cli
Version: 0.1.0
Summary: 异步并发命令行爬虫工具 / Async concurrent web crawler CLI
License: MIT
Keywords: crawler,scraper,async,cli,web
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: beautifulsoup4>=4.15.0
Requires-Dist: httpx[http2]>=0.28.1
Requires-Dist: loguru>=0.7.3
Requires-Dist: lxml>=6.1.1
Requires-Dist: pydantic>=2.13.4
Requires-Dist: pyyaml>=6.0.3
Requires-Dist: rich>=15.0.0
Requires-Dist: typer>=0.27.0
Requires-Dist: shellingham>=1.4.0
Dynamic: license-file

# pyspider-cli

[![PyPI](https://img.shields.io/pypi/v/pyspider-cli)](https://pypi.org/project/pyspider-cli/)
[![Python](https://img.shields.io/pypi/pyversions/pyspider-cli)](https://pypi.org/project/pyspider-cli/)
[![Tests](https://github.com/JokerGHB/pyspider-cli/actions/workflows/test.yml/badge.svg)](https://github.com/JokerGHB/pyspider-cli/actions/workflows/test.yml)
[![License](https://img.shields.io/github/license/JokerGHB/pyspider-cli)](LICENSE)

**pyspider-cli** 是一个生产级异步并发命令行爬虫工具，使用 Python 3.12+ 开发。

**pyspider-cli** is a production-grade async concurrent web crawler CLI tool built with Python 3.12+.

---

## 特性 / Features

- ⚡ **异步并发** — 基于 `asyncio` + `httpx`，可配置并发数
- 🚦 **限速** — Token Bucket 算法，精确控制请求速率
- 🔄 **自动重试** — 指数退避 + 随机抖动，自动重试网络错误和 5xx
- 📝 **HTML 解析** — BeautifulSoup + lxml 解析，支持自定义 CSS 选择器
- 📊 **进度条** — Rich 实时进度显示（完成数、速率、耗时、错误数）
- 📦 **多格式输出** — JSON / CSV
- ⚙️ **YAML 配置** — Pydantic v2 校验，CLI 参数可覆盖
- 📋 **日志** — loguru 彩色日志，可选文件日志
- 🔍 **全类型注解** — mypy strict 零错误

---

## 安装 / Installation

```bash
pip install pyspider-cli
```

需要 Python 3.12+。推荐使用 `uv` 安装：

```bash
uv pip install pyspider-cli
```

---

## 快速开始 / Quick Start

### 命令行 / CLI

```bash
# 爬取单个 URL
pyspider crawl https://httpbin.org/html -o result.json

# 从文件读取 URL 列表，并发 10
pyspider crawl -f urls.txt -c 10 -o result.json

# 从 stdin 读取（每行一个 URL）
cat urls.txt | pyspider crawl --stdin --format csv -o result.csv

# 指定 YAML 配置文件
pyspider crawl -f urls.txt --config myconfig.yaml -o result.json

# 限速 + 禁用解析（仅下载）
pyspider crawl -f urls.txt --rate-limit 20 --no-parse -o out.json
```

### 参数说明 / Options

| 参数 | 缩写 | 默认值 | 说明 |
|------|------|--------|------|
| `urls` | — | — | URL 参数（位置参数，空格分隔） |
| `--file` | `-f` | — | URL 文件（每行一个） |
| `--stdin` | — | `False` | 从 stdin 读取 URL |
| `--concurrency` | `-c` | `5` | 最大并发数 |
| `--output` | `-o` | — | 输出文件路径（默认 stdout） |
| `--format` | — | `json` | 输出格式：`json` / `csv` |
| `--config` | — | — | YAML 配置文件路径 |
| `--timeout` | — | `10.0` | 请求超时秒数 |
| `--rate-limit` | `--rl` | `5.0` | 每秒最大请求数 |
| `--retry` | — | `2` | 最大重试次数 |
| `--parse/--no-parse` | — | `--parse` | 启用 HTML 解析 |
| `--log-level` | — | `INFO` | 日志等级 |
| `--version` | `-V` | — | 显示版本号 |

### Python API

```python
import asyncio
from pyspider_cli.crawler import Crawler
from pyspider_cli.config import CrawlConfig
from pyspider_cli.rate_limiter import TokenBucket
from pyspider_cli.parser import HtmlParser

async def main():
    config = CrawlConfig(concurrency=10, rate_limit=20.0)
    bucket = TokenBucket(config.rate_limit)
    parser = HtmlParser(selectors={"title": "h1.entry-title"})
    crawler = Crawler(config, bucket, parser)

    async for result in crawler.crawl(["https://example.com"]):
        print(f"{result.url} → {result.status_code}")
        if result.parsed:
            print(f"  Title: {result.parsed.title}")
            print(f"  Links: {len(result.parsed.links)}")

asyncio.run(main())
```

---

## 配置文件 / Configuration

创建 `config.yaml`：

```yaml
concurrency: 10
timeout: 15.0
retry_times: 3
rate_limit: 20.0
headers:
  User-Agent: MyBot/1.0
  Accept-Language: zh-CN
enable_parse: true
selectors:
  title: h1.article-title
  content: div.article-content
output_format: json
log_level: INFO
```

使用：`pyspider crawl -f urls.txt --config config.yaml -o out.json`

---

## 抓取示例 / Real Examples

### Hacker News 标题

```bash
# 一行搞定
echo "https://news.ycombinator.com" | pyspider crawl --stdin -o hn.json
```

### GitHub Trending

```bash
pyspider crawl https://github.com/trending -o trending.json
```

查看完整示例：[examples/](examples/)

---

## 开发 / Development

```bash
# 克隆
git clone https://github.com/JokerGHB/pyspider-cli.git
cd pyspider-cli

# 使用 uv 安装开发依赖
uv venv
uv sync

# 运行测试
uv run pytest test/ --cov=src/pyspider_cli

# 类型检查
uv run mypy src/pyspider_cli/ --strict

# 代码风格
uv run ruff check src/pyspider_cli/

# 构建
uv run python -m build
```

### 项目结构 / Project Structure

```
src/pyspider_cli/
├── __init__.py       # 包元数据
├── __main__.py       # python -m 支持
├── cli.py            # Typer CLI 入口
├── config.py         # Pydantic 配置模型 + YAML 加载
├── crawler.py        # 异步爬虫引擎
├── io.py             # URL 输入 + 输出写入
├── logger.py         # loguru 日志配置
├── models.py         # CrawlResult / ParsedData 数据模型
├── parser.py         # HTML 解析器
├── progress.py       # Rich 进度条
└── rate_limiter.py   # Token Bucket 限速器
```

---

## 许可 / License

MIT
