Nekoyazuma/scry
GitHub: Nekoyazuma/scry
scry 是一个 Linux 命令行 OCR 工具,通过拖拽选取图片区域并将识别结果自动复制到剪贴板与 stdout。
Stars: 2 | Forks: 0
# scry
[options]
```
对图像运行它,然后在想要的文本周围拖拽出一个选框:
```
python -m scry screenshot.png
```
打开一个显示图像的窗口。点击并拖拽以选择一个区域;
松开鼠标以提取文本。按下 **Escape** 或关闭窗口,
即可取消而不提取任何内容。
### CLI 选项
```
usage: scry [-h] [-l LANG] [-v] [--no-notify] [--version] image
See beyond the pixels. Drag-select text from an image, straight to your
clipboard.
positional arguments:
image Path to the image to select text from.
options:
-h, --help show this help message and exit
-l LANG, --lang LANG Tesseract language code(s), e.g. 'eng' or 'eng+fra'
(default: eng).
-v, --verbose Increase log verbosity to stderr (-v for INFO, -vv for
DEBUG).
--no-notify Skip the desktop notification after copying.
--version show program's version number and exit
```
### 示例
基本用法:
```
python -m scry diagram.png
```
提取法语文本:
```
python -m scry receipt.png --lang fra
```
提取混合的英语和法语文本:
```
python -m scry menu.png --lang eng+fra
```
运行而不显示桌面通知(在脚本中或重复
调用 scry 时很有用):
```
python -m scry screenshot.png --no-notify
```
查看底层发生了什么:
```
python -m scry screenshot.png -v # INFO-level logging
python -m scry screenshot.png -vv # DEBUG-level logging, incl. tracebacks on internal errors
```
由于提取的文本也会打印到 stdout,scry 可以与
常规的 shell 工具组合使用:
```
python -m scry error_dialog.png | grep -i "exception"
python -m scry note.png > extracted.txt
```
(stderr 专用于日志记录,永远不会与 stdout 上的
提取文本混杂在一起,因此通过管道传递 stdout 始终是安全的。)
## scry 的工作原理
每次运行都遵循相同的固定 pipeline:
```
load image
|
v
select a region (drag in the Tk window)
|
v
crop to that region
|
v
run OCR (Tesseract, via pytesseract)
|
v
copy the extracted text to the clipboard
|
v
print the extracted text to stdout
|
v
show a desktop notification (unless --no-notify)
```
一些值得了解的细节:
- **空选择不是错误。** 如果你在没有
真正拖拽的情况下松开鼠标(拖拽范围小于 4×4 像素),或者按下了 Escape,或者
关闭了窗口,scry 会以退出代码 `1` 静默退出——什么都不会
被打印、复制或通知。
- **“未找到文本”同样不是错误。** 如果 OCR 成功运行
但在你的选择中什么也没找到,scry 仍然会以 `0` 退出,打印一个
空行,并显示“未找到文本”通知,而不是
“已复制到剪贴板”。
- **提取的文本总是会到达 stdout**,即使剪贴板
复制本身失败也是如此——因此你不会因为缺少
剪贴板工具而丢失结果。
- **剪贴板复制失败永远不会触发通知。** 相反,你会
在 stderr 上看到错误信息,并附上修复说明。
- **通知发送失败永远不会导致运行失败。** 桌面通知是
尽力而为的;如果没有安装 `notify-send`,scry 会
静默继续执行而不发送通知。
### 退出代码
| 代码 | 含义 |
|---|---|
| `0` | 成功(包括“未找到文本”) |
| `1` | 选择被用户取消 |
| `2` | 图像路径缺失、无法读取,或不是有效的图像 |
| `3` | OCR 引擎失败 |
| `4` | 没有可用的剪贴板工具 |
| `5` | 发生意外的内部错误 |
## 项目理念
scry 的构建宗旨是保持小巧。代码库始终遵循以下
几条规则:
- **每次运行只做一件事。** 没有配置文件,没有 daemon,调用之间
没有持久化状态。
- **使用普通函数而非类。** scry 的大部分内部实现
(`crop()`、`ocr.extract_text()`、`clipboard.copy()`、`notify.send()`)
都是单一的函数,而不是仅仅为了包装单一实现而存在的类。
- **抽象是争取来的,而不是凭空预期的。** 唯一的例外是
`RegionSelector`,一个抽象基类——它已经支持了两个真实的
实现(真实的 Tkinter 窗口,以及测试中使用的假实现),
这正是 scry 在任何地方引入抽象之前所采用的实际标准。
- **每一次失败要么是预期之内的,要么就是 Bug。** scry 为其预期的
每种失败模式(图像损坏、选择取消、OCR 失败、剪贴板失败)
都定义了特定的异常和退出代码。
其他任何情况都被视为真正的 Bug:它会提供完整的 traceback
(仅在指定 `-vv` 时可见),在 stderr 上输出干净的单行消息,并且
退出代码为 `5`——永远不会抛出原始且未处理的 traceback。
## 测试
scry 在其各个模块中都有单元测试覆盖——包括异常层级结构、
CLI 解析、图像加载、区域/裁剪计算、OCR 和剪贴板
封装(带有特定于发行版的错误消息),以及桌面
通知。GUI 驱动的代码(实际的 Tkinter 窗口)在
不需要显示器即可测试其逻辑的地方进行了覆盖;打开真实窗口的验证
是通过手动完成的,而不是在自动化测试套件中进行。
运行测试套件:
```
pip install pytest
pytest -v
```
有些测试会根据你的环境有条件地运行:
- OCR 往返测试只有在 `tesseract` 位于你的 `PATH` 中时
才会运行(否则将被跳过)。
- 涉及剪贴板、OCR 引擎或通知的测试会 mock
这些调用,因此不需要安装 `tesseract`、`xclip`、
`wl-clipboard` 或 `notify-send` 即可通过完整的测试套件。
## 已知限制
- **OCR 准确率完全取决于 Tesseract 以及你的图像/裁剪
质量。** 模糊的屏幕截图、微小的文本、低对比度或异常的
字体都会导致结果变差——这是
底层 OCR 引擎的特性,除了对微小裁剪区域
应用自动放大之外,scry 无法进行其他补偿。
- **不支持多显示器跨屏。** 选择窗口会在
你的窗口管理器视为主/默认显示器的那台显示器上打开;scry
不会检测或针对特定的显示器。
- **选择窗口中无法缩放或平移** —— 非常大的图像会被
缩小以适应你的屏幕,你需要针对该缩放后的
视图进行选择。
- **拖拽后无法进行调整。** 如果拖拽失误,你必须重来;
没有调整大小的手柄。
- **仅支持鼠标选择。** 目前没有任何基于键盘的
选择方式。
- **每次运行只能选择一次。** scry 每次调用
提取一个区域;没有批量或多区域模式。
- **仅支持 Linux。** scry 是在 Linux(X11 和
XWayland)上开发和测试的;除了 `pyperclip`/`wl-clipboard` 所支持的之外,它没有在 Wayland 原生剪贴板工具上进行过测试,也不支持
Windows 或 macOS。
## 故障排除
**“Tesseract is not installed. Install it with: ...”**
`tesseract` 二进制文件不在你的 `PATH` 中。scry 会检测你的发行版
并打印出确切的安装命令——运行建议的
命令然后重试。
**“No clipboard tool available. Install it with: ...”**
同样的思路,只不过是针对剪贴板的:scry 会检测你是在 X11 还是
Wayland 上(通过 `$WAYLAND_DISPLAY`)以及你的发行版,并打印出确切的
安装命令。请注意,即使
发生这种情况,提取的文本仍会到达 stdout——你不会丢失它。
**没有出现桌面通知。**
如果没有安装 `notify-send`(来自 `libnotify`),这是预期的,
并且无害——通知是可选的,根据设计会静默失败。
如果你想确认是否发生了这种情况,请使用 `-vv` 运行(你将
看到一条 `DEBUG` 级别的日志,指出通知尝试已被跳过)。
**“A required system dependency is missing: No module named 'tkinter'”**
未安装 `python3-tk`(或你发行版的 Tkinter 软件包)。请使用上面
[系统依赖](#system-dependencies)中对应你发行版的
命令进行安装。
**窗口似乎没有打开,或者什么也没发生。**
确保你有一个正常工作的 X11 或 Wayland 会话——scry 需要
一个真实的显示器。尝试使用 `-vv` 运行,以在 scry 加载图像并打开选择窗口时,
在 stderr 上查看详细的日志记录。
**我收到了“Image file not found” / “Not a valid image file”。**
仔细检查你传递的路径,以及该文件是否实际上是
scry 基于 Pillow 的加载器可以解码的有效图像。这些消息意味着
scry 已经成功查看了该路径——问题出在它
在那里找到的内容上。
**我想了解更多关于哪里出错的细节。**
使用 `-vv` 重新运行。默认的日志记录在设计上是静默的(除非
发生了值得注意的情况,否则 stderr 是干净的);`-v` 会增加 `INFO` 级别的
详细信息,而 `-vv` 会增加完整的 `DEBUG` 详细信息,包括针对意外内部错误的
完整 traceback。
## 许可证
scry 采用 [MIT 许可证](LICENSE)发布。
标签:OCR, Python, Tesseract, 剪贴板, 文本提取, 无后门, 逆向工具