Metadata-Version: 2.4
Name: ja-stopword-filter
Version: 0.3.0
Summary: A lightweight Python library designed to filter stopwords for Japanese text.
Author: BrambleXu
Author-email: BrambleXu <liangxu006@gmail.com>
License-Expression: Apache-2.0 AND Unicode-3.0
License-File: LICENSE
License-File: LICENSE-UNICODE
Requires-Python: >=3.12
Project-URL: Homepage, https://github.com/BrambleXu/ja-stopword-filter
Project-URL: Repository, https://github.com/BrambleXu/ja-stopword-filter
Project-URL: Documentation, https://github.com/BrambleXu/ja-stopword-filter
Project-URL: Issues, https://github.com/BrambleXu/ja-stopword-filter/issues
Description-Content-Type: text/markdown

# ja-stopword-filter

[![CI](https://github.com/BrambleXu/ja-stopword-filter/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/BrambleXu/ja-stopword-filter/actions/workflows/ci.yml)
[![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue?logo=python&logoColor=white)](https://github.com/BrambleXu/ja-stopword-filter/blob/main/pyproject.toml)
[![License: Apache-2.0 AND Unicode-3.0](https://img.shields.io/badge/license-Apache--2.0%20AND%20Unicode--3.0-blue)](#license)

分かち書き済みの日本語トークンから、ストップワードや指定した種類のトークンを除去する Python ライブラリです。実行時の外部依存はありません。Python 3.12 以上に対応しています。

[English](https://github.com/BrambleXu/ja-stopword-filter/blob/main/README_en.md)

**このライブラリは分かち書きを行いません。** 文全体を文字列で渡さず、文字列または `Token` のリストを渡してください。

## インストールと最小例

```bash
pip install ja-stopword-filter
```

配布名は `ja-stopword-filter`、インポート名は `ja_stopword_filter` です。

```python
from ja_stopword_filter import JaStopwordFilter

words = ["これ", "は", "東京", "。", "🤖"]
print(JaStopwordFilter().remove(words))  # Output: ['は', '東京', '。', '🤖']
```

デフォルトで有効なのは内蔵の語リストと、照合用の NFKC 正規化だけです。内蔵リストは 310 語で、`は`、`が`、`です`、`ます` などは含みません。必要な語や品詞を追加してください。

## ルールを組み合わせる

```python
from ja_stopword_filter import JaStopwordFilter

stopword_filter = JaStopwordFilter(
    use_date=True,
    use_numbers=True,
    use_symbols=True,
    use_spaces=True,
    use_emojis=True,
    custom_wordlist=["は"],
)
words = ["これ", "は", "東京", "。", "!!!", "🤖", "２０２４年１１月", "123", "", "2024年11月発売"]
print(stopword_filter.remove(words))  # Output: ['東京', '2024年11月発売']
```

| パラメータ | デフォルト | 動作 |
| --- | --- | --- |
| `convert_full_to_half: bool` | `True` | 内蔵ルールの照合に NFKC を使用。出力やコールバックの入力は変えません。 |
| `use_slothlib: bool` | `True` | 内蔵の非空ストップワード 310 語を使用。 |
| `filter_length: int` | `0` | 正規化後の長さが指定値以下のトークンを除去。0 以下では無効。 |
| `use_date: bool` | `False` | トークン全体が `YYYY年M月`、`M月D日`、`YYYY年M月D日` の形に一致すれば除去。 |
| `use_numbers: bool` | `False` | 正規化後の `str.isdigit()` が真なら除去。 |
| `use_symbols: bool` | `False` | 全文字が Unicode の句読点・記号カテゴリ `P` / `S` である非空トークンを除去。 |
| `use_spaces: bool` | `False` | 空文字列や、空白・タブ・改行だけのトークンを除去。 |
| `use_emojis: bool` | `False` | 元の表記に Unicode 17.0 の絵文字を含むトークン全体を除去。 |
| `custom_wordlist: list[str] \| None` | `None` | 内蔵リストに追加するストップワード。 |
| `custom_filter: Callable[[T], bool] \| None` | `None` | 元のトークンを受け取り、`True` なら除去。 |

### 挙動の境界

- NFKC は単なる全角→半角変換ではありません。`ｶﾀｶﾅ` → `カタカナ`、`①` → `1`、`㍑` → `リットル` も含みます。`convert_to_halfwidth()` で同じ変換を明示的に利用できます。
- `remove()` は新しいリストを返します。順序、重複、残した文字列の元の表記、`Token` のオブジェクト同一性を保ちます。入力リストや `surface` は変更しません。
- 日付は形式の照合だけです。`2024年99月99日` も一致します。実在日付の検証や `2024-11-26` の解析は行いません。`2024年11月発売` は日付ルールでは除去しません。
- 数字ルールは `123` や `１２３` を除去しますが、`-123`、`3.14`、`1,000`、`一` は残します。
- 記号ルールは `。`、`!!!`、`￥` を除去し、`C++` や `a-b` は残します。一部の絵文字も `S` カテゴリなので、このルールと絵文字ルールは重複します。複合絵文字には `use_emojis` を使用してください。
- 絵文字は Unicode の fully-qualified / minimally-qualified / unqualified 表記を検出します。`❤`、国旗、肌色修飾、ZWJ、キーキャップを含みます。単独の `1`、`#`、`*`、国旗の片側の地域指示文字は絵文字扱いしません。絵文字列の厳密な妥当性検証ではなく、含有判定です。
- 文字数は正規化後の Python 文字列の長さです。表示上の一文字とは限りません。空白は `str.strip()` に従い、ゼロ幅スペース U+200B は除去しません。
- どれか一つの有効なルールに一致すれば除去します。空文字列を自分で `custom_wordlist` に追加した場合、`use_spaces=False` でも除去されます。

## 品詞・独自属性によるフィルタ

`Token(surface, pos)` の `pos` は呼び出し側が与える文字列です。内蔵ルールは品詞を判定しません。コールバックは内蔵ルールより先に実行され、正規化前の文字列または元の `Token` を受け取ります。

```python
from ja_stopword_filter import JaStopwordFilter, Token

class CountedToken(Token):
    def __init__(self, surface: str, pos: str, frequency: int) -> None:
        super().__init__(surface, pos)
        self.frequency = frequency

def exclude(token: CountedToken) -> bool:
    return token.pos == "助詞" or token.frequency < 2

words = [CountedToken("東京", "名詞", 5), CountedToken("は", "助詞", 8), CountedToken("例", "名詞", 1)]
filtered = JaStopwordFilter(custom_filter=exclude).remove(words)
print([token.surface for token in filtered])  # Output: ['東京']
```

コールバックは入力の型に合わせてください。文字列と `Token` を混在させる場合は `isinstance` で分岐します。[混在入力の例](https://github.com/BrambleXu/ja-stopword-filter/blob/main/examples/custom_filter.py) と、分かち書きから実行する [Janome の例](https://github.com/BrambleXu/ja-stopword-filter/blob/main/examples/janome_example.py) を用意しています。Janome は例専用で、本ライブラリの依存には含めません。

型注釈と `py.typed` を同梱しています。`JaStopwordFilter` はコールバックの型を推論し、`remove()` は入力の要素型（Token のサブクラスを含む）を維持します。

### 公開 API

- `JaStopwordFilter(...).remove(tokens)`：分かち書き済みのリストやタプルをフィルタ。生の文字列・bytes や、`str` / `Token` 以外の要素には `TypeError`。
- `Token(surface: str, pos: str)`：拡張可能なトークン。残されたオブジェクトはコピーしません。
- `get_stopwords() -> list[str]`：空行を除いた内蔵語リストの新しいリストを返します。
- `convert_to_halfwidth(text: str) -> str`：Unicode NFKC を適用します。関数名は互換性のため維持しています。

## License

Python の実装は [Apache License 2.0](https://github.com/BrambleXu/ja-stopword-filter/blob/main/LICENSE)、Unicode データから生成した絵文字パターンは [Unicode License v3](https://github.com/BrambleXu/ja-stopword-filter/blob/main/LICENSE-UNICODE) に基づきます。
