[go: up one dir, main page]
More Web Proxy on the site http://driver.im/

anorithのブログ

主にGIS系の記事を書く。

GitHub Actions、GitHub PagesでSphinxお試し

概要

SphinxGitHub Actionsを使用してGitHub Pagesにドキュメントをデプロイするまでをやってみる。

内容

リポジトリ作成して、GitHub Pagesの「Source」を「GitHub Actions」に変更。

リポジトリにフォルダやファイルを作成していく。 今回は以下のようなフォルダ構成とした。

  • .github/workflows/shinx.ymlにGitHub Actionsで実行する内容を記載
    • python環境にsphinxsphinx拡張機能をインストールしている
    • 静的ページの中身ができたらArtifactに登録し、それをPagesに反映している。
    • このあたりの内部挙動がどうなっているのかも勉強したいがとりあえずは動いているのでOK・・・。
  • docs以下にsphinxの設定ファイルconf.pyとベースのrstファイルのindex.rstを格納。
    • これらは「sphinx-quickstart」コマンドで作成したものをベースに適当に編集
    • GitHub Actionsではこれらのフォルダの下でドキュメント作成の作業を行う。
  • src以下に自作モジュールを格納。

プッシュするとActionsのタブでビルドが走っていることがわかる。

設定からPagesの欄を見ると作成されたページへのリンクがある。

作成されたページは以下。

それっぽいがレイアウトこんな感じだっけ?という箇所もあり。 とりあえずデプロイまではできたのでOKとする・・・。

メモ

以下に公開している。

VSCodeサーバー機能を使用してWindowsで他ユーザーとして作業する

概要

  • VSCodeサーバー機能を使用してWindowsで他ユーザーとして作業する

作業

事前に別ユーザーを作成しておく(以下ではベースとなるユーザーの他にanorith347というユーザーを作成している)。

別ユーザーとしてログインしている状態でrunasコマンドで別ユーザーとしてコマンドプロンプトを起動する。

runas /user:anorith347 cmd

VSCodeCLIバージョンをダウンロードして、作業対象ユーザーのフォルダにコピーしておく。

以下コマンドでVSCodeをサーバーモードで起動。

code serve-web

表示されるURLで別ユーザーのVSCodeにアクセスできる。

メモ

もともとGit(というかGitHub)周りを別ユーザーで作業したくて、細かい設定するよりWindowsの別ユーザーとして環境作った方が間違いが少ないのでは?と思って調べた。意外と簡単にできて満足。

以下のページにあるように複数ユーザー同時GUI操作は結構大変&ライセンスにも気を付けなくちゃいけなさそう。VSCodeサーバーだけならその辺は気にしなくてよさそう。

QGISプラグイン開発の勉強(2)

概要

参考

  • ChatGPT
    • GPT-4を使用しました。
    • 記事の最後に少しコメントを記載しています。

アイコン設定とショートカット設定

前回のプラグインフォルダをそのまま使用します。フォルダにアイコン用の画像を格納します。

アイコンには以下の画像を使用しました。DALL·E3に白背景のアイコンを描いてもらい、ノイズ除去のためvectorizer.aiで一度ベクター化&pngで再保存して、白背景部分をPythonで透過に処理してアイコンにしました(AIに頼りすぎでは・・・?)。

まずインポート部分にアイコン設定用のモジュールを追加します。

from PyQt5.QtWidgets import QAction
from PyQt5.QtGui import QIcon

次に__init__.pyinitGuiの箇所を以下のように書き換えます。

    def initGui(self):
        self.action = QAction('MyPluginAction', self.iface.mainWindow())

        icon_path = os.path.join(os.path.dirname(__file__), "icon.png")        
        self.action.setIcon(QIcon(icon_path))
        self.action.setShortcut("Ctrl+T")

        self.action.triggered.connect(self.run)
        self.iface.addToolBarIcon(self.action)

以下のようにアイコンが反映されました。オリジナルのアイコンだと一気にプラグイン作ってる感じが出ますね。

またショートカットCtrl+Tも使用してrunの処理が行えるようになっています。

画像保存プラグインの作成

インポート部分に必要なモジュールを追加します。

import os
from PyQt5.QtWidgets import QAction
from PyQt5.QtGui import QIcon
from qgis.core import QgsProject, QgsMapRendererParallelJob

runの中身を以下の内容をに書き換えます(ChatGPTの出力そのままです)。

    def run(self):
        # 現在のプロジェクトのファイルパスを取得
        project_path = QgsProject.instance().fileName()
        if not project_path:
            # プロジェクトが保存されていない場合は、処理を中止
            return
        
        # プロジェクトのディレクトリパスを取得
        project_directory = os.path.dirname(project_path)
        image_path = os.path.join(project_directory, "map_image.png")

        # 現在の地図の設定を取得
        map_settings = self.iface.mapCanvas().mapSettings()

        # レンダリングジョブを作成して地図を画像として保存
        job = QgsMapRendererParallelJob(map_settings)
        job.start()
        job.waitForFinished()
        image = job.renderedImage()

        image.save(image_path)

以下の状態でプラグインを実行します(アイコンクリックorCtrl+T)。

以下の画像がQGISプロジェクトと同じ箇所に保存されます。

思ったより簡単にできました。 画像保存の話は以前も書きましたが、こういう書き方もあるのだと勉強になりました(以前の記事:https://anorith.hatenablog.com/entry/2023/01/15/213632)。

ChatGPTについて

今回はChatGPT使って勉強してみましたが、ぶっちゃけブログ記事書く(見る)よりChatGPTに聞いた方がよくない?という気がしてきますね・・・。

チャットのログ:https://chat.openai.com/share/c5fea02b-6009-4b05-8317-bc11d9b643e7

ログの途中のショートカットのやりとりは別原因だったためスルーして下さい。

QGISプラグイン開発の勉強(1)

概要

参考

バージョン情報

  • QGISのバージョン: 3.22.14

プラグイン作成

最小構成のQGISプラグインを作ってプラグイン開発の勉強をしてみました。プラグイン作成は初めてです。上記の「qgis-minimal-plugin」を使用しました。

ネット上だとPlugin Builderを使った手順は多いですが、とりあえず触ってみる、という感じだけならこっちでも十分そうです(というか最初に手を付けるならこっちの方がいい気がします)。

とりあえずReadmeの手順に従ってプラグインフォルダの中にminimalフォルダを作成し、その中にmetadata.txt__init__.pyを作成します。

プラグインフォルダ:C:\Users\USER\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\minimal

両方中身もコピペしますが、__init__.pyはここにも書いておきます。

from PyQt5.QtWidgets import QAction, QMessageBox

def classFactory(iface):
    return MinimalPlugin(iface)


class MinimalPlugin:
    def __init__(self, iface):
        self.iface = iface

    def initGui(self):
        self.action = QAction('Go!', self.iface.mainWindow())
        self.action.triggered.connect(self.run)
        self.iface.addToolBarIcon(self.action)

    def unload(self):
        self.iface.removeToolBarIcon(self.action)
        del self.action

    def run(self):
        QMessageBox.information(None, 'Minimal plugin', 'Do something useful here')
  • classFactory__init__.pyに必須のクラスのようですね。
  • __init__, initGui, unloadプラグインクラスに必須のメソッドの様です。
  • initGuiプラグインが有効になったときに呼ばれるメソッドで、unloadプラグインが無効になったときに呼ばれるメソッドの様です。
  • どうやらここではGo!という名前(テキスト属性)でアクションを作成し、メッセージを表示するメソッドを紐づけてツールバーに追加するようです。

有効化してみます。

↓追加されました。アクションがプラグインツールバーに追加されたようです。

アクションをクリックすると以下のメッセージが表示されます。

とりあえず動作確認はできました。

変更の反映

自分でコードをいじって遊びたいのでコードの変更の反映方法を確認しておきます。

とりあえず「プラグインの管理とコンソール」で無効にして再度有効化すればよいようです。 initGUIの文字をGo?にしてみます。

    def initGui(self):
        self.action = QAction('Go?', self.iface.mainWindow())
        self.action.triggered.connect(self.run)
        self.iface.addToolBarIcon(self.action)

反映されました。

今のところQGISらしさが皆無なので、QGISのPythonAPIも使用してみます。 プラグイン開発2 · GIS実習オープン教材を参考にレイヤ数を表示してみます。

runの中身を以下のように変更して再度読み込みます。

    def run(self):
        cnt = self.iface.mapCanvas().layerCount()
        QMessageBox.information(None, 'Minimal plugin', f'layers: {cnt}')

レイヤ数が表示されました。

これだけで基本的なプラグインとして動かせるので色々遊べそうですね。

WSL2のDockerでmastodonを起動してみる(HTTPS)

概要

手順(メモ)

前回のブログ内容と以下リンクを参考にやりました。

https://gist.github.com/melroy89/6fe7d05bdc0cfd2153b77310abf62990

特に詰まることろはなかったので、メモ書き程度の内容を記載しておきます。

  • DBの準備

上記リンクの

docker-compose run --rm web bundle exec rails db:setup

の箇所は代わりに前回記事のマイグレーションのコマンドを実行した(違いは不明)。

  • 証明書の作成

証明書の作成はWSL上で以下のコマンドで実行。

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout nginx/ssl/server.key -out nginx/ssl/server.crt

参考にしたサイトがあったが忘れた(どこでも出てくるレベルのコマンドっぽいので実際に参考にしたサイトを後から探せなかった・・・)。

  • WSLのネットワークについて

WSLを再インストールした影響か、WSLから外部のネットワークへつながらなくなった。以下リンクを参考にしたところ解決した(mastodonの設定とは全く関係ない)。 - https://qiita.com/RIckyBan/items/87b558220d2bc5dd11cb

その他

HTTPS対応したことでアイコンや画像もちゃんと表示されるようになりました。

※画像はnijijourneyで生成したもの

WSL2のDockerでmastodonを起動してみる(HTTP)

概要

  • WSL上でDockerを使用してmastodonを起動
  • インターネットには公開しないローカルでのお試し用。
  • localhostへのアクセスとし、http通信のみで行う(SSLの設定はしない)。

手順

ソースコードのDL

作業用に適当なディレクトリを作成して作業します。

まずはGitHubからソースのダウンロードを行います。 この時点の最新の安定版である「stable-4.1」を使用します。

wget https://github.com/mastodon/mastodon/archive/refs/heads/stable-4.1.zip
unzip stable-4.1.zip
cd mastodon-stable-4.1

リポジトリごとDLしていますが、実際に使用するのは「.env.production.sample」ファイルと「docker-compose.yml」くらいです。

docker-compose.ymlの編集

dbの環境変数を「POSTGRES_USER: mastodon」「POSTGRES_DB: mastodon」「POSTGRES_PASSWORD: password」としてユーザーを設定します(ついでに「POSTGRES_HOST_AUTH_METHOD」も書き方を統一&「healthcheck」もちょっと修正)。

  db:
    restart: always
    image: postgres:14-alpine
    shm_size: 256mb
    networks:
      - internal_network
    healthcheck:
      # test: ['CMD', 'pg_isready', '-U', 'postgres']
      test: ['CMD', 'pg_isready', '-U', 'mastodon']
    volumes:
      - ./postgres14:/var/lib/postgresql/data
    environment:
      POSTGRES_HOST_AUTH_METHOD: trust
      POSTGRES_USER: mastodon
      POSTGRES_DB: mastodon
      POSTGRES_PASSWORD: password

HTTP通信をするためにコンテナ内部の設定ファイルを変更したいので「web」の実行時のコマンドに以下の内容を追加します。

sed 's/config.force_ssl = true/config.force_ssl = false/' /opt/mastodon/config/environments/production.rb > /opt/mastodon/config/environments/production.rb

また、環境変数にもHTTP通信用の設定を追加します。

    environment:
      HTTPS_LOCAL: 'false'

また、Dockerイメージのビルドを省略するために「build .」をコメントアウトします。「web」「streaming」「sidekiq」の3か所あります。

最終的に以下のようなdocker-composeファイルになります。

docker-compose.yml

version: '3'
services:
  db:
    restart: always
    image: postgres:14-alpine
    shm_size: 256mb
    networks:
      - internal_network
    healthcheck:
      # test: ['CMD', 'pg_isready', '-U', 'postgres']
      test: ['CMD', 'pg_isready', '-U', 'mastodon']
    volumes:
      - ./postgres14:/var/lib/postgresql/data
    environment:
      POSTGRES_HOST_AUTH_METHOD: trust
      POSTGRES_USER: mastodon
      POSTGRES_DB: mastodon
      POSTGRES_PASSWORD: password
  redis:
    restart: always
    image: redis:7-alpine
    networks:
      - internal_network
    healthcheck:
      test: ['CMD', 'redis-cli', 'ping']
    volumes:
      - ./redis:/data

  # es:
  #   restart: always
  #   image: docker.elastic.co/elasticsearch/elasticsearch:7.17.4
  #   environment:
  #     - "ES_JAVA_OPTS=-Xms512m -Xmx512m -Des.enforce.bootstrap.checks=true"
  #     - "xpack.license.self_generated.type=basic"
  #     - "xpack.security.enabled=false"
  #     - "xpack.watcher.enabled=false"
  #     - "xpack.graph.enabled=false"
  #     - "xpack.ml.enabled=false"
  #     - "bootstrap.memory_lock=true"
  #     - "cluster.name=es-mastodon"
  #     - "discovery.type=single-node"
  #     - "thread_pool.write.queue_size=1000"
  #   networks:
  #      - external_network
  #      - internal_network
  #   healthcheck:
  #      test: ["CMD-SHELL", "curl --silent --fail localhost:9200/_cluster/health || exit 1"]
  #   volumes:
  #      - ./elasticsearch:/usr/share/elasticsearch/data
  #   ulimits:
  #     memlock:
  #       soft: -1
  #       hard: -1
  #     nofile:
  #       soft: 65536
  #       hard: 65536
  #   ports:
  #     - '127.0.0.1:9200:9200'

  web:
    # build: .
    image: ghcr.io/mastodon/mastodon:v4.1.6
    restart: always
    env_file: .env.production
    command: bash -c "rm -f /mastodon/tmp/pids/server.pid; sed 's/config.force_ssl = true/config.force_ssl = false/' /opt/mastodon/config/environments/production.rb > /opt/mastodon/config/environments/production.rb; bundle exec rails s -p 3000"
    networks:
      - external_network
      - internal_network
    healthcheck:
      # prettier-ignore
      test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:3000/health || exit 1']
    ports:
      - '127.0.0.1:3000:3000'
    depends_on:
      - db
      - redis
      # - es
    volumes:
      - ./public/system:/mastodon/public/system
    environment:
      HTTPS_LOCAL: 'false'

  streaming:
    # build: .
    image: ghcr.io/mastodon/mastodon:v4.1.6
    restart: always
    env_file: .env.production
    command: node ./streaming
    networks:
      - external_network
      - internal_network
    healthcheck:
      # prettier-ignore
      test: ['CMD-SHELL', 'wget -q --spider --proxy=off localhost:4000/api/v1/streaming/health || exit 1']
    ports:
      - '127.0.0.1:4000:4000'
    depends_on:
      - db
      - redis

  sidekiq:
    # build: .
    image: ghcr.io/mastodon/mastodon:v4.1.6
    restart: always
    env_file: .env.production
    command: bundle exec sidekiq
    depends_on:
      - db
      - redis
    networks:
      - external_network
      - internal_network
    volumes:
      - ./public/system:/mastodon/public/system
    healthcheck:
      test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"]

  ## Uncomment to enable federation with tor instances along with adding the following ENV variables
  ## http_proxy=http://privoxy:8118
  ## ALLOW_ACCESS_TO_HIDDEN_SERVICE=true
  # tor:
  #   image: sirboops/tor
  #   networks:
  #      - external_network
  #      - internal_network
  #
  # privoxy:
  #   image: sirboops/privoxy
  #   volumes:
  #     - ./priv-config:/opt/config
  #   networks:
  #     - external_network
  #     - internal_network

networks:
  external_network:
  internal_network:
    internal: true

.env.productionの作成、設定

「.env.production.sample」をコピーして「.env.production」を作成します。

cp .env.production.sample .env.production

このファイルの設定に鍵の生成が必要なのですが、今回は公式とは別のlinuxserverが作成しているコンテナを使用します(生成さえできれば手段はなんでもよいので)。

「SECRET_KEY_BASE」「OTP_SECRET」に設定する値を生成するために以下のDockerイメージとコマンドを使用します。2回実行し表示された値をそれぞれ「SECRET_KEY_BASE」「OTP_SECRET」に設定します。

docker run --rm -it --entrypoint /bin/bash lscr.io/linuxserver/mastodon generate-secret

「VAPID_PRIVATE_KEY」「VAPID_PUBLIC_KEY」に設定する値を生成するために以下のコマンドを使用します。こちらはそのままコピペできる形で出力されます。

docker run --rm -it --entrypoint /bin/bash lscr.io/linuxserver/mastodon generate-vapid

その他以下のように設定します。

LOCAL_DOMAIN=localhost
REDIS_HOST=redis

DB_HOST=db
DB_USER=mastodon
DB_NAME=mastodon
DB_PASS=password

ES_ENABLED=false

S3_ENABLED=false

最終的には以下のようなファイルになります。

.env.production

# This is a sample configuration file. You can generate your configuration
# with the `rake mastodon:setup` interactive setup wizard, but to customize
# your setup even further, you'll need to edit it manually. This sample does
# not demonstrate all available configuration options. Please look at
# https://docs.joinmastodon.org/admin/config/ for the full documentation.

# Note that this file accepts slightly different syntax depending on whether
# you are using `docker-compose` or not. In particular, if you use
# `docker-compose`, the value of each declared variable will be taken verbatim,
# including surrounding quotes.
# See: https://github.com/mastodon/mastodon/issues/16895

# Federation
# ----------
# This identifies your server and cannot be changed safely later
# ----------
LOCAL_DOMAIN=localhost

# Redis
# -----
REDIS_HOST=redis
REDIS_PORT=6379

# PostgreSQL
# ----------
DB_HOST=db
DB_USER=mastodon
DB_NAME=mastodon
DB_PASS=password
DB_PORT=5432

# Elasticsearch (optional)
# ------------------------
ES_ENABLED=false
ES_HOST=localhost
ES_PORT=9200
# Authentication for ES (optional)
ES_USER=elastic
ES_PASS=password

# Secrets
# -------
# Make sure to use `rake secret` to generate secrets
# -------
SECRET_KEY_BASE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
OTP_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

# Web Push
# --------
# Generate with `rake mastodon:webpush:generate_vapid_key`
# --------
VAPID_PRIVATE_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
VAPID_PUBLIC_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

# Sending mail
# ------------
SMTP_SERVER=
SMTP_PORT=587
SMTP_LOGIN=
SMTP_PASSWORD=
SMTP_FROM_ADDRESS=notifications@example.com

# File storage (optional)
# -----------------------
S3_ENABLED=false
S3_BUCKET=files.example.com
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
S3_ALIAS_HOST=files.example.com

# IP and session retention
# -----------------------
# Make sure to modify the scheduling of ip_cleanup_scheduler in config/sidekiq.yml
# to be less than daily if you lower IP_RETENTION_PERIOD below two days (172800).
# -----------------------
IP_RETENTION_PERIOD=31556952
SESSION_RETENTION_PERIOD=31556952

DBの設定とアセットのコンパイル

以下のコマンドでDBのマイグレーションを行います。大量のログが出力されるので少し待ちます。

docker-compose run --rm web rails db:migrate

次にアセットのコンパイルを行います(作成済みのDockerイメージを使用する場合は不要という情報もありましたが念のため・・・)。

docker-compose run --rm web rails assets:precompile

コンテナの起動

以下コマンドでコンテナを起動します。

docker-compose  up -d

以下のようなログが出ます。

mastodon-stable-41_db_1 is up-to-date
mastodon-stable-41_redis_1 is up-to-date
Creating mastodon-stable-41_web_1       ... done
Creating mastodon-stable-41_streaming_1 ... done
Creating mastodon-stable-41_sidekiq_1   ... done

「docker ps」でコンテナを確認すると以下のようになっています(直後なのでまだhealth: startingですが・・・)。

c7f09f791613   ghcr.io/mastodon/mastodon:v4.1.6   "/usr/bin/tini -- no…"   24 seconds ago       Up 21 seconds (health: starting)   3000/tcp, 127.0.0.1:4000->4000/tcp   mastodon-stable-41_streaming_1
abfb7420b861   ghcr.io/mastodon/mastodon:v4.1.6   "/usr/bin/tini -- bu…"   24 seconds ago       Up 20 seconds (health: starting)   3000/tcp, 4000/tcp                   mastodon-stable-41_sidekiq_1
911368ee133a   ghcr.io/mastodon/mastodon:v4.1.6   "/usr/bin/tini -- ba…"   24 seconds ago       Up 20 seconds (health: starting)   127.0.0.1:3000->3000/tcp, 4000/tcp   mastodon-stable-41_web_1
ee657ada8db7   postgres:14-alpine                 "docker-entrypoint.s…"   About a minute ago   Up About a minute (healthy)                                             mastodon-stable-41_db_1
d982b142e1a4   redis:7-alpine                     "docker-entrypoint.s…"   About a minute ago   Up About a minute (healthy)                                             mastodon-stable-41_redis_1

ここで「http://localhost:3000/」にアクセスするとmastodonの画面が表示されます。

※普通に表示されることもありますが、chromeの設定やキャッシュによってHTTPSにリダイレクトされ「ERR_SSL_PROTOCOL_ERROR」が出ることもあります。その場合はシークレットモードだとアクセスできます。

ユーザーの作成とログイン

このままだとログインできないのでユーザーを作成します。メールサーバーを設定しておらず通常のようにユーザーの新規作成ができないのでコンテナに入って無理やり作成します。

以下のコマンドでコンテナに入ります。

docker exec -it mastodon-stable-41_web_1 /bin/bash

コンテナ内で以下のコマンドでユーザーを作成します。「confirmed 」はメール認証を省略するためのオプションです。

bundle exec bin/tootctl accounts create admin_user --email admin@localhost --confirmed --role Admin

※メアドは適当です。example.comだとはじかれたのでlocalhostにしています。ついでにAdmin権限を与えていますが、あまり意味はないです。

パスワードが表示されるので上のメアドと表示されたパスワードを使用してログインします。

ログインすると以下のような画面になります。

投稿もできます。

ただしアイコン画像などはリンクがhttpsで設定されているためか表示されません。 httpで確認できるのはこの程度っぽいですね。

その他コメント

特にHTTPS通信を回避するところでめちゃくちゃ詰まりました。最初はオレオレ証明書でやろうとしたりもしてましたが、ごちゃごちゃしてきたので一旦http通信で起動する方針にしました。最終的には比較的するっといけましたが、途中無駄にDockerのネットワークの仕様など調べて疲れました・・・。https版の設定もできたら記事にしようと思います。

参考

登記所備付地図データをGeoPackageにしてQGISで読み込む

概要

  • 登記所備付地図をGeoPackageにしてQGISで読み込む
  • 変換はpython(mojxml2geojson, geopandas)を使用する

参考

DLしたxmlをgeojsonに変換

公式からデータをDLする。

Python環境にmojxml2geojsonをインストールして、以下のスクリプトでDLしたzipを解凍してgeojsonに変換する。 (ブログに載せるほどのスクリプトでもないが・・・)

import os
import glob
import shutil
import subprocess

input_file = R"D:\Geo\touki\47201-3600.zip"
out_dir = R"D:\Geo\touki_out"

# DLしたzipを解凍
input_name = os.path.basename(input_file).split(".")[0]
temp_dir = os.path.join(os.path.dirname(input_file), input_name)
shutil.unpack_archive(input_file, temp_dir)

# 中身のzipを解凍
zip_path_list = glob.glob(os.path.join(temp_dir, "*.zip"))
xml_dir = os.path.join(out_dir, "xml", input_name)
for zip_path in zip_path_list:
    shutil.unpack_archive(zip_path, xml_dir)

# xmlをgeojsonに変換
xml_path_list =glob.glob(os.path.join(xml_dir, "*.xml")) 
for idx, xml_path in enumerate(xml_path_list):
    print(f"[{idx+1}/{len(xml_path_list)}] {os.path.basename(xml_path)}")
    cmd = ["mojxml2geojson", xml_path]
    subprocess.run(cmd)
  • xml -> geojsonの変換は結構遅い。大量にやるなら並列化したいところ。

geopandasでgeojsonをGeoPackageに変換

以下スクリプトでDLしたzipの単位でGeoPackageにまとめて保存する。

import os
import glob
import shutil
import geopandas as gpd
import pandas as pd

input_dir = R"D:\Geo\touki_out\xml\47201-3600" # 先ほどgeojsonに変換したディレクトリを指定
out_dir = R"D:\Geo\touki_out\gpkg"
os.makedirs(out_dir, exist_ok=True)

input_name = os.path.basename(input_dir)
geojson_path_list = glob.glob(os.path.join(input_dir, "*.geojson")) 
gdf_list = []
for idx, geojson_path in enumerate(geojson_path_list):
    print(f"[{idx+1}/{len(geojson_path_list)}] {os.path.basename(geojson_path)}")
    gdf = gpd.read_file(geojson_path)
    gdf = gdf[gdf["座標系"] != "任意座標系"]
    gdf_list.append(gdf.to_crs("epsg:4326"))
gdf = pd.concat(gdf_list)
out_path = os.path.join(out_dir, f"{input_name}.gpkg")
gdf.to_file(out_path, driver='GPKG', layer=input_name)  
  • 大したデータ量でもないのでGeoDataFrameの時点でまとめて一つのGeoDataFrameに してしまっている。大量に処理するなら小分けしてGeoPackageへの保存は追記モードでやった方がよさげ。
  • 任意座標系はあきらめる。
  • .to_crs("epsg:4326")をやっておかないと以下のようなエラーが出る場合がある。
ValueError: Cannot determine common CRS for concatenation inputs, got ['JGD2011', 'WGS 84']. Use `to_crs()` to transform geometries to the same CRS before merging.
  • 本当に少ししかやっていないので、なんかほかにも例外出るようなデータはあるかも・・・。

QGISで表示してみる

大字コードで色分けすると以下のような感じ。

QGISのフィルタでNOT "地番" LIKE '%地区外%'として地区外のデータは除外して表示している。xml -> geojsonの段階でmojxml2geojsonの実行オプションとして--excludeとしておけばそもそも地区外のデータをgeojsonに含まれないようにもできる。

フィルタに関するよさげなリンクメモ。