GitHub Actions、GitHub PagesでSphinxお試し
概要
Sphinx、GitHub Actionsを使用してGitHub Pagesにドキュメントをデプロイするまでをやってみる。
内容
リポジトリ作成して、GitHub Pagesの「Source」を「GitHub Actions」に変更。
リポジトリにフォルダやファイルを作成していく。 今回は以下のようなフォルダ構成とした。
- .github/workflows/shinx.ymlにGitHub Actionsで実行する内容を記載
- docs以下にsphinxの設定ファイルconf.pyとベースのrstファイルのindex.rstを格納。
- src以下に自作モジュールを格納。
- 今回は以下からNumpyスタイルのDocStringを持ってきた。
- https://www.sphinx-doc.org/ja/master/usage/extensions/example_numpy.html
プッシュするとActionsのタブでビルドが走っていることがわかる。
設定からPagesの欄を見ると作成されたページへのリンクがある。
作成されたページは以下。
それっぽいがレイアウトこんな感じだっけ?という箇所もあり。 とりあえずデプロイまではできたのでOKとする・・・。
メモ
以下に公開している。
VSCodeサーバー機能を使用してWindowsで他ユーザーとして作業する
概要
作業
事前に別ユーザーを作成しておく(以下ではベースとなるユーザーの他にanorith347というユーザーを作成している)。
別ユーザーとしてログインしている状態でrunasコマンドで別ユーザーとしてコマンドプロンプトを起動する。
runas /user:anorith347 cmd
- 「runas」コマンドで他のユーザー権限でプログラムを実行する
VSCodeのCLIバージョンをダウンロードして、作業対象ユーザーのフォルダにコピーしておく。
以下コマンドでVSCodeをサーバーモードで起動。
code serve-web
表示されるURLで別ユーザーのVSCodeにアクセスできる。
メモ
もともとGit(というかGitHub)周りを別ユーザーで作業したくて、細かい設定するよりWindowsの別ユーザーとして環境作った方が間違いが少ないのでは?と思って調べた。意外と簡単にできて満足。
以下のページにあるように複数ユーザー同時GUI操作は結構大変&ライセンスにも気を付けなくちゃいけなさそう。VSCodeサーバーだけならその辺は気にしなくてよさそう。
QGISプラグイン開発の勉強(2)
概要
- 前回(https://anorith.hatenablog.com/entry/2023/10/28/234120)の続き
- プラグインのアイコン・ショートカット設定
- 画像を保存する処理の追加
参考
- ChatGPT
- GPT-4を使用しました。
- 記事の最後に少しコメントを記載しています。
アイコン設定とショートカット設定
前回のプラグインフォルダをそのまま使用します。フォルダにアイコン用の画像を格納します。
アイコンには以下の画像を使用しました。DALL·E3に白背景のアイコンを描いてもらい、ノイズ除去のためvectorizer.aiで一度ベクター化&pngで再保存して、白背景部分をPythonで透過に処理してアイコンにしました(AIに頼りすぎでは・・・?)。
まずインポート部分にアイコン設定用のモジュールを追加します。
from PyQt5.QtWidgets import QAction from PyQt5.QtGui import QIcon
次に__init__.py
のinitGui
の箇所を以下のように書き換えます。
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-minimal-plugin
- https://github.com/wonder-sk/qgis-minimal-plugin
- 最小限のプラグインに必要なものが記載されている。
- ドキュメント
バージョン情報
- 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://anorith.hatenablog.com/entry/2023/08/13/232556)のHTTPS対応版
- HTTPS対応は自己署名証明書とnginx(Docker不使用)で対応
手順(メモ)
前回のブログ内容と以下リンクを参考にやりました。
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)
概要
手順
ソースコードの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版の設定もできたら記事にしようと思います。
参考
- Dockerで雑にMastodonを起動する方法
- https://qiita.com/zembutsu/items/fd52a504321dd5d6f0b8
- わりとベースにしているかもしれない記事。mastodonのバージョンが古いのでいろいろ異なる。
- mastodon コマンド備忘録
- linuxserver/docker-mastodon(GitHub)
- Google Chrome redirecting localhost to https
- https://stackoverflow.com/questions/25277457/google-chrome-redirecting-localhost-to-https
- Chromeでlocalhostが見れない場合の参考?ぶっちゃけいろいろ試しても直らなった(記事中の画像はChrome内の別プロファイルで表示した)。
- Cannot find user role with that name
登記所備付地図データをGeoPackageにしてQGISで読み込む
概要
参考
- 法務省登記所備付地図データ(G空間情報センター)
- mojxml2geojson(GitHub)
- https://github.com/JDA-DM/mojxml2geojson
- 配布されているxmlをgeojsonに変換するPythonライブラリ。
- デジタル庁の仕事っぽい。
- 法務省地図XMLアダプトプロジェクト
- https://github.com/amx-project
- 今回は使用していないが、DLするのはこっちの方が楽そう。
- ベクトルタイルも配布してるっぽい:https://github.com/amx-project/a-spec
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に含まれないようにもできる。
フィルタに関するよさげなリンクメモ。