elaws-parser 0.1.0__tar.gz

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.
@@ -0,0 +1,149 @@
1
+ Metadata-Version: 2.4
2
+ Name: elaws-parser
3
+ Version: 0.1.0
4
+ Summary: e-Gov法令検索の法令API v2を利用して法令データを取得し、テキスト形式およびYAML形式に変換するためのPythonツール群です。
5
+ Author-email: ToAmano <amanotomohito040@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/ToAmano/elaws-parser
8
+ Project-URL: Bug Tracker, https://github.com/ToAmano/elaws-parser/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Topic :: Text Processing :: Markup :: XML
13
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: requests
17
+ Provides-Extra: llm
18
+ Requires-Dist: langchain>=0.1; extra == "llm"
19
+ Requires-Dist: langchain-openai>=0.1; extra == "llm"
20
+ Requires-Dist: langgraph>=0.0.30; extra == "llm"
21
+ Requires-Dist: pydantic>=2.0; extra == "llm"
22
+ Requires-Dist: pyyaml>=6.0; extra == "llm"
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest; extra == "dev"
25
+ Requires-Dist: pre-commit; extra == "dev"
26
+ Requires-Dist: black; extra == "dev"
27
+ Requires-Dist: isort; extra == "dev"
28
+ Requires-Dist: mypy; extra == "dev"
29
+ Requires-Dist: flake8; extra == "dev"
30
+
31
+ # e-Gov法令API v2 ラッパー & 構造化コンバーター (`elaws-parser`)
32
+
33
+ このリポジトリは、[e-Gov法令検索](https://elaws.e-gov.go.jp/)の[法令API v2](https://developer.e-gov.go.jp/contents/law_api_v2_2)を利用して法令データを取得し、人間や機械が扱いやすいテキスト形式およびYAML形式に変換・抽出するためのPythonパッケージです。
34
+
35
+ ---
36
+
37
+ ## 主な機能
38
+
39
+ - **法令データの取得**: 法令タイトルをキーに、e-Gov法令API v2から法令のXMLデータを直接取得します。
40
+ - **XMLからテキストへの変換**: 取得した法令XMLを、読みやすいプレーンテキスト形式に構造を保ったまま変換します。
41
+ - **XMLからYAMLへの変換**: 法令XMLを、構造が分かりやすいYAML形式に変換します。プログラムでのパースや分析が容易になります。
42
+ - **LLM/LangGraphによる条文抽出**: LangGraphと大規模言語モデル(LLM)を活用して、特定の法令や施行規則から関連する条項を抽出し、要約・比較分析を行います。
43
+
44
+ ---
45
+
46
+ ## ディレクトリ構成
47
+
48
+ ```
49
+ .
50
+ ├── pyproject.toml # パッケージのビルド・設定ファイル (setuptools)
51
+ ├── requirements.txt # 基本依存ライブラリ
52
+ ├── src/
53
+ │ └── elaws_parser/ # パッケージソース
54
+ │ ├── __init__.py # パッケージエントリーポイント(公開API定義)
55
+ │ ├── hourei_apiv2.py # e-Gov法令API v2 クライアント
56
+ │ ├── text_converter.py # XMLからTextへの変換ロジック
57
+ │ ├── yaml_converter.py # XMLからYAMLへの変換ロジック
58
+ │ ├── law_extraction.py # LLMを用いた法令抽出(基本機能)
59
+ │ └── law_extraction_v2.py # LLMを用いた法令抽出(YAML構造・LangGraph版)
60
+ ├── notebooks/
61
+ │ └── examples/ # パッケージの動作確認・検証用 Jupyter Notebook群
62
+ └── data/ # 検証用に取得・生成された法令データ(xml, yaml, txt 等)
63
+ ```
64
+
65
+ ---
66
+
67
+ ## セットアップ
68
+
69
+ ### 1. リポジトリのクローン
70
+ ```bash
71
+ git clone <repository_url>
72
+ cd <repository_name>
73
+ ```
74
+
75
+ ### 2. パッケージのインストール
76
+ 本パッケージは、用途に合わせてインストールオプションを選択できます。
77
+
78
+ #### 基本機能(API取得・Text/YAML変換)のみを使用する場合:
79
+ ```bash
80
+ pip install -e .
81
+ ```
82
+
83
+ #### LLM/LangGraphを用いた抽出・要約機能も使用する場合:
84
+ ```bash
85
+ pip install -e .[llm]
86
+ ```
87
+
88
+ ---
89
+
90
+ ## 使用方法
91
+
92
+ ### 1. 法令データの取得と変換(基本機能)
93
+ 法令名(例:「電気事業法」)を指定して、XMLデータを取得し、テキスト形式とYAML形式で保存する基本的な例です。
94
+
95
+ ```python
96
+ from elaws_parser import (
97
+ get_lawid_from_lawtitle,
98
+ get_lawdata_from_law_id,
99
+ get_lawdata_from_lawname,
100
+ save_xml_string_to_file,
101
+ convert_xml_to_text,
102
+ convert_xml_to_yaml,
103
+ )
104
+
105
+ # 1. 法令名から直接法令のXMLデータを取得
106
+ law_title = "電気事業法"
107
+ xml_string = get_lawdata_from_lawname(law_title)
108
+
109
+ # 2. XMLをファイルに保存
110
+ save_xml_string_to_file(xml_string, f"data/{law_title}.xml")
111
+
112
+ # 3. Text形式に変換して保存
113
+ text_content = convert_xml_to_text(xml_string)
114
+ with open(f"data/{law_title}.txt", "w", encoding="utf-8") as f:
115
+ f.write(text_content)
116
+
117
+ # 4. YAML形式に変換して保存
118
+ yaml_content = convert_xml_to_yaml(xml_string)
119
+ with open(f"data/{law_title}.yaml", "w", encoding="utf-8") as f:
120
+ f.write(yaml_content)
121
+ ```
122
+
123
+ ### 2. LLMを用いた関連条文の抽出・要約
124
+ LLMおよびLangGraphを用いた高度な抽出機能のサンプルです(要 `pip install -e .[llm]`)。
125
+
126
+ ```python
127
+ from langchain_openai import ChatOpenAI
128
+ from elaws_parser import LegalExtractionConfig, create_legal_extraction_system
129
+
130
+ # LLMと設定の初期化
131
+ llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.1)
132
+ config = LegalExtractionConfig(llm=llm, prompts_dir="prompts")
133
+ system = create_legal_extraction_system(config)
134
+
135
+ # ※具体的な実行方法は notebooks/examples/ のノートブックを参照してください。
136
+ ```
137
+
138
+ ### 3. Jupyter Notebookによる実例
139
+ より具体的な使用方法や動作テストの例については、`notebooks/examples/` ディレクトリ配下にある各種ノートブックを参照してください。
140
+
141
+ - **[examples01_hourei_xml_converter.ipynb](notebooks/examples/examples01_hourei_xml_converter.ipynb)**: 基本的な変換機能の実例
142
+ - **[test_houreiapiv2.ipynb](notebooks/examples/test_houreiapiv2.ipynb)**: APIラッパーのテスト
143
+ - **[test_law_extraction_v2.ipynb](notebooks/examples/test_law_extraction_v2.ipynb)**: LangGraphを用いた条文抽出機能の実例
144
+
145
+ ---
146
+
147
+ ## 参考文献
148
+
149
+ - [e-Gov法令検索 法令API v2 仕様書 (Swagger UI)](https://laws.e-gov.go.jp/api/2/swagger-ui)
@@ -0,0 +1,119 @@
1
+ # e-Gov法令API v2 ラッパー & 構造化コンバーター (`elaws-parser`)
2
+
3
+ このリポジトリは、[e-Gov法令検索](https://elaws.e-gov.go.jp/)の[法令API v2](https://developer.e-gov.go.jp/contents/law_api_v2_2)を利用して法令データを取得し、人間や機械が扱いやすいテキスト形式およびYAML形式に変換・抽出するためのPythonパッケージです。
4
+
5
+ ---
6
+
7
+ ## 主な機能
8
+
9
+ - **法令データの取得**: 法令タイトルをキーに、e-Gov法令API v2から法令のXMLデータを直接取得します。
10
+ - **XMLからテキストへの変換**: 取得した法令XMLを、読みやすいプレーンテキスト形式に構造を保ったまま変換します。
11
+ - **XMLからYAMLへの変換**: 法令XMLを、構造が分かりやすいYAML形式に変換します。プログラムでのパースや分析が容易になります。
12
+ - **LLM/LangGraphによる条文抽出**: LangGraphと大規模言語モデル(LLM)を活用して、特定の法令や施行規則から関連する条項を抽出し、要約・比較分析を行います。
13
+
14
+ ---
15
+
16
+ ## ディレクトリ構成
17
+
18
+ ```
19
+ .
20
+ ├── pyproject.toml # パッケージのビルド・設定ファイル (setuptools)
21
+ ├── requirements.txt # 基本依存ライブラリ
22
+ ├── src/
23
+ │ └── elaws_parser/ # パッケージソース
24
+ │ ├── __init__.py # パッケージエントリーポイント(公開API定義)
25
+ │ ├── hourei_apiv2.py # e-Gov法令API v2 クライアント
26
+ │ ├── text_converter.py # XMLからTextへの変換ロジック
27
+ │ ├── yaml_converter.py # XMLからYAMLへの変換ロジック
28
+ │ ├── law_extraction.py # LLMを用いた法令抽出(基本機能)
29
+ │ └── law_extraction_v2.py # LLMを用いた法令抽出(YAML構造・LangGraph版)
30
+ ├── notebooks/
31
+ │ └── examples/ # パッケージの動作確認・検証用 Jupyter Notebook群
32
+ └── data/ # 検証用に取得・生成された法令データ(xml, yaml, txt 等)
33
+ ```
34
+
35
+ ---
36
+
37
+ ## セットアップ
38
+
39
+ ### 1. リポジトリのクローン
40
+ ```bash
41
+ git clone <repository_url>
42
+ cd <repository_name>
43
+ ```
44
+
45
+ ### 2. パッケージのインストール
46
+ 本パッケージは、用途に合わせてインストールオプションを選択できます。
47
+
48
+ #### 基本機能(API取得・Text/YAML変換)のみを使用する場合:
49
+ ```bash
50
+ pip install -e .
51
+ ```
52
+
53
+ #### LLM/LangGraphを用いた抽出・要約機能も使用する場合:
54
+ ```bash
55
+ pip install -e .[llm]
56
+ ```
57
+
58
+ ---
59
+
60
+ ## 使用方法
61
+
62
+ ### 1. 法令データの取得と変換(基本機能)
63
+ 法令名(例:「電気事業法」)を指定して、XMLデータを取得し、テキスト形式とYAML形式で保存する基本的な例です。
64
+
65
+ ```python
66
+ from elaws_parser import (
67
+ get_lawid_from_lawtitle,
68
+ get_lawdata_from_law_id,
69
+ get_lawdata_from_lawname,
70
+ save_xml_string_to_file,
71
+ convert_xml_to_text,
72
+ convert_xml_to_yaml,
73
+ )
74
+
75
+ # 1. 法令名から直接法令のXMLデータを取得
76
+ law_title = "電気事業法"
77
+ xml_string = get_lawdata_from_lawname(law_title)
78
+
79
+ # 2. XMLをファイルに保存
80
+ save_xml_string_to_file(xml_string, f"data/{law_title}.xml")
81
+
82
+ # 3. Text形式に変換して保存
83
+ text_content = convert_xml_to_text(xml_string)
84
+ with open(f"data/{law_title}.txt", "w", encoding="utf-8") as f:
85
+ f.write(text_content)
86
+
87
+ # 4. YAML形式に変換して保存
88
+ yaml_content = convert_xml_to_yaml(xml_string)
89
+ with open(f"data/{law_title}.yaml", "w", encoding="utf-8") as f:
90
+ f.write(yaml_content)
91
+ ```
92
+
93
+ ### 2. LLMを用いた関連条文の抽出・要約
94
+ LLMおよびLangGraphを用いた高度な抽出機能のサンプルです(要 `pip install -e .[llm]`)。
95
+
96
+ ```python
97
+ from langchain_openai import ChatOpenAI
98
+ from elaws_parser import LegalExtractionConfig, create_legal_extraction_system
99
+
100
+ # LLMと設定の初期化
101
+ llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.1)
102
+ config = LegalExtractionConfig(llm=llm, prompts_dir="prompts")
103
+ system = create_legal_extraction_system(config)
104
+
105
+ # ※具体的な実行方法は notebooks/examples/ のノートブックを参照してください。
106
+ ```
107
+
108
+ ### 3. Jupyter Notebookによる実例
109
+ より具体的な使用方法や動作テストの例については、`notebooks/examples/` ディレクトリ配下にある各種ノートブックを参照してください。
110
+
111
+ - **[examples01_hourei_xml_converter.ipynb](notebooks/examples/examples01_hourei_xml_converter.ipynb)**: 基本的な変換機能の実例
112
+ - **[test_houreiapiv2.ipynb](notebooks/examples/test_houreiapiv2.ipynb)**: APIラッパーのテスト
113
+ - **[test_law_extraction_v2.ipynb](notebooks/examples/test_law_extraction_v2.ipynb)**: LangGraphを用いた条文抽出機能の実例
114
+
115
+ ---
116
+
117
+ ## 参考文献
118
+
119
+ - [e-Gov法令検索 法令API v2 仕様書 (Swagger UI)](https://laws.e-gov.go.jp/api/2/swagger-ui)
@@ -0,0 +1,49 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "elaws-parser"
7
+ version = "0.1.0"
8
+ description = "e-Gov法令検索の法令API v2を利用して法令データを取得し、テキスト形式およびYAML形式に変換するためのPythonツール群です。"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ { name = "ToAmano", email = "amanotomohito040@gmail.com" },
14
+ ]
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Operating System :: OS Independent",
19
+ "Topic :: Text Processing :: Markup :: XML",
20
+ "Topic :: Software Development :: Libraries :: Python Modules",
21
+ ]
22
+
23
+ dependencies = [
24
+ "requests",
25
+ ]
26
+
27
+ [project.optional-dependencies]
28
+ llm = [
29
+ "langchain>=0.1",
30
+ "langchain-openai>=0.1",
31
+ "langgraph>=0.0.30",
32
+ "pydantic>=2.0",
33
+ "pyyaml>=6.0",
34
+ ]
35
+ dev = [
36
+ "pytest",
37
+ "pre-commit",
38
+ "black",
39
+ "isort",
40
+ "mypy",
41
+ "flake8",
42
+ ]
43
+
44
+ [project.urls]
45
+ "Homepage" = "https://github.com/ToAmano/elaws-parser"
46
+ "Bug Tracker" = "https://github.com/ToAmano/elaws-parser/issues"
47
+
48
+ [tool.setuptools.packages.find]
49
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,19 @@
1
+ from .hourei_apiv2 import (
2
+ get_lawid_from_lawtitle,
3
+ get_lawdata_from_law_id,
4
+ get_lawdata_from_lawname,
5
+ save_xml_string_to_file,
6
+ extract_sections_from_xml,
7
+ )
8
+ from .text_converter import convert_xml_to_text, LawXmlParser
9
+ from .yaml_converter import convert_xml_to_yaml, LawToYamlConverter
10
+
11
+ # LLM/LangGraph機能はオプショナル依存関係のため、インストールされていない場合は無視する
12
+ try:
13
+ from .law_extraction_v2 import (
14
+ LegalExtractionConfig,
15
+ create_legal_extraction_system,
16
+ YamlArticleExtractor,
17
+ )
18
+ except ImportError:
19
+ pass
@@ -0,0 +1,128 @@
1
+ """
2
+ eGovのAPI v2を利用して,法令を取得するコード
3
+ 取得した法令のxml構造を解析して,必要な情報を返す.
4
+ """
5
+
6
+ # TODO :: パーサーは,textのパーサーとyamlのパーサー
7
+
8
+ from __future__ import annotations
9
+
10
+ from functools import lru_cache
11
+ from typing import Dict, Literal
12
+ from xml.etree import ElementTree
13
+
14
+ import requests
15
+
16
+
17
+ @lru_cache
18
+ def get_lawid_from_lawtitle(
19
+ law_title: str, *, if_exact: bool = True
20
+ ) -> str | Dict[str, str]:
21
+ """APIから法令タイトルでヒットする法令IDを取得(完全一致のみ)"""
22
+ url = "https://laws.e-gov.go.jp/api/2/laws"
23
+ r = requests.get(url, params={"response_format": "xml", "law_title": law_title})
24
+ # XMLデータの解析
25
+ root = ElementTree.fromstring(r.content.decode(encoding="utf-8"))
26
+
27
+ laws_elem = root.find("laws")
28
+ if laws_elem is None:
29
+ print("Error: 'laws' element not found in response.")
30
+ return {}
31
+
32
+ counter = 0
33
+ law_dict = {} # 辞書{名称: 法令番号}の作成
34
+ for law in laws_elem.findall("law"): # loop over <law> elements
35
+ counter += 1
36
+
37
+ law_info = law.find("law_info")
38
+ revision_info = law.find("revision_info")
39
+
40
+ if law_info is None or revision_info is None:
41
+ continue # skip incomplete entries
42
+
43
+ law_id: str = law_info.findtext("law_id", default="(no id)")
44
+ law_num: str = law_info.findtext("law_num", default="(no number)")
45
+ lawtitle: str = revision_info.findtext("law_title", default="(no title)")
46
+
47
+ print(f"ID: {law_id}, Num: {law_num}, Title: {lawtitle}")
48
+ law_dict[lawtitle] = law_id
49
+ print(f"Number of laws: {counter}")
50
+ if if_exact:
51
+ return law_dict[law_title] # allow exact match
52
+ return law_dict # return all matches
53
+
54
+
55
+ def get_lawdata_from_law_id(law_id: str, output_type: Literal["xml", "list"]):
56
+ """法令IDから法令データを取得"""
57
+ url = f"https://laws.e-gov.go.jp/api/2/law_data/{law_id}"
58
+ r = requests.get(url, params={"response_format": "xml"})
59
+ if r.status_code != 200:
60
+ print(f"Error fetching law data for ID {law_id}: {r.status_code}")
61
+ return None
62
+ if output_type == "xml":
63
+ return r.content.decode(encoding="utf-8")
64
+
65
+ if output_type == "list":
66
+ # XMLデータの解析
67
+ root = ElementTree.fromstring(r.content.decode(encoding="utf-8"))
68
+ contents = [e.text.strip() for e in root.iter() if e.text]
69
+ return [t for t in contents if t]
70
+ raise ValueError(f"Supported output type is xml or list. Got {output_type}")
71
+
72
+
73
+ def get_lawdata_from_lawname(law_name: str) -> str:
74
+ """法令名から法令データを取得(完全一致のみ)"""
75
+ law_id: str = get_lawid_from_lawtitle(law_name, if_exact=True)
76
+ law_text: str = get_lawdata_from_law_id(law_id, "xml")
77
+ return law_text
78
+
79
+
80
+ def save_xml_string_to_file(xml_string: str, filename: str):
81
+ """save xml string to a file"""
82
+ with open(filename, "w", encoding="utf-8") as f:
83
+ f.write(xml_string)
84
+
85
+
86
+ def extract_sections_from_xml(xml_string: str) -> Dict[str, str | None | list[str]]:
87
+ """TOC, MainProvision,SupplProvisionの3つを取得"""
88
+ root = ElementTree.fromstring(xml_string)
89
+
90
+ # law_infoタグを取得
91
+ law_full_text = root.find("law_full_text")
92
+ if law_full_text is None:
93
+ raise ValueError("law_full_textタグが見つかりません")
94
+
95
+ # <Law> の中にある <LawBody> を探す
96
+ law = law_full_text.find("Law")
97
+ if law is None:
98
+ raise ValueError("<Law> タグが <law_full_text> 内に見つかりません")
99
+
100
+ law_body = law.find("LawBody")
101
+ if law_body is None:
102
+ raise ValueError("<LawBody> タグが <Law> 内に見つかりません")
103
+
104
+ # 対象の3つのタグを取得
105
+ toc = law_body.find("TOC")
106
+ main_prov = law_body.find("MainProvision")
107
+ suppl_provs = law_body.findall("SupplProvision")
108
+
109
+ return {
110
+ "TOC": (
111
+ ElementTree.tostring(toc, encoding="unicode") if toc is not None else None
112
+ ),
113
+ "MainProvision": (
114
+ ElementTree.tostring(main_prov, encoding="unicode")
115
+ if main_prov is not None
116
+ else None
117
+ ),
118
+ # "SupplProvision": (
119
+ # ElementTree.tostring(suppl_prov, encoding="unicode")
120
+ # if suppl_prov is not None
121
+ # else None
122
+ # ),
123
+ "SupplProvision": (
124
+ [ElementTree.tostring(s, encoding="unicode") for s in suppl_provs]
125
+ if suppl_provs
126
+ else None
127
+ ),
128
+ }