wp2txt 1.1.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.dockerignore +12 -0
- data/.github/workflows/ci.yml +13 -13
- data/.gitignore +14 -0
- data/CHANGELOG.md +284 -0
- data/DEVELOPMENT.md +415 -0
- data/DEVELOPMENT_ja.md +415 -0
- data/Dockerfile +19 -10
- data/Gemfile +2 -8
- data/README.md +259 -123
- data/README_ja.md +375 -0
- data/Rakefile +4 -0
- data/bin/wp2txt +863 -161
- data/lib/wp2txt/article.rb +98 -13
- data/lib/wp2txt/bz2_validator.rb +239 -0
- data/lib/wp2txt/category_cache.rb +313 -0
- data/lib/wp2txt/cli.rb +319 -0
- data/lib/wp2txt/cli_ui.rb +428 -0
- data/lib/wp2txt/config.rb +158 -0
- data/lib/wp2txt/constants.rb +134 -0
- data/lib/wp2txt/data/html_entities.json +2135 -0
- data/lib/wp2txt/data/language_metadata.json +4769 -0
- data/lib/wp2txt/data/language_tiers.json +59 -0
- data/lib/wp2txt/data/mediawiki_aliases.json +12366 -0
- data/lib/wp2txt/data/template_aliases.json +193 -0
- data/lib/wp2txt/data/wikipedia_entities.json +12 -0
- data/lib/wp2txt/extractor.rb +545 -0
- data/lib/wp2txt/file_utils.rb +91 -0
- data/lib/wp2txt/formatter.rb +352 -0
- data/lib/wp2txt/global_data_cache.rb +353 -0
- data/lib/wp2txt/index_cache.rb +258 -0
- data/lib/wp2txt/magic_words.rb +353 -0
- data/lib/wp2txt/memory_monitor.rb +236 -0
- data/lib/wp2txt/multistream.rb +1383 -0
- data/lib/wp2txt/output_writer.rb +182 -0
- data/lib/wp2txt/parser_functions.rb +606 -0
- data/lib/wp2txt/ractor_worker.rb +215 -0
- data/lib/wp2txt/regex.rb +396 -12
- data/lib/wp2txt/section_extractor.rb +354 -0
- data/lib/wp2txt/stream_processor.rb +271 -0
- data/lib/wp2txt/template_expander.rb +830 -0
- data/lib/wp2txt/text_processing.rb +337 -0
- data/lib/wp2txt/utils.rb +629 -270
- data/lib/wp2txt/version.rb +1 -1
- data/lib/wp2txt.rb +53 -26
- data/scripts/benchmark_regex.rb +161 -0
- data/scripts/fetch_html_entities.rb +94 -0
- data/scripts/fetch_language_metadata.rb +180 -0
- data/scripts/fetch_mediawiki_data.rb +334 -0
- data/scripts/fetch_template_data.rb +186 -0
- data/scripts/profile_memory.rb +139 -0
- data/spec/article_spec.rb +402 -0
- data/spec/auto_download_spec.rb +314 -0
- data/spec/bz2_validator_spec.rb +193 -0
- data/spec/category_cache_spec.rb +226 -0
- data/spec/category_fetcher_spec.rb +504 -0
- data/spec/cleanup_spec.rb +197 -0
- data/spec/cli_options_spec.rb +678 -0
- data/spec/cli_spec.rb +876 -0
- data/spec/config_spec.rb +194 -0
- data/spec/constants_spec.rb +138 -0
- data/spec/file_utils_spec.rb +170 -0
- data/spec/fixtures/samples.rb +181 -0
- data/spec/formatter_sections_spec.rb +382 -0
- data/spec/global_data_cache_spec.rb +186 -0
- data/spec/index_cache_spec.rb +210 -0
- data/spec/integration_spec.rb +543 -0
- data/spec/magic_words_spec.rb +261 -0
- data/spec/markers_spec.rb +476 -0
- data/spec/memory_monitor_spec.rb +192 -0
- data/spec/multistream_spec.rb +690 -0
- data/spec/output_writer_spec.rb +400 -0
- data/spec/parser_functions_spec.rb +455 -0
- data/spec/ractor_worker_spec.rb +197 -0
- data/spec/regex_spec.rb +281 -0
- data/spec/section_extractor_spec.rb +397 -0
- data/spec/spec_helper.rb +63 -0
- data/spec/stream_processor_spec.rb +579 -0
- data/spec/template_data_spec.rb +246 -0
- data/spec/template_expander_spec.rb +472 -0
- data/spec/template_processing_spec.rb +217 -0
- data/spec/text_processing_spec.rb +312 -0
- data/spec/utils_spec.rb +195 -16
- data/spec/wp2txt_spec.rb +510 -0
- data/wp2txt.gemspec +5 -3
- metadata +146 -18
- data/.rubocop.yml +0 -80
- data/data/output_samples/testdata_en.txt +0 -23002
- data/data/output_samples/testdata_en_category.txt +0 -132
- data/data/output_samples/testdata_en_summary.txt +0 -1376
- data/data/output_samples/testdata_ja.txt +0 -22774
- data/data/output_samples/testdata_ja_category.txt +0 -206
- data/data/output_samples/testdata_ja_summary.txt +0 -1560
- data/data/testdata_en.bz2 +0 -0
- data/data/testdata_ja.bz2 +0 -0
- data/image/screenshot.png +0 -0
data/DEVELOPMENT_ja.md
ADDED
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
# WP2TXT 開発ガイド
|
|
2
|
+
|
|
3
|
+
このドキュメントはWP2TXTの開発者向けガイダンスを提供します。ユーザードキュメントは[README_ja.md](README_ja.md)を参照してください。
|
|
4
|
+
|
|
5
|
+
[English](DEVELOPMENT.md) | 日本語
|
|
6
|
+
|
|
7
|
+
## クイックスタート
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# 依存関係をインストール
|
|
11
|
+
bundle install
|
|
12
|
+
|
|
13
|
+
# テストを実行
|
|
14
|
+
bundle exec rspec
|
|
15
|
+
|
|
16
|
+
# カバレッジ付きでテストを実行
|
|
17
|
+
bundle exec rspec # カバレッジレポートは coverage/index.html
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## アーキテクチャ概要
|
|
21
|
+
|
|
22
|
+
### 処理パイプライン
|
|
23
|
+
|
|
24
|
+
WP2TXTはWikipediaダンプを処理するためにストリーミングアーキテクチャを使用します:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
入力 (bz2/xml) → StreamProcessor → Article Parser → OutputWriter → 出力ファイル
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
1. **StreamProcessor** (`lib/wp2txt.rb`): bz2を解凍しXMLページをストリーミング
|
|
31
|
+
2. **Article** (`lib/wp2txt/article.rb`): MediaWikiテキストを型付き要素にパース
|
|
32
|
+
3. **Utils** (`lib/wp2txt/utils.rb`): テキストフォーマットとクリーンアップ関数を提供
|
|
33
|
+
4. **OutputWriter** (`lib/wp2txt.rb`): テキストまたはJSON形式で出力を書き込み
|
|
34
|
+
|
|
35
|
+
### コアクラス
|
|
36
|
+
|
|
37
|
+
| クラス | ファイル | 目的 |
|
|
38
|
+
|--------|----------|------|
|
|
39
|
+
| `StreamProcessor` | `lib/wp2txt/stream_processor.rb` | 適応的バッファリングで圧縮ダンプからページをストリーミング |
|
|
40
|
+
| `Article` | `lib/wp2txt/article.rb` | MediaWikiマークアップをパース |
|
|
41
|
+
| `OutputWriter` | `lib/wp2txt.rb` | 出力ファイルローテーションを管理 |
|
|
42
|
+
| `DumpManager` | `lib/wp2txt/multistream.rb` | ダンプをダウンロード・キャッシュ |
|
|
43
|
+
| `MultistreamIndex` | `lib/wp2txt/multistream.rb` | ランダムアクセス用に記事をインデックス化 |
|
|
44
|
+
| `MultistreamReader` | `lib/wp2txt/multistream.rb` | 記事を抽出(並列抽出対応) |
|
|
45
|
+
| `CategoryFetcher` | `lib/wp2txt/multistream.rb` | Wikipedia APIからカテゴリメンバーを取得 |
|
|
46
|
+
| `MemoryMonitor` | `lib/wp2txt/memory_monitor.rb` | クロスプラットフォームメモリ監視 |
|
|
47
|
+
| `Bz2Validator` | `lib/wp2txt/bz2_validator.rb` | bz2ファイルの整合性を検証 |
|
|
48
|
+
| `CLI` | `lib/wp2txt/cli.rb` | コマンドラインオプションのパース |
|
|
49
|
+
|
|
50
|
+
### キャッシュクラス
|
|
51
|
+
|
|
52
|
+
| クラス | ファイル | 目的 |
|
|
53
|
+
|--------|----------|------|
|
|
54
|
+
| `GlobalDataCache` | `lib/wp2txt/global_data_cache.rb` | パース済みJSONデータファイルのSQLiteキャッシュ |
|
|
55
|
+
| `CategoryCache` | `lib/wp2txt/category_cache.rb` | Wikipediaカテゴリ階層のSQLiteキャッシュ |
|
|
56
|
+
| `IndexCache` | `lib/wp2txt/index_cache.rb` | マルチストリームインデックスエントリのSQLiteキャッシュ |
|
|
57
|
+
|
|
58
|
+
### 要素タイプ
|
|
59
|
+
|
|
60
|
+
`Article`クラスはMediaWikiテキストを型付き要素にパースします:
|
|
61
|
+
|
|
62
|
+
| タイプ | 説明 |
|
|
63
|
+
|--------|------|
|
|
64
|
+
| `:mw_heading` | セクション見出し (`== タイトル ==`) |
|
|
65
|
+
| `:mw_paragraph` | 通常のテキスト段落 |
|
|
66
|
+
| `:mw_table` | Wikiテーブル (`{| ... |}`) |
|
|
67
|
+
| `:mw_quote` | ブロッククォート |
|
|
68
|
+
| `:mw_pre` | 整形済みテキスト |
|
|
69
|
+
| `:mw_unordered` | 順序なしリスト項目 |
|
|
70
|
+
| `:mw_ordered` | 順序付きリスト項目 |
|
|
71
|
+
| `:mw_definition` | 定義リスト項目 |
|
|
72
|
+
| `:mw_link` | 単一行リンク |
|
|
73
|
+
| `:mw_ml_link` | 複数行リンク |
|
|
74
|
+
| `:mw_redirect` | リダイレクトページ |
|
|
75
|
+
| `:mw_template` | テンプレート |
|
|
76
|
+
| `:mw_isolated_tag` | HTMLタグ |
|
|
77
|
+
|
|
78
|
+
### マーカーシステム
|
|
79
|
+
|
|
80
|
+
コンテンツタイプマーカーは特殊コンテンツ(math、codeなど)をプレースホルダーに置き換えます:
|
|
81
|
+
|
|
82
|
+
```ruby
|
|
83
|
+
# utils.rb内
|
|
84
|
+
MARKER_TYPES = %i[math code chem table score timeline graph ipa].freeze
|
|
85
|
+
|
|
86
|
+
# 処理フロー:
|
|
87
|
+
# 1. コンテンツ検出 → プレースホルダーに置換 («« MATH »»)
|
|
88
|
+
# 2. テキスト処理続行(プレースホルダーはクリーンアップから保護)
|
|
89
|
+
# 3. finalize_markers() がプレースホルダーを [MARKER] 形式に変換
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### テンプレート展開
|
|
93
|
+
|
|
94
|
+
`TemplateExpander`クラス(`lib/wp2txt/template_expander.rb`)は一般的なWikipediaテンプレートを可読テキストに展開します:
|
|
95
|
+
|
|
96
|
+
| テンプレートタイプ | 例 | 出力 |
|
|
97
|
+
|--------------------|-----|------|
|
|
98
|
+
| 生年月日/没年月日 | `{{birth date|1990|5|15}}` | "May 15, 1990" |
|
|
99
|
+
| 単位変換 | `{{convert|100|km|mi}}` | "100 km (62 mi)" |
|
|
100
|
+
| 座標 | `{{coord|35|41|N|139|41|E}}` | "35°41′N 139°41′E" |
|
|
101
|
+
| 言語タグ | `{{lang|ja|日本語}}` | "日本語" |
|
|
102
|
+
| 仮名 | `{{nihongo|Tokyo|東京|Tōkyō}}` | "Tokyo (東京, Tōkyō)" |
|
|
103
|
+
|
|
104
|
+
テンプレート展開はデフォルトで有効です。`--no-expand-templates`または`expand_templates: false`で無効化できます。
|
|
105
|
+
|
|
106
|
+
### マジックワード展開
|
|
107
|
+
|
|
108
|
+
`MagicWordExpander`クラス(`lib/wp2txt/magic_words.rb`)はMediaWikiマジックワードを実際の値に展開します:
|
|
109
|
+
|
|
110
|
+
| カテゴリ | マジックワード | 例 |
|
|
111
|
+
|----------|----------------|-----|
|
|
112
|
+
| ページ文脈 | `PAGENAME`, `FULLPAGENAME`, `BASEPAGENAME`, `ROOTPAGENAME`, `SUBPAGENAME`, `NAMESPACE`, `TALKPAGENAME` | `{{PAGENAME}}` → "記事タイトル" |
|
|
113
|
+
| 日時 | `CURRENTYEAR`, `CURRENTMONTH`, `CURRENTDAY`, `CURRENTDAYNAME`, `CURRENTTIME`, `CURRENTTIMESTAMP` | `{{CURRENTYEAR}}` → "2024" |
|
|
114
|
+
| 文字列関数 | `lc`, `uc`, `lcfirst`, `ucfirst`, `urlencode`, `anchorencode`, `padleft`, `padright` | `{{uc:hello}}` → "HELLO" |
|
|
115
|
+
| パーサー関数 | `#titleparts` | `{{#titleparts:A/B/C\|2}}` → "A/B" |
|
|
116
|
+
|
|
117
|
+
マジックワードは`format_wiki()`パイプラインの早い段階で、configにtitleが指定されている場合に展開されます:
|
|
118
|
+
|
|
119
|
+
```ruby
|
|
120
|
+
result = format_wiki(text, title: "記事名", dump_date: Time.now)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## キャッシングインフラストラクチャ
|
|
124
|
+
|
|
125
|
+
WP2TXTはSQLiteベースのキャッシュを使用して、繰り返し実行時のパフォーマンスを向上させています。すべてのキャッシュは `~/.wp2txt/cache/` に保存されます。
|
|
126
|
+
|
|
127
|
+
### GlobalDataCache
|
|
128
|
+
|
|
129
|
+
パース済みJSONデータファイル(テンプレート、MediaWikiエイリアス、HTMLエンティティ)をキャッシュし、パースのオーバーヘッドを削減:
|
|
130
|
+
|
|
131
|
+
```ruby
|
|
132
|
+
# 自動 - データ読み込みメソッドは透過的にキャッシュを使用
|
|
133
|
+
data = Wp2txt.load_mediawiki_data # 有効であればキャッシュを使用
|
|
134
|
+
|
|
135
|
+
# 手動キャッシュ操作
|
|
136
|
+
Wp2txt::GlobalDataCache.clear! # キャッシュをすべてクリア
|
|
137
|
+
Wp2txt::GlobalDataCache.stats # キャッシュ統計を取得
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
キャッシュ検証:ソースファイルの変更時刻とサイズをチェックします。ソースファイルが変更されると自動的にキャッシュは無効化されます。
|
|
141
|
+
|
|
142
|
+
### CategoryCache
|
|
143
|
+
|
|
144
|
+
Wikipedia APIからのカテゴリ階層をキャッシュし、カテゴリベースの記事抽出を高速化:
|
|
145
|
+
|
|
146
|
+
```ruby
|
|
147
|
+
cache = Wp2txt::CategoryCache.new("en", cache_dir: "/path/to/cache")
|
|
148
|
+
|
|
149
|
+
# カテゴリデータを保存
|
|
150
|
+
cache.save("カテゴリ名", ["記事1", "記事2"], ["サブカテゴリ1"])
|
|
151
|
+
|
|
152
|
+
# カテゴリデータを取得
|
|
153
|
+
data = cache.get("カテゴリ名") # { pages: [...], subcats: [...] }
|
|
154
|
+
|
|
155
|
+
# カテゴリツリー内のすべてのページを取得
|
|
156
|
+
pages = cache.get_all_pages("ルートカテゴリ", max_depth: 2)
|
|
157
|
+
|
|
158
|
+
# 統計とメンテナンス
|
|
159
|
+
cache.stats # キャッシュ統計
|
|
160
|
+
cache.cleanup_expired! # 古いエントリを削除
|
|
161
|
+
cache.clear! # すべてクリア
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### IndexCache
|
|
165
|
+
|
|
166
|
+
パース済みマルチストリームインデックスエントリをキャッシュし、記事の高速検索を実現:
|
|
167
|
+
|
|
168
|
+
```ruby
|
|
169
|
+
cache = Wp2txt::IndexCache.new("/path/to/index.txt", cache_dir: "/path/to/cache")
|
|
170
|
+
|
|
171
|
+
# キャッシュの有効性を確認
|
|
172
|
+
cache.valid? # キャッシュが存在しソースファイルと一致する場合 true
|
|
173
|
+
|
|
174
|
+
# 保存/読み込み操作(MultistreamIndexで内部的に使用)
|
|
175
|
+
cache.save(entries_by_title, stream_offsets)
|
|
176
|
+
data = cache.load # { entries_by_title: {}, entries_by_id: {}, stream_offsets: [] }
|
|
177
|
+
|
|
178
|
+
# バッチ検索
|
|
179
|
+
results = cache.find_by_titles(["記事1", "記事2"])
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### キャッシュの場所
|
|
183
|
+
|
|
184
|
+
すべてのキャッシュは `~/.wp2txt/cache/` に保存されます:
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
~/.wp2txt/cache/
|
|
188
|
+
├── global_data.sqlite3 # GlobalDataCache
|
|
189
|
+
├── categories_en.sqlite3 # CategoryCache(英語)
|
|
190
|
+
├── categories_ja.sqlite3 # CategoryCache(日本語)
|
|
191
|
+
└── enwiki_*_index.sqlite3 # IndexCache(ダンプファイルごと)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## テストシステム
|
|
195
|
+
|
|
196
|
+
### テスト構造
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
spec/
|
|
200
|
+
├── spec_helper.rb # RSpec設定
|
|
201
|
+
├── article_spec.rb # 記事パーステスト
|
|
202
|
+
├── utils_spec.rb # テキスト処理テスト
|
|
203
|
+
├── markers_spec.rb # マーカー機能テスト
|
|
204
|
+
├── auto_download_spec.rb # CLIとダウンロードテスト
|
|
205
|
+
├── multilingual_spec.rb # 言語固有テスト
|
|
206
|
+
├── streaming_spec.rb # ストリーミングアーキテクチャテスト
|
|
207
|
+
└── testdata/ # 静的テストデータ
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### テストの実行
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# 全テストを実行
|
|
214
|
+
bundle exec rspec
|
|
215
|
+
|
|
216
|
+
# 特定のテストファイルを実行
|
|
217
|
+
bundle exec rspec spec/utils_spec.rb
|
|
218
|
+
|
|
219
|
+
# ドキュメント形式で実行
|
|
220
|
+
bundle exec rspec --format documentation
|
|
221
|
+
|
|
222
|
+
# 行番号で特定のテストを実行
|
|
223
|
+
bundle exec rspec spec/utils_spec.rb:42
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## マルチストリームサポート
|
|
227
|
+
|
|
228
|
+
WP2TXTは効率的な記事抽出のためにWikipediaのマルチストリーム形式をサポートしています。
|
|
229
|
+
|
|
230
|
+
### マルチストリームの仕組み
|
|
231
|
+
|
|
232
|
+
1. **インデックスファイル** (`-multistream-index.txt.bz2`): 記事タイトルをバイトオフセットにマッピング
|
|
233
|
+
2. **マルチストリームファイル** (`-multistream.xml.bz2`): 連結されたbz2ストリーム
|
|
234
|
+
|
|
235
|
+
### 並列抽出
|
|
236
|
+
|
|
237
|
+
`MultistreamReader`はパフォーマンス向上のための並列記事抽出をサポートしています:
|
|
238
|
+
|
|
239
|
+
```ruby
|
|
240
|
+
reader = MultistreamReader.new(multistream_path, index_path)
|
|
241
|
+
|
|
242
|
+
# 複数の記事を並列で抽出(デフォルト4プロセス)
|
|
243
|
+
results = reader.extract_articles_parallel(["東京", "京都", "大阪"], num_processes: 4)
|
|
244
|
+
|
|
245
|
+
# 並列処理でイテレート
|
|
246
|
+
reader.each_article_parallel(entries, num_processes: 4) do |page|
|
|
247
|
+
process(page)
|
|
248
|
+
end
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
記事はストリームオフセットでグループ化され、bz2解凍のオーバーヘッドを最小化します。
|
|
252
|
+
|
|
253
|
+
### 部分ダウンロード
|
|
254
|
+
|
|
255
|
+
特定の記事抽出では、WP2TXTは必要なデータのみをダウンロードします:
|
|
256
|
+
|
|
257
|
+
```ruby
|
|
258
|
+
# 最初のNストリームのみダウンロード
|
|
259
|
+
manager.download_multistream(max_streams: 10)
|
|
260
|
+
|
|
261
|
+
# 必要なバイト範囲のみダウンロード
|
|
262
|
+
download_file_range(url, path, start_byte, end_byte)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### 差分ダウンロード
|
|
266
|
+
|
|
267
|
+
部分ダンプが存在する場合、`download_multistream_full`はダウンロードを再開できます:
|
|
268
|
+
|
|
269
|
+
```ruby
|
|
270
|
+
manager = DumpManager.new("ja")
|
|
271
|
+
|
|
272
|
+
# 既存の部分ダンプを確認
|
|
273
|
+
partial = manager.find_any_partial_cache
|
|
274
|
+
# => { path: "...", dump_date: "20260101", stream_count: 100, size: 1000000, mtime: ... }
|
|
275
|
+
|
|
276
|
+
# 差分ダウンロードが可能か確認
|
|
277
|
+
resume_info = manager.can_resume_from_partial?(partial)
|
|
278
|
+
# => { possible: true, current_streams: 100, total_streams: 5000, current_size: 1000000 }
|
|
279
|
+
# => { possible: false, reason: :date_mismatch, partial_date: "20250101", latest_date: "20260101" }
|
|
280
|
+
|
|
281
|
+
# 差分ダウンロードサポート付きでフルダンプをダウンロード(対話式プロンプト)
|
|
282
|
+
path = manager.download_multistream_full(interactive: true)
|
|
283
|
+
|
|
284
|
+
# 非対話モード(ユーザープロンプトをスキップ、必要に応じて常に新規ダウンロード)
|
|
285
|
+
path = manager.download_multistream_full(interactive: false)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
差分ダウンロードのユーザープロンプト:
|
|
289
|
+
|
|
290
|
+
1. **同一日付の部分ダンプが存在:**
|
|
291
|
+
- `[Y]` ダウンロードを再開(残りのデータのみダウンロード)
|
|
292
|
+
- `[n]` 既存の部分ダンプをそのまま使用
|
|
293
|
+
- `[f]` 新規フルダンプをダウンロード
|
|
294
|
+
|
|
295
|
+
2. **古い部分ダンプが存在:**
|
|
296
|
+
- `[D]` 古い部分を削除して最新をダウンロード(推奨)
|
|
297
|
+
- `[k]` 古い部分を保持、最新を別途ダウンロード
|
|
298
|
+
- `[u]` 古い部分をそのまま使用(内容が古い可能性あり)
|
|
299
|
+
|
|
300
|
+
### 記事抽出フロー
|
|
301
|
+
|
|
302
|
+
```
|
|
303
|
+
1. インデックスファイルをダウンロード(英語版で約500MB)
|
|
304
|
+
2. インデックスをハッシュにロード(O(1)ルックアップ)
|
|
305
|
+
3. 記事オフセットを検索
|
|
306
|
+
4. ストリームオフセットでグループ化
|
|
307
|
+
5. 必要なストリームのみダウンロード
|
|
308
|
+
6. 特定の記事を抽出
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## メモリ管理
|
|
312
|
+
|
|
313
|
+
WP2TXTには大規模ダンプ処理のための適応型メモリ管理が含まれています:
|
|
314
|
+
|
|
315
|
+
### MemoryMonitor
|
|
316
|
+
|
|
317
|
+
`lib/wp2txt/memory_monitor.rb`でのクロスプラットフォームメモリ監視:
|
|
318
|
+
|
|
319
|
+
```ruby
|
|
320
|
+
# 現在のメモリ使用量を確認
|
|
321
|
+
stats = Wp2txt::MemoryMonitor.memory_stats
|
|
322
|
+
# => { current: 256000000, available: 8000000000, ... }
|
|
323
|
+
|
|
324
|
+
# 利用可能メモリに基づく最適バッファサイズを取得
|
|
325
|
+
buffer_size = Wp2txt::MemoryMonitor.optimal_buffer_size
|
|
326
|
+
# => 10485760 (10 MB)
|
|
327
|
+
|
|
328
|
+
# メモリが少ない場合GCをトリガー
|
|
329
|
+
Wp2txt::MemoryMonitor.gc_if_needed
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### StreamProcessorの適応的バッファリング
|
|
333
|
+
|
|
334
|
+
`StreamProcessor`はバッファサイズを動的に調整します:
|
|
335
|
+
|
|
336
|
+
```ruby
|
|
337
|
+
processor = Wp2txt::StreamProcessor.new(input_path, adaptive_buffer: true)
|
|
338
|
+
processor.each_page { |title, text| ... }
|
|
339
|
+
|
|
340
|
+
# 処理統計を監視
|
|
341
|
+
processor.stats
|
|
342
|
+
# => { pages_processed: 1000, bytes_read: 50000000, buffer_size: 10485760, ... }
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## bz2検証
|
|
346
|
+
|
|
347
|
+
`Bz2Validator`モジュールは処理前にbz2ファイルを検証します:
|
|
348
|
+
|
|
349
|
+
```ruby
|
|
350
|
+
# 完全検証(ヘッダー + 解凍テスト)
|
|
351
|
+
result = Wp2txt::Bz2Validator.validate("/path/to/file.bz2")
|
|
352
|
+
result.valid? # => true/false
|
|
353
|
+
result.error_type # => :invalid_magic, :too_small など
|
|
354
|
+
result.message # => "Invalid bz2 header..."
|
|
355
|
+
|
|
356
|
+
# クイック検証(ヘッダーのみ)
|
|
357
|
+
result = Wp2txt::Bz2Validator.validate_quick("/path/to/file.bz2")
|
|
358
|
+
|
|
359
|
+
# ファイル情報を取得
|
|
360
|
+
info = Wp2txt::Bz2Validator.file_info("/path/to/file.bz2")
|
|
361
|
+
# => { path: "...", size: 1000000, valid_header: true, version: "h", block_size: 9, ... }
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
## 新機能の追加
|
|
365
|
+
|
|
366
|
+
### 新しいマーカータイプの追加
|
|
367
|
+
|
|
368
|
+
1. `lib/wp2txt/utils.rb`の`MARKER_TYPES`に追加
|
|
369
|
+
2. `apply_markers()`に検出パターンを追加
|
|
370
|
+
3. `spec/markers_spec.rb`にテストを追加
|
|
371
|
+
|
|
372
|
+
### 新しいCLIオプションの追加
|
|
373
|
+
|
|
374
|
+
1. `lib/wp2txt/cli.rb`にオプション定義を追加
|
|
375
|
+
2. `validate_options!()`にバリデーションを追加
|
|
376
|
+
3. `bin/wp2txt`でオプションを処理
|
|
377
|
+
4. `spec/auto_download_spec.rb`にテストを追加
|
|
378
|
+
5. README.mdを更新
|
|
379
|
+
|
|
380
|
+
### 言語サポートの追加
|
|
381
|
+
|
|
382
|
+
1. カテゴリキーワード: `data/language_categories.json`
|
|
383
|
+
2. リダイレクトキーワード: `data/language_redirects.json`
|
|
384
|
+
3. スクリプト: `scripts/generate_language_data.rb`
|
|
385
|
+
|
|
386
|
+
## コードスタイル
|
|
387
|
+
|
|
388
|
+
- Ruby 2.6+互換性
|
|
389
|
+
- フローズンストリングリテラル (`# frozen_string_literal: true`)
|
|
390
|
+
- RuboCop設定は`.rubocop.yml`
|
|
391
|
+
- 全体でUTF-8エンコーディング
|
|
392
|
+
|
|
393
|
+
## Docker
|
|
394
|
+
|
|
395
|
+
Dockerイメージのビルドとプッシュ:
|
|
396
|
+
|
|
397
|
+
```bash
|
|
398
|
+
rake push # マルチアーキテクチャでビルドしDocker Hubにプッシュ
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
## リリースプロセス
|
|
402
|
+
|
|
403
|
+
1. `lib/wp2txt/version.rb`のバージョンを更新
|
|
404
|
+
2. CHANGELOG.mdを更新
|
|
405
|
+
3. フルテストスイートを実行: `bundle exec rspec`
|
|
406
|
+
4. gemをビルド: `gem build wp2txt.gemspec`
|
|
407
|
+
5. RubyGemsにプッシュ: `gem push wp2txt-*.gem`
|
|
408
|
+
6. Dockerイメージをプッシュ: `rake push`
|
|
409
|
+
7. GitHubリリースを作成
|
|
410
|
+
|
|
411
|
+
## 便利なリンク
|
|
412
|
+
|
|
413
|
+
- [MediaWikiマークアップリファレンス](https://www.mediawiki.org/wiki/Help:Formatting)
|
|
414
|
+
- [Wikipediaダンプダウンロード](https://dumps.wikimedia.org/)
|
|
415
|
+
- [マルチストリーム形式](https://meta.wikimedia.org/wiki/Data_dumps/FAQ#Why_are_there_multiple_files_for_a_single_dump?)
|
data/Dockerfile
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
|
-
FROM ruby:
|
|
1
|
+
FROM ruby:4.0.1-alpine3.23
|
|
2
2
|
|
|
3
3
|
WORKDIR /wp2txt
|
|
4
4
|
COPY . ./
|
|
5
|
-
RUN rm -
|
|
5
|
+
RUN rm -f Gemfile.lock
|
|
6
6
|
|
|
7
|
+
# Install dependencies (git is required by gemspec's `git ls-files`)
|
|
7
8
|
RUN apk update && \
|
|
8
9
|
apk upgrade && \
|
|
9
|
-
apk add --no-cache
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
apk add --no-cache \
|
|
11
|
+
linux-headers libxml2-dev make gcc libc-dev bash \
|
|
12
|
+
sqlite-dev git && \
|
|
13
|
+
apk add --no-cache -t .build-packages \
|
|
14
|
+
build-base curl-dev wget && \
|
|
15
|
+
git init && git add -A && \
|
|
16
|
+
bundle install -j4 && \
|
|
17
|
+
apk del .build-packages
|
|
12
18
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
# lbzip2 is not available as an Alpine package; build from source
|
|
20
|
+
RUN apk add --no-cache build-base wget && \
|
|
21
|
+
wget https://github.com/kjn/lbzip2/releases/download/v2.5/lbzip2-2.5.tar.gz -O lbzip2.tar.gz && \
|
|
22
|
+
tar -xf lbzip2.tar.gz && cd lbzip2-2.5 && \
|
|
23
|
+
./configure && make && make install && \
|
|
24
|
+
cd .. && rm -rf lbzip2* && \
|
|
25
|
+
apk del build-base wget
|
|
17
26
|
|
|
18
27
|
WORKDIR /
|
|
19
|
-
ENV PATH
|
|
28
|
+
ENV PATH=/wp2txt/bin:$PATH
|
|
20
29
|
CMD ["bash"]
|
data/Gemfile
CHANGED