Skip to content

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

warpgeo — WARP に残された地理空間データを掘る

A toolkit for finding and retrieving geospatial data that survives only in WARP, the National Diet Library of Japan's web archive. It handles WARP's undocumented access path (collection-ID resolution, raw-byte retrieval, viewer-HTML detection) and records provenance for every file. Japanese docs below.

配布元のサイトが消え、Wayback Machine にも残っていない地理空間データが、 国立国会図書館の WARP(インターネット資料収集保存事業)にだけ現存していることがある。 それを見つけて、正しく取り出して、来歴を付けて保管するための道具。

汎用アーカイブクローラではない。 WARP に特化し、地理空間データを掘ることに特化している。

きっかけは mlit-groundwater-well-registry で、 国土交通省の地下水データベース2003年版(座標付きの深井戸 57,847点)を掘り出した作業だった。 配布元の tochi.mlit.go.jp は消滅し、Wayback にも地域別 zip は無く、 WARP が2009年に収集したものだけが現存していた。あの作業を汎用化したのがこれ。


なぜ専用の道具が要るのか

WARP から生データを取るのは、URLに id_ を挟むだけでは済まない。

$ curl -o /dev/null -w '%{http_code}\n' \
    'https://warp.ndl.go.jp/web/20090217012940id_/http://tochi.mlit.go.jp/.../kantou.zip'
500

生データを返すのは /{コレクションID}/{ts}id_/{原URL} だけで、そのコレクションIDは TimeMap にも API にも出てこない(閲覧用HTMLの iframe から抜くしかない)。 id_ を付け忘れると、zip を要求したのに閲覧用HTMLが 200 で返ってきて、 気づかず保存すると後段で原因不明の展開エラーになる。

こうした落とし穴を全部畳み込んであるのがこの道具。 仕様そのものは docs/warp-api-notes.md にまとめてあるので、 別の言語で実装したい人はそちらだけ読めばよい。

インストール

$ pip install git+https://github.com/shiwaku/ndl-warp-geospatial-data-fetcher.git

Python 3.11 以上。依存は httpx のみ。

発見・取得・素性判定に加え、GeoJSON への変換まで標準ライブラリだけで動く。 GDAL も geopandas も要らない。FlatGeobuf / GeoParquet と、 日本測地系からの実際の座標変換にだけ [convert] を足す。

$ pip install 'git+https://github.com/shiwaku/ndl-warp-geospatial-data-fetcher.git#egg=warpgeo[convert]'

使い方

自分が探しているデータを掘りたい人は docs/guide.md を読んでください。 探す・収集回を選ぶ・絞る・素性を確かめる、の判断基準を段階ごとに書いた手順書です。 以下はコマンドの早見表です。

段階実行が基本。search と discover は候補を出すだけで取得はしない。

# 1. 配布ページを探す(全文検索)
$ warpgeo search "地下水 データベース ダウンロード" --limit 20

# 2. 収集日時を確認する
$ warpgeo timemap http://tochi.mlit.go.jp/tockok/tochimizu/F9/data/kantou.zip
収集回: 14
  20041111072814  2004-11-11 07:28:14 UTC
  20090217012940  2009-02-17 01:29:40 UTC
  ...

# 2b. どの収集回が充実しているかを、落とさずに測って比べる
$ warpgeo timemap http://tochi.mlit.go.jp/tockok/tochimizu/F9/data/kantou.zip --sizes

# 3. 配布ページを辿って候補を集める
$ warpgeo discover http://tochi.mlit.go.jp/tockok/tochimizu/F9/download.html \
      --depth 0 -o work/manifest.jsonl

# 4. 欲しいものだけ、狙った収集回で取る(--dry-run で先に確認できる)
$ warpgeo fetch --manifest work/manifest.jsonl \
      --exclude '[0-9]*' --at 20090217012940 --output out/

# 5. 中身を開いて素性を確かめる(WARP には繋がない)
$ warpgeo identify

# 6. 現代の形式に変換する
$ warpgeo convert --to geojson -o out/

実例: 2003年版・地下水データベース

docs/recipes/ に置いてある手順をなぞると、先行事例と同じものが手に入る。

$ warpgeo discover http://tochi.mlit.go.jp/tockok/tochimizu/F9/download.html --depth 0
  [1] zip        http://tochi.mlit.go.jp/tockok/tochimizu/F9/data/kantou.zip
      «関東»
  ...
巡回 1 ページ / 失敗 0 / 候補 55 件(収集日時 20041111072814)

$ warpgeo fetch --manifest work/manifest.jsonl --exclude '[0-9]*' --at 20090217012940
--include/--exclude で除外: 47 件
  取得 kantou.zip  859,109 bytes  [zip]  @20090217012940
  ...
成功 8 / 失敗 0
コレクションID解決の節約: 7 リクエスト

--exclude で都道府県別(01.zip〜47.zip)を落とし、--at で 一覧ページとは別の収集回を指定している。一覧ページを辿る収集回と、 実体を取る収集回は別に選ぶ必要があり、これがこの道具で一番の勘所。

8本を展開すると合計 57,847 点。先行事例の記載値と一致する。

素性判定(identify)

取得したバイト列を開いて中身を確かめる。ここが単なるダウンローダとの差。

$ warpgeo identify
kantou.zip
  関東  [Shapefile] Point  11,361 件  cp932
      範囲 138.42186,33.10002 - 140.84361,37.10863
      測地系 JGD2000(変換済みフラグ列)/ EPSG:4612 / 測地系変換 不要
      ⚠ S_TKY2JGD が示すとおり測地系変換は済んでいる。**二重変換の禁止** —
        日本測地系とみなして再変換すると北483m・西334mずれる。
      座標品質 一意 4,936 / 同一地点 1,189 / 代表点の疑い 5,236(46.1%)
      注意 PH: 数値列の 77.2% が 0。空欄が 0 で埋められていれば真の 0 と区別できない
      註 prj が無い(座標系の宣言が原本に無い)

やっていること。

  • 展開 — zip / lzh / gzip / tar / 自己解凍 exe を再帰的に開く。 zip 内のファイル名が cp932 のまま入っていれば復元する(関東.shp が読めるようになる)
  • 形式判定 — 拡張子ではなく中身で決める。.shp と .dbf と .shx は 1つのデータセットとしてまとめる
  • 文字コード判定 — cp932 / euc-jp / utf-8。.cpg があれば推定より宣言を優先する
  • 測地系判定 — .prj、srsName、そして変換済みフラグ列(S_TKY2JGD 等)を見る。 根拠が無ければ「不明」と記録し、変換を下流に禁じる
  • 座標品質 — 同一座標に別の地名が積まれている行を「代表点の疑い」として数える
  • 列の欠陥 — 空欄が 0 で埋められた数値列、数値列への非数値の混入。 直さず、印を付けて残す

測地系を「不明」と言うこと

日本の経緯度データは、日本測地系(Tokyo)でも JGD2000 でも同じレンジに収まる。 座標値からは区別できない。 だから根拠が無ければ may_convert: false として、 下流が自動変換しないようにする。

先行事例では、変換済みのデータを未変換とみなして再変換した結果、 北483m・西334mの系統ズレが出た。判らないものを判ったことにしないのが、 この層で一番大事な仕事になっている。

判定結果は来歴付きで work/identify.jsonl に残る。 .lzh の展開だけは標準ライブラリでできないので、 pip install lhafile か lha/7z があれば使う(無ければ理由を添えて失敗として記録する)。

変換(convert)

$ warpgeo convert --to geojson -o out/
kantou.zip
  out/関東.geojson  11,361 地物  EPSG:4612 →(座標は変換なし) EPSG:4326
      根拠 JGD2000(変換済みフラグ列)
      註 S_TKY2JGD が示すとおり測地系変換は済んでいる。**二重変換の禁止** — …
      註 補助列 _position_quality は本ツールの導出であり原本には無い(代表点の疑い 46.1%)
      註 属性は原本のまま文字列で出している(数値化していない)

判らないものは変換しない。

$ warpgeo convert wells.zip -o out/
  断った wells: «wells» の測地系は「不明」。…
      根拠があるなら --assume-crs EPSG:4301(日本測地系)のように明示すること
$ echo $?
1

測地系変換をしてよいかは identify の判定が決め、変換層はそれを覆せません。 覆せるのは --assume-crs を明示したときだけで、そのときは 「利用者の指定による」と成果物に記録されます。 断ったデータセットは標準エラーに必ず出るので、 「出力に無い=元々無かった」と読み違えることがありません。

そのほかの約束。

  • 原本の欠陥は直さない。 属性は dbf に入っていた文字列のまま出す。 0.00 を数値の 0 に直すと、空欄由来の 0 と真の 0 が永久に区別できなくなる。 数値にしたい場合は --numeric を明示して選ぶ
  • 来歴は成果物に埋め込む。 GeoJSON なら warpgeo メンバとして本体に、 FlatGeobuf / GeoParquet なら併置する .provenance.json に
  • 導出した値には印を付ける。 座標の質は _position_quality (unique / site / fallback)という補助列になる。原本の列とは接頭辞で区別できる

GeoJSON への変換は依存なしで動く。 FlatGeobuf・GeoParquet と、日本測地系からの実際の座標変換だけは pip install 'warpgeo[convert]' が要る(無ければ理由を添えて断る)。 JGD2000 と WGS84 の差は実用上無視できるため、この間は座標を触らず宣言し直すだけにしてある。

収集回を選ぶ(timemap --sizes)

同じURLでも収集回によって中身は違う。配布開始直後でまだ一部しか置かれていない回、 サイト閉鎖の直前でファイルが消えている回、実体が揃っている回が混ざる。 TimeMap は日時しか返さないので、日時からは判らない。

$ warpgeo timemap http://example.go.jp/data/kantou.zip --sizes
収集回: 14(うち 5 回を実測)

  20041111072814  2004-11-11        12,043 bytes
      最大の回の半分未満(中身が欠けている可能性)
  20090217012940  2009-02-17       859,109 bytes ★ 推奨
  ...
  20110302012512  2011-03-02         4,210 bytes
      データではなくHTMLが返る(収集時点でファイルが無かった見込み)

生データURLへの HEAD が Content-Length を返すので、本文を落とさずに比べられる (docs/warp-api-notes.md §2.5)。 Content-Type が HTML なら、その回にはファイルが無かったと分かる。

自動選択はしない。 サイズは代用の指標にすぎず、中身が正しいかは identify でしか 判らない。道具は測って並べ、薦めるところまでにとどめる。 実測した回がすべて同じ大きさなら、そう言う(更新されていないファイルでは普通に起きる)。

1つの回を測るのに2リクエスト(閲覧用HTML + HEAD)かかる。既定は5回。

発見の3つの経路

WARP には Wayback の CDX API に相当するものが無く、 「このディレクトリ配下のURL全部」は原理的に引けない。だから経路を使い分ける。

経路 使いどころ 限界
timemap URLが分かっている URLが分からないと使えない
discover 配布ページが分かっている 起点が要る
search 何も分からない 本文テキストしか索引されていない。zip や shp は出てこず、配布ページが出る

search でデータファイルを直接探そうとしても出てこない。 配布ページを見つけて discover に渡す、というのが本筋。

来歴

取得物には必ず来歴が付く(work/index.jsonl)。 原URL・収集日時・コレクションIDの3点が揃っていれば、第三者が同じものを再取得できる。

{
  "original_url": "http://tochi.mlit.go.jp/tockok/tochimizu/F9/data/kantou.zip",
  "timestamp": "20090217012940",
  "memento_datetime": "2009-02-17T01:29:40+00:00",
  "warp_collection_id": "20090319",
  "warp_raw_url": "https://warp.ndl.go.jp/20090319/20090217012940id_/http://...",
  "sha256": "...", "size": 859109, "sniffed_format": "zip"
}

対応形式

warpgeo formats で一覧できる。2000年代前半の日本の官公庁サイトが相手なので、 現代のGIS形式だけでなく .lzh、自己解凍 .exe、.sima(SIMA)、.sfc(SXF)、 .dm(数値地図)、.mif(MapInfo)なども候補として拾う。

形式の知識は warpgeo/formats.py の1つの表に集約されている。 新しい形式への対応は、そこに1行足すだけで発見と素性判定の両方に効く。


WARP を利用するにあたって

この道具は WARP に負荷をかけないことを最優先に作られている。

  • WARP は「大規模・継続的なリクエストはIPブロックの対象」と案内している。 継続的に利用する場合は WARP に事前に連絡すること。 → https://warp.ndl.go.jp/info/WARP_help.html
  • 既定のアクセス間隔は 1リクエスト2秒・直列。並列取得はオプションとしても実装していない。
  • User-Agent は既定でこのリポジトリのURLを名乗る。WARP 側から誰が叩いているか分かるようにするため。
  • 取得済みのバイトは内容アドレスで保管し、再実行しても取り直さない。
  • WARP の robots.txt は一般のUAに対し /search /web/ /20 /collections/ を Disallow している。 本ツールは低レート・件数限定の調査利用を想定しており、網羅的なクロールに使うものではない。 この点を理解したうえで使うこと。

ライセンスと著作権

LICENSE の MIT ライセンスは本ソフトウェア(道具)にのみ適用される。 本ソフトウェアを用いて WARP から取得したコンテンツの著作権は、 元のコンテンツの権利者に帰属する。利用条件は取得物ごとに利用者が確認すること。

このリポジトリが含む WARP 由来のデータは、 tests/data/groundwater2003/ のテストデータだけ(4.6MB)。 国立国会図書館 WARP を通じて取得した国土交通省の資料であり、MIT ライセンスの対象外。 ネットワークに繋がずに実データで回帰テストを回すために置いている。 出典・収集日時・利用上の注意は 同ディレクトリの README に明記してある。

成果物としてデータを公開する場合は、 先行事例のように データ案件ごとに別リポジトリを立て、そこで権利関係と品質の但し書きを個別に書くことを勧める。 道具のリポジトリにデータを溜めるものではない。


文書

文書 読むとき
docs/guide.md 自分が探しているデータを掘りたいとき(手順書)
docs/recipes/ 最後まで通した実例を見たいとき
docs/warp-api-notes.md WARP の仕組みを知りたい・別の言語で実装したいとき
DESIGN.md なぜこの設計なのか、未解決の課題は何か

実装状況

層 内容 状態
Layer 1 discover(TimeMap / クロール / 全文検索) 実装済み
Layer 2 fetch(コレクションID解決・生バイト取得・来歴) 実装済み
Layer 3 identify(展開・文字コード・CRS・座標品質) 実装済み
Layer 4 convert(GeoJSON / FlatGeobuf / GeoParquet) 実装済み

設計の全体像は DESIGN.md。

開発

$ pip install -e '.[dev]'
$ pytest                 # オフラインテストのみ(WARP を叩かない)
$ pytest -m live         # WARP への疎通確認。手動でだけ実行する
$ ruff check .

CI は WARP にアクセスしない。記録済み応答(tests/fixtures/)と、 実際に取得したシェープファイル(tests/data/groundwater2003/)で回している。

テストデータを WARP から取り直したいときは:

$ python tests/data/groundwater2003/fetch.py --verify   # 手元の sha256 を突合するだけ
$ python tests/data/groundwater2003/fetch.py            # WARP から取り直す

About

国立国会図書館WARPにしか現存しない地理空間データを発見・取得する道具 / Find and retrieve geospatial data that survives only in Japan's NDL web archive (WARP)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages