shw-geocoder 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.
- shw_geocoder-0.1.0/LICENSE +21 -0
- shw_geocoder-0.1.0/MANIFEST.in +4 -0
- shw_geocoder-0.1.0/PKG-INFO +96 -0
- shw_geocoder-0.1.0/README.md +70 -0
- shw_geocoder-0.1.0/pyproject.toml +36 -0
- shw_geocoder-0.1.0/setup.cfg +4 -0
- shw_geocoder-0.1.0/shw_geocoder/__init__.py +4 -0
- shw_geocoder-0.1.0/shw_geocoder/__main__.py +4 -0
- shw_geocoder-0.1.0/shw_geocoder/cli.py +175 -0
- shw_geocoder-0.1.0/shw_geocoder/geocoder.py +30 -0
- shw_geocoder-0.1.0/shw_geocoder.egg-info/PKG-INFO +96 -0
- shw_geocoder-0.1.0/shw_geocoder.egg-info/SOURCES.txt +14 -0
- shw_geocoder-0.1.0/shw_geocoder.egg-info/dependency_links.txt +1 -0
- shw_geocoder-0.1.0/shw_geocoder.egg-info/entry_points.txt +2 -0
- shw_geocoder-0.1.0/shw_geocoder.egg-info/requires.txt +1 -0
- shw_geocoder-0.1.0/shw_geocoder.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 zx
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: shw-geocoder
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Geocoder client for SHSMI address_search API
|
|
5
|
+
Author: zx
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: geocoder,geocoding,address,shsmi,csv
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
20
|
+
Classifier: Topic :: Utilities
|
|
21
|
+
Requires-Python: >=3.8
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: requests
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# shw-geocoder
|
|
28
|
+
|
|
29
|
+
A minimal PyPI package that wraps the SHSMI `address_search` geocoding API. **THIS PACKAGE IS SPECIFIC TO CERTAIN GEOCODING APIS AND IS NOT UNIVERSAL.**
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install shw-geocoder
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For local development:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install -e .
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Python API
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from shw_geocoder import geocode
|
|
47
|
+
|
|
48
|
+
result = geocode("your-address", "geocoder-url")
|
|
49
|
+
print(result["data"][0]["pointX"], result["data"][0]["pointY"])
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`geocode(address, base, result_count=3)` returns the raw JSON returned by the
|
|
53
|
+
service. When the address cannot be resolved, the payload's `count` field is `0`
|
|
54
|
+
and `data` is empty.
|
|
55
|
+
|
|
56
|
+
## CLI
|
|
57
|
+
|
|
58
|
+
The package exposes a `shw-geocoder` command.
|
|
59
|
+
|
|
60
|
+
### Single address
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
shw-geocoder --base "geocoder-url" \
|
|
64
|
+
--address "your-address"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Prints `x, y, accuracy, poi, room_count` to stdout.
|
|
68
|
+
|
|
69
|
+
### Batch (CSV in -> CSV out + log)
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
shw-geocoder --base "geocoder-url" \
|
|
73
|
+
--input addrs.csv \
|
|
74
|
+
--address-column address \
|
|
75
|
+
--output out.csv \
|
|
76
|
+
--log run.log
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- `out.csv` keeps every original column from `addrs.csv` and appends five new
|
|
80
|
+
columns: `x, y, accuracy, poi, room_count`. Failed rows leave these blank.
|
|
81
|
+
- `run.log` is a plain-text summary containing start/end time, elapsed seconds,
|
|
82
|
+
total / success / failed counts, and a breakdown by `accuracy` value.
|
|
83
|
+
|
|
84
|
+
### Arguments
|
|
85
|
+
|
|
86
|
+
| Flag | Required | Description |
|
|
87
|
+
|-------------------|----------|--------------------------------------------------------------|
|
|
88
|
+
| `--base` | yes | Full URL of the address_search endpoint |
|
|
89
|
+
| `--input` | batch | Input CSV path |
|
|
90
|
+
| `--address-column`| batch | Column name in the input CSV that holds the address |
|
|
91
|
+
| `--output` | batch | Output CSV path |
|
|
92
|
+
| `--log` | batch | Log file path |
|
|
93
|
+
| `--encoding` | no | Input CSV encoding (e.g. `utf-8`, `gbk`, `gb18030`); default `utf-8` |
|
|
94
|
+
| `--address` | single | Single address to geocode (printed to stdout) |
|
|
95
|
+
|
|
96
|
+
`--address` and the `--input` group are mutually exclusive.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# shw-geocoder
|
|
2
|
+
|
|
3
|
+
A minimal PyPI package that wraps the SHSMI `address_search` geocoding API. **THIS PACKAGE IS SPECIFIC TO CERTAIN GEOCODING APIS AND IS NOT UNIVERSAL.**
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install shw-geocoder
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
For local development:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install -e .
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Python API
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from shw_geocoder import geocode
|
|
21
|
+
|
|
22
|
+
result = geocode("your-address", "geocoder-url")
|
|
23
|
+
print(result["data"][0]["pointX"], result["data"][0]["pointY"])
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`geocode(address, base, result_count=3)` returns the raw JSON returned by the
|
|
27
|
+
service. When the address cannot be resolved, the payload's `count` field is `0`
|
|
28
|
+
and `data` is empty.
|
|
29
|
+
|
|
30
|
+
## CLI
|
|
31
|
+
|
|
32
|
+
The package exposes a `shw-geocoder` command.
|
|
33
|
+
|
|
34
|
+
### Single address
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
shw-geocoder --base "geocoder-url" \
|
|
38
|
+
--address "your-address"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Prints `x, y, accuracy, poi, room_count` to stdout.
|
|
42
|
+
|
|
43
|
+
### Batch (CSV in -> CSV out + log)
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
shw-geocoder --base "geocoder-url" \
|
|
47
|
+
--input addrs.csv \
|
|
48
|
+
--address-column address \
|
|
49
|
+
--output out.csv \
|
|
50
|
+
--log run.log
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- `out.csv` keeps every original column from `addrs.csv` and appends five new
|
|
54
|
+
columns: `x, y, accuracy, poi, room_count`. Failed rows leave these blank.
|
|
55
|
+
- `run.log` is a plain-text summary containing start/end time, elapsed seconds,
|
|
56
|
+
total / success / failed counts, and a breakdown by `accuracy` value.
|
|
57
|
+
|
|
58
|
+
### Arguments
|
|
59
|
+
|
|
60
|
+
| Flag | Required | Description |
|
|
61
|
+
|-------------------|----------|--------------------------------------------------------------|
|
|
62
|
+
| `--base` | yes | Full URL of the address_search endpoint |
|
|
63
|
+
| `--input` | batch | Input CSV path |
|
|
64
|
+
| `--address-column`| batch | Column name in the input CSV that holds the address |
|
|
65
|
+
| `--output` | batch | Output CSV path |
|
|
66
|
+
| `--log` | batch | Log file path |
|
|
67
|
+
| `--encoding` | no | Input CSV encoding (e.g. `utf-8`, `gbk`, `gb18030`); default `utf-8` |
|
|
68
|
+
| `--address` | single | Single address to geocode (printed to stdout) |
|
|
69
|
+
|
|
70
|
+
`--address` and the `--input` group are mutually exclusive.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "shw-geocoder"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Geocoder client for SHSMI address_search API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "zx" }]
|
|
13
|
+
keywords = ["geocoder", "geocoding", "address", "shsmi", "csv"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
21
|
+
"Programming Language :: Python :: 3.8",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Scientific/Engineering :: GIS",
|
|
27
|
+
"Topic :: Utilities",
|
|
28
|
+
]
|
|
29
|
+
dependencies = ["requests"]
|
|
30
|
+
|
|
31
|
+
[project.scripts]
|
|
32
|
+
shw-geocoder = "shw_geocoder.cli:main"
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.packages.find]
|
|
35
|
+
include = ["shw_geocoder*"]
|
|
36
|
+
exclude = ["tests*"]
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""Command-line entry point for shw-geocoder."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import csv
|
|
5
|
+
import sys
|
|
6
|
+
import time
|
|
7
|
+
from collections import Counter
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
|
|
10
|
+
from .geocoder import geocode
|
|
11
|
+
|
|
12
|
+
NEW_COLUMNS = ["x", "y", "accuracy", "poi", "room_count"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _extract(result: dict):
|
|
16
|
+
"""Return (x, y, accuracy, poi, room_count) from an API response, or None."""
|
|
17
|
+
if not result or result.get("count", 0) <= 0:
|
|
18
|
+
return None
|
|
19
|
+
data = result.get("data") or []
|
|
20
|
+
if not data:
|
|
21
|
+
return None
|
|
22
|
+
d = data[0]
|
|
23
|
+
return (
|
|
24
|
+
d.get("pointX"),
|
|
25
|
+
d.get("pointY"),
|
|
26
|
+
d.get("resultAccuracy"),
|
|
27
|
+
d.get("poiString"),
|
|
28
|
+
d.get("roomCount"),
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _progress(done: int, total: int):
|
|
33
|
+
if total <= 0:
|
|
34
|
+
return
|
|
35
|
+
pct = done * 100 // total
|
|
36
|
+
sys.stderr.write(f"\r[{done}/{total}] {pct}%")
|
|
37
|
+
sys.stderr.flush()
|
|
38
|
+
if done == total:
|
|
39
|
+
sys.stderr.write("\n")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _run_single(address: str, base: str) -> int:
|
|
43
|
+
try:
|
|
44
|
+
result = geocode(address, base)
|
|
45
|
+
except Exception as exc: # noqa: BLE001
|
|
46
|
+
print(f"geocode failed: {exc}", file=sys.stderr)
|
|
47
|
+
return 1
|
|
48
|
+
fields = _extract(result)
|
|
49
|
+
if fields is None:
|
|
50
|
+
print("no result", file=sys.stderr)
|
|
51
|
+
return 1
|
|
52
|
+
print("x={}, y={}, accuracy={}, poi={}, room_count={}".format(*fields))
|
|
53
|
+
return 0
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _run_batch(args) -> int:
|
|
57
|
+
start = datetime.now()
|
|
58
|
+
start_ts = time.time()
|
|
59
|
+
|
|
60
|
+
encoding = args.encoding
|
|
61
|
+
print(f"using encoding: {encoding}", file=sys.stderr)
|
|
62
|
+
try:
|
|
63
|
+
with open(args.input, newline="", encoding=encoding) as f:
|
|
64
|
+
reader = csv.DictReader(f)
|
|
65
|
+
fieldnames = list(reader.fieldnames or [])
|
|
66
|
+
rows = list(reader)
|
|
67
|
+
except UnicodeDecodeError as exc:
|
|
68
|
+
print(
|
|
69
|
+
f"error: failed to decode '{args.input}' as '{encoding}' ({exc}). "
|
|
70
|
+
f"The file's actual encoding does not match --encoding. "
|
|
71
|
+
f"Re-run with the correct --encoding (e.g. utf-8, gbk, gb18030).",
|
|
72
|
+
file=sys.stderr,
|
|
73
|
+
)
|
|
74
|
+
return 2
|
|
75
|
+
|
|
76
|
+
if args.address_column not in fieldnames:
|
|
77
|
+
print(
|
|
78
|
+
f"error: address column '{args.address_column}' not found in "
|
|
79
|
+
f"input CSV (columns: {fieldnames})",
|
|
80
|
+
file=sys.stderr,
|
|
81
|
+
)
|
|
82
|
+
return 2
|
|
83
|
+
|
|
84
|
+
total = len(rows)
|
|
85
|
+
success = 0
|
|
86
|
+
fail = 0
|
|
87
|
+
acc_counter = Counter()
|
|
88
|
+
|
|
89
|
+
out_fields = fieldnames + [c for c in NEW_COLUMNS if c not in fieldnames]
|
|
90
|
+
|
|
91
|
+
with open(args.output, "w", newline="", encoding="utf-8") as f:
|
|
92
|
+
writer = csv.DictWriter(f, fieldnames=out_fields)
|
|
93
|
+
writer.writeheader()
|
|
94
|
+
for i, row in enumerate(rows, 1):
|
|
95
|
+
address = row.get(args.address_column) or ""
|
|
96
|
+
try:
|
|
97
|
+
result = geocode(address, args.base)
|
|
98
|
+
except Exception: # noqa: BLE001
|
|
99
|
+
result = None
|
|
100
|
+
fields = _extract(result)
|
|
101
|
+
if fields is None:
|
|
102
|
+
fail += 1
|
|
103
|
+
acc_counter["<nan>"] += 1
|
|
104
|
+
else:
|
|
105
|
+
success += 1
|
|
106
|
+
x, y, acc, poi, room = fields
|
|
107
|
+
row["x"] = x
|
|
108
|
+
row["y"] = y
|
|
109
|
+
row["accuracy"] = acc
|
|
110
|
+
row["poi"] = poi
|
|
111
|
+
row["room_count"] = room
|
|
112
|
+
acc_counter[str(acc)] += 1
|
|
113
|
+
writer.writerow(row)
|
|
114
|
+
_progress(i, total)
|
|
115
|
+
|
|
116
|
+
end = datetime.now()
|
|
117
|
+
elapsed = time.time() - start_ts
|
|
118
|
+
_write_log(args.log, start, end, elapsed, total, success, fail, acc_counter)
|
|
119
|
+
return 0
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _write_log(path, start, end, elapsed, total, success, fail, acc_counter):
|
|
123
|
+
lines = [
|
|
124
|
+
"shw-geocoder run summary",
|
|
125
|
+
"========================",
|
|
126
|
+
f"Start: {start.strftime('%Y-%m-%d %H:%M:%S')}",
|
|
127
|
+
f"End: {end.strftime('%Y-%m-%d %H:%M:%S')}",
|
|
128
|
+
f"Elapsed: {elapsed:.1f} s",
|
|
129
|
+
f"Total: {total}",
|
|
130
|
+
f"Success: {success}",
|
|
131
|
+
f"Failed: {fail}",
|
|
132
|
+
"Accuracy breakdown:",
|
|
133
|
+
]
|
|
134
|
+
for acc, cnt in sorted(acc_counter.items()):
|
|
135
|
+
lines.append(f" {acc} : {cnt}")
|
|
136
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
137
|
+
f.write("\n".join(lines) + "\n")
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
141
|
+
p = argparse.ArgumentParser(prog="shw-geocoder", description=__doc__)
|
|
142
|
+
p.add_argument("--base", required=True, help="Full URL of the address_search endpoint")
|
|
143
|
+
|
|
144
|
+
group = p.add_mutually_exclusive_group(required=True)
|
|
145
|
+
group.add_argument("--input", help="Input CSV path (batch mode)")
|
|
146
|
+
group.add_argument("--address", help="Single address to geocode")
|
|
147
|
+
|
|
148
|
+
p.add_argument("--address-column", help="Column name holding the address in the input CSV")
|
|
149
|
+
p.add_argument("--encoding", default="utf-8", help="Input CSV encoding (e.g. utf-8, gbk, gb18030); default utf-8")
|
|
150
|
+
p.add_argument("--output", help="Output CSV path (batch mode)")
|
|
151
|
+
p.add_argument("--log", help="Log file path (batch mode)")
|
|
152
|
+
return p
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def main(argv=None) -> int:
|
|
156
|
+
args = build_parser().parse_args(argv)
|
|
157
|
+
|
|
158
|
+
if args.input:
|
|
159
|
+
missing = []
|
|
160
|
+
if not args.address_column:
|
|
161
|
+
missing.append("--address-column")
|
|
162
|
+
if not args.output:
|
|
163
|
+
missing.append("--output")
|
|
164
|
+
if not args.log:
|
|
165
|
+
missing.append("--log")
|
|
166
|
+
if missing:
|
|
167
|
+
print(f"error: batch mode requires {' '.join(missing)}", file=sys.stderr)
|
|
168
|
+
return 2
|
|
169
|
+
return _run_batch(args)
|
|
170
|
+
|
|
171
|
+
return _run_single(args.address, args.base)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
if __name__ == "__main__":
|
|
175
|
+
sys.exit(main())
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Thin client around the SHSMI address_search endpoint."""
|
|
2
|
+
|
|
3
|
+
import requests
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def geocode(address: str, base: str, result_count: int = 3, timeout: float = 10.0) -> dict:
|
|
7
|
+
"""Geocode a single address.
|
|
8
|
+
|
|
9
|
+
Parameters
|
|
10
|
+
----------
|
|
11
|
+
address:
|
|
12
|
+
The address text to search for.
|
|
13
|
+
base:
|
|
14
|
+
Full URL of the `address_search?parameters` endpoint.
|
|
15
|
+
result_count:
|
|
16
|
+
How many candidate results to request from the service.
|
|
17
|
+
timeout:
|
|
18
|
+
Per-request timeout in seconds.
|
|
19
|
+
|
|
20
|
+
Returns
|
|
21
|
+
-------
|
|
22
|
+
dict
|
|
23
|
+
The raw JSON payload returned by the service. When the address cannot
|
|
24
|
+
be resolved, the payload's ``count`` field is ``0`` and ``data`` is
|
|
25
|
+
empty.
|
|
26
|
+
"""
|
|
27
|
+
params = {"search_word": address, "result_count": result_count}
|
|
28
|
+
resp = requests.get(base, params=params, timeout=timeout)
|
|
29
|
+
resp.raise_for_status()
|
|
30
|
+
return resp.json()
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: shw-geocoder
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Geocoder client for SHSMI address_search API
|
|
5
|
+
Author: zx
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: geocoder,geocoding,address,shsmi,csv
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
20
|
+
Classifier: Topic :: Utilities
|
|
21
|
+
Requires-Python: >=3.8
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: requests
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# shw-geocoder
|
|
28
|
+
|
|
29
|
+
A minimal PyPI package that wraps the SHSMI `address_search` geocoding API. **THIS PACKAGE IS SPECIFIC TO CERTAIN GEOCODING APIS AND IS NOT UNIVERSAL.**
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install shw-geocoder
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For local development:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install -e .
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Python API
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from shw_geocoder import geocode
|
|
47
|
+
|
|
48
|
+
result = geocode("your-address", "geocoder-url")
|
|
49
|
+
print(result["data"][0]["pointX"], result["data"][0]["pointY"])
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`geocode(address, base, result_count=3)` returns the raw JSON returned by the
|
|
53
|
+
service. When the address cannot be resolved, the payload's `count` field is `0`
|
|
54
|
+
and `data` is empty.
|
|
55
|
+
|
|
56
|
+
## CLI
|
|
57
|
+
|
|
58
|
+
The package exposes a `shw-geocoder` command.
|
|
59
|
+
|
|
60
|
+
### Single address
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
shw-geocoder --base "geocoder-url" \
|
|
64
|
+
--address "your-address"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Prints `x, y, accuracy, poi, room_count` to stdout.
|
|
68
|
+
|
|
69
|
+
### Batch (CSV in -> CSV out + log)
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
shw-geocoder --base "geocoder-url" \
|
|
73
|
+
--input addrs.csv \
|
|
74
|
+
--address-column address \
|
|
75
|
+
--output out.csv \
|
|
76
|
+
--log run.log
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- `out.csv` keeps every original column from `addrs.csv` and appends five new
|
|
80
|
+
columns: `x, y, accuracy, poi, room_count`. Failed rows leave these blank.
|
|
81
|
+
- `run.log` is a plain-text summary containing start/end time, elapsed seconds,
|
|
82
|
+
total / success / failed counts, and a breakdown by `accuracy` value.
|
|
83
|
+
|
|
84
|
+
### Arguments
|
|
85
|
+
|
|
86
|
+
| Flag | Required | Description |
|
|
87
|
+
|-------------------|----------|--------------------------------------------------------------|
|
|
88
|
+
| `--base` | yes | Full URL of the address_search endpoint |
|
|
89
|
+
| `--input` | batch | Input CSV path |
|
|
90
|
+
| `--address-column`| batch | Column name in the input CSV that holds the address |
|
|
91
|
+
| `--output` | batch | Output CSV path |
|
|
92
|
+
| `--log` | batch | Log file path |
|
|
93
|
+
| `--encoding` | no | Input CSV encoding (e.g. `utf-8`, `gbk`, `gb18030`); default `utf-8` |
|
|
94
|
+
| `--address` | single | Single address to geocode (printed to stdout) |
|
|
95
|
+
|
|
96
|
+
`--address` and the `--input` group are mutually exclusive.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
shw_geocoder/__init__.py
|
|
6
|
+
shw_geocoder/__main__.py
|
|
7
|
+
shw_geocoder/cli.py
|
|
8
|
+
shw_geocoder/geocoder.py
|
|
9
|
+
shw_geocoder.egg-info/PKG-INFO
|
|
10
|
+
shw_geocoder.egg-info/SOURCES.txt
|
|
11
|
+
shw_geocoder.egg-info/dependency_links.txt
|
|
12
|
+
shw_geocoder.egg-info/entry_points.txt
|
|
13
|
+
shw_geocoder.egg-info/requires.txt
|
|
14
|
+
shw_geocoder.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
shw_geocoder
|