Metadata-Version: 2.4
Name: skysearch
Version: 0.4.0
Summary: Search the web, rank results, fetch any page content.
Author: zimvir
License: MIT
Project-URL: Homepage, https://github.com/zimvir/skysearch
Project-URL: Documentation, https://github.com/zimvir/skysearch#readme
Keywords: search,fetch,bing,bm25,web-scraper,crawler
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.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: DrissionPage
Requires-Dist: beautifulsoup4
Requires-Dist: lxml
Requires-Dist: readability-lxml
Requires-Dist: jieba
Requires-Dist: rank-bm25

# SkySearch

基于 Bing 搜索 + DrissionPage 动态渲染的搜索服务，核心优势是**能抓取 JS 动态加载的内容**（知乎、SPA、单页应用等）。

> DrissionPage：Python 轻量级网页自动化库，比 Selenium 更轻，支持 JS 动态渲染。

## 特性

- **Bing 搜索**：SessionPage 底层 TLS 指纹伪装，绕过反爬
- **动态页面抓取**：Chromium 无头渲染，支持 SPA / 懒加载 / 反爬较强的动态站
- **结构化输出**：`mode=info` 返回完整 JSON（title、text、links、meta）
- **CLI + Python API**：命令行直接用，也可用作库

## 安装

```bash
pip install skysearch
```

## 标准工作流

推荐：`search_bare` → 判断 URL → `fetch(mode=info)`

```
search_bare(num=30) → 人工/agent判断URL → fetch(mode=info) → 完整结构化数据
```

**为什么不用 `search`？** `search` 会抓取所有结果页面做 BM25 排名，慢且没必要——`search_bare` 够快，`fetch` 按需抓取更灵活。

**为什么 `mode=info`？** `text` 模式依赖 readability 清洗，会删减部分正文内容。`info` 返回完整结构化数据，更适合 agent 处理。

## 命令行使用

### search_bare（推荐）

```bash
# 纯搜索，不抓页面不排名（快）
skysearch "浙江大学 录取 分数线" --bare -n 10

# num 建议：日常 10，批量研究 20~30，深度调研最多 50
skysearch "Python教程" --bare -n 30
```

### URL 抓取

```bash
# 结构化信息（推荐）
skysearch --url https://example.com --mode info

# 原始 HTML
skysearch --url https://example.com --mode raw

# 调试：打开浏览器窗口
skysearch --url https://example.com --mode info --headed
```

### 搜索 + 抓取（不推荐，慢）

```bash
# 搜索 + BM25 排名，所有结果页面都会被抓取，慢
skysearch "关键词" -n 10
```

## Python API

```python
import skysearch

# Step 1：search_bare 批量搜索（快）
results = skysearch.search_bare("浙江大学 录取 分数线", num=30)
# [{'title': ..., 'url': ..., 'snippet': ...}, ...]

# Step 2：判断 URL 后，按需抓取
info = skysearch.fetch("https://example.com", mode='info')
# {'url': ..., 'title': ..., 'text': ..., 'links': [...], 'meta': {...}}
```

### 中文搜索注意

skysearch 对中文词边界敏感。**短词查询会被错误切分**：

| 查询 | 结果 |
|------|------|
| `浙大2024分数线` | 切词错误，答非所问 |
| `浙江大学 录取 分数线` | 精准命中多条相关内容 |

**规则：中文查询时，在词与词之间加空格，模拟分词效果。**

## API 参考

### search_bare(query, num=10)

| 参数 | 说明 | 默认值 |
|------|------|--------|
| query | 搜索关键词（中文建议手动分词加空格） | - |
| num | 结果数量（支持分页，建议不超过 50） | 10 |

返回：纯 Bing 结果列表（快速，不抓页面不排名）

### fetch(url, mode='info', keep=False, timeout=10, retry=2, headless=True)

| 参数 | 说明 | 默认值 |
|------|------|--------|
| url | 页面 URL | - |
| mode | `info`（推荐）/`text`/`raw` | info |
| keep | 保持浏览器打开 | False |
| timeout | 请求超时秒数 | 10 |
| retry | 重试次数 | 2 |
| headless | 无头浏览器（默认 True） | True |

### search_and_fetch(query, num=10, mode='info', verbose=False, keep=False, headless=True)

搜索 + 抓取一体化，返回列表包含结果信息和抓取内容。

## fetch 的三种 mode

| 模式 | 说明 | 推荐度 |
|------|------|--------|
| `info` | 结构化 JSON（url, title, text, links, meta） | ✅ 推荐 |
| `text` | 清洗后正文，内容可能被删减 | ❌ 不推荐 |
| `raw` | 原始 HTML，数据量大 | 按需 |

## 技术栈

| 模块 | 技术 |
|------|------|
| HTTP 请求 | DrissionPage (SessionPage) |
| 动态渲染 | DrissionPage (ChromiumPage) |
| HTML 解析 | BeautifulSoup4 + lxml |
| 正文提取 | readability-lxml |

## 项目结构

```
skysearch/
├── api.py            # 简洁 API 接口
├── cli.py            # 命令行入口
├── search.py         # Bing 搜索（含分页）
├── ranker.py         # BM25 排序
└── fetcher/          # 页面抓取包
    ├── core.py       # 核心函数
    ├── session.py    # 会话管理
    └── parser.py     # HTML 解析
```

## License

MIT
