end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

vue.js ver.3 で global component を複数書く場合、<~ />のような単独タグはNG

どうやら、 vue.js ver.3 で グローバルコンポーネントを複数書く場合、 <comport-a />のような単独タグでなく、 <comport-a></comport-a> のように閉じタグを必要とするみたい。

<head>
  <meta charset="UTF-8">
  <title>end0tknr's vue.js sample</title>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" >
  <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vue@3.2.31"></script>
</head>
<body>
  <h1 class="bg-secondary text-white display-4 px-3">Vue3</h1>
  <div id="app" class="container">
    <p>{{ message }}</p>
    <bye></bye>
    <hello></hello>
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message : '※コンポーネントを表示する'
      }
    }
  }

  let app = Vue.createApp(appdata)

  app.component('hello', {
    template: '<p class="alert alert-primary">Hello!</p>'
  })
  app.component('bye', {
    template: '<p class="alert alert-primary">Bye!</p>'
  })

  app.mount('#app')
  </script>
</body>

install imagemagick to rhel8

convert HEIC/HEIF image file to jpeg by libheif & GD & php - end0tknr's kipple - web写経開発

先程の上記entry の関連です。

GD + libheif で、heic/heif->jpeg 変換できるのであれば、 imagemagick でも実施しようとしました。

が、imagemagick では動作せず、今回は諦めました。 (今後、imagemagickのverionがあがれば、できるのかもしれません)

install ImageMagick ImageMagick-devel

$ sudo su -

# yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
# ARCH=$( /bin/arch )
# subscription-manager repos --enable "codeready-builder-for-rhel-8-${ARCH}-rpms"
Repository 'codeready-builder-for-rhel-8-x86_64-rpms' is enabled for this system.

# yum install ImageMagick ImageMagick-devel

install php-pear & imagick

# yum install php-pear
# pecl install imagick
  :
Build process completed successfully
Installing '/usr/lib64/php/modules/imagick.so'
Installing '/usr/include/php/ext/imagick/php_imagick_shared.h'
install ok: channel://pecl.php.net/imagick-3.7.0
configuration option "php_ini" is not set to php.ini location
You should add "extension=imagick.so" to php.ini

$ sudo vi /etc/php.ini
  extension=imagick.so ##<--ADD

$ php -r 'phpinfo();' | grep imagick
imagick
imagick module => enabled
imagick module version => 3.7.0
imagick classes => Imagick, ImagickDraw, ImagickPixel, ImagickPixelIterator, ImagickKernel
imagick.allow_zero_dimension_images => 0 => 0
imagick.locale_fix => 0 => 0
imagick.progress_monitor => 0 => 0
imagick.set_single_thread => 1 => 1
imagick.shutdown_sleep_count => 10 => 10
imagick.skip_version_check => 0 => 0

imagemagick では、heic/heif を認識せず...

imagemagick に付属する identify や convert コマンドで 試してみました。

## identifyで HEIFやHIECが表示されず...
$ /usr/bin/identify -list format | grep -i HEIF

## convert でも、jpeg に変換できず...

$ /usr/bin/convert IMG_0829.HEIC IMG_0829.JPG
convert: no decode delegate for this image format `HEIC' @ error/constitute.c/ReadImage/566.
convert: no images defined `IMG_0829.JPG' @ error/convert.c/ConvertImageCommand/3226.

convert HEIC/HEIF image file to jpeg by libheif & GD & php

最近の iphone(ios)では、画像ファイルに HEIC/HEIF を使用するようですが、 windows10では、これに対応していません。

なので、rhel8 に libheif をインストールし、 GD & phpjpeg化しました。

install libheif & libde265

libheif は、rhel8 の標準パッケージ(yum install)として 提供されていないらしく、sourceからinstallを行います。

また、libheif は libde265 に依存するようですので、併せて installします。

$ wget https://github.com/strukturag/libde265/archive/refs/tags/v1.0.8.tar.gz
$ ./autogen.sh
$ ./configure
$ make
$ sudo make install

$ wget https://github.com/strukturag/libheif/archive/refs/tags/v1.12.0.tar.gz

## 単純な configure ; make では、libde265 を認識しない為
## 以下の 環境変数を設定

$ export libde265_CFLAGS="-I/usr/local/include"
$ export libde265_LIBS="-L/usr/local/lib -lde265 -lstdc++"

$ ./autogen.sh
$ ./configure
$ make
$ sudo make install

## すると、以下の 4コマンドがインストールされます。

$ ls -l /usr/local/bin/heif-*
-rwxr-xr-x 1 404088 Feb 15 /usr/local/bin/heif-convert
-rwxr-xr-x 1 460576 Feb 15 /usr/local/bin/heif-enc
-rwxr-xr-x 1 172840 Feb 15 /usr/local/bin/heif-info
-rwxr-xr-x 1 232872 Feb 15 /usr/local/bin/heif-thumbnailer

convert heic->jpeg by heif-convert

libheifに付属する heif-convert コマンドでの heic->jpeg 変換も可能です。

$ /usr/local/bin/heif-convert IMG_0829.HEIC IMG_0829.JPG
File contains 1 images
Written to IMG_0829.JPG

convert heic->jpeg by GD & php

$ sudo yum install php-gd

$ php -r 'phpinfo();' | grep GD
GD Support => enabled
GD headers Version => 2.2.5
GD library Version => 2.2.5
<?php

$org_file = 'IMG_0829.JPG';
//$org_file = 'IMG_0829.HEIC';

echo filesize($org_file) , " bytes\n";

$org_img_info = getimagesize($org_file);
echo print_r($org_img_info,true);

$org_image = imagecreatefromjpeg($org_file);
$new_image = imagecreatetruecolor(
    $org_img_info[0] * 0.8,
    $org_img_info[1] * 0.8 );

imagecopyresampled(
    $new_image,
    $org_image,
    0,0, // copy先の座標
    0,0, // copy元の座標
    $org_img_info[0] * 0.8, // copy先のsize
    $org_img_info[1] * 0.8, //  〃
    $org_img_info[0],       // copy元のsize
    $org_img_info[1]);      //  〃

imagejpeg($new_image , 'NEW.JPG');

psycopg2 for python3 による postgresql 操作

先程の entry の postgres版。

今回のpostgresも /usr/local/pgsql へ、source install していますので、 通常の pip3 インストールとは、少々、手順が異なります。

https://pypi.org/project/psycopg2/

install psycopg2 for python3

$ sudo su - 
$ export PATH="/usr/local/pgsql/bin:$PATH"

# pip3 install psycopg2

$ sudo vi /etc/ld.so.conf
  /usr/local/pgsql/lib ##<--ADD
$ sudo ldconfig

sample code of psycopg2 for python3

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import psycopg2

def main():
    db_conn = psycopg2.connect(
        'postgresql://testuser:testuser@localhost:5432/springvue')
    #                 USER      PASSWD                   DB_NAME
    
    db_cur = db_conn.cursor()

    sql = "select * from test where id in (%s,%s,%s)"
    #sql = "select * from test"

    try:
        db_cur.execute(sql,('1','2','3'))
#        db_cur.execute(sql)
    except Exception as e:
        print(e)
        return
    
    # db_cur.execute(sql)

    ret_rows = db_cur.fetchall()
    # connection.commit()

    for row in ret_rows:
        print(row)
 
    db_cur.close()
    db_conn.close()
    

if __name__ == '__main__':
    main()

mysqlclient ( MySQLdb ) for python3 による mysql 操作

https://pypi.org/project/mysqlclient/

python3 + mysql8 + centos7.9 の手習い。

目次

install mysqlclient ( MySQLdb )

mysqlclient は、インストール時に mysql_config を参照しますが、 「pip3 install mysqlclient」によるインストールでは、 「/bin/sh: mysql_config: command not found」エラーとなる為 mysqlclient-2.1.0.tar.gz を wget し、local install しています。

$ mkdir pip_packages
$ cd pip_packages
$ wget https://files.pythonhosted.org/packages/de/79/<略>/mysqlclient-2.1.0.tar.gz
$ tar -xvf mysqlclient-2.1.0.tar.gz

$ vi mysqlclient-2.1.0/site.cfg
  old) #mysql_config = /usr/local/bin/mysql_config
  new) mysql_config = /usr/local/mysql/bin/mysql_config
$ tar -xcvf mysqlclient-2.1.0.tar.gz mysqlclient-2.1.0

$ cd ..
$ sudo pip3 install --no-index --find-links=./pip_packages mysqlclient

$ sudo vi /etc/ld.so.conf
  /usr/local/mysql/lib   ## <--ADD
$ sudo ldconfig

試していませんが、以下でのインストールできたのかもしれません...

$ sudo su -
# export PATH="/usr/local/mysql/bin:$PATH"
# pip3 install mysqlclient

sample code of mysqlclient ( MySQLdb ) for python3

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import MySQLdb

def main():
    db_conn = MySQLdb.connect(
        host='localhost',
        user='wordpress',
        passwd='wordpress',
        db='wordpress')
    db_cur = db_conn.cursor()

    sql = "select * from wp_users where id in (%s,%s,%s)"
    # sql = "select * from wp_users"

    try:
        db_cur.execute(sql,(1,2,3))
    except Exception as e:
        print(e)
        return
    
    # db_cur.execute(sql)

    ret_rows = db_cur.fetchall()
    # connection.commit()

    for row in ret_rows:
        print(row)
 
    db_cur.close()
    db_conn.close()
    

if __name__ == '__main__':
    main()

apache maven (mvn) for java の手習い

re: Javaビルドツール入門 Maven / Gradle / SBT / Bazel 対応 - end0tknr's kipple - web写経開発

すっかり忘れてしまっていますので、上記entryに対しての自分用メモです。

目次

コマンド一覧

No コマンド 内容
0 sudo yum install maven インストール
1 mvn archetype:generate プロジェクト作成
2 mvn compile コンパイル
3 mvn test-compile テスト群のコンパイル
4 mvn test テスト群の実行
5 mvn package パッケージ作成(jar,war)
6 mvn clean = make clean
7 mvn exec:java メインクラスの実行
8 mvn eclipse:eclipse maven->eclipseプロジェクト化
9 mvn eclipse:to-maven eclipse->mavenプロジェクト化
10 mvn eclipse:clean eclipse->mavenプロジェクト化?
11 mvn install ローカルリポジトリへの登録
12 mvn jetty:run jetty-maven-pluginでのweb実行

1.mvn archetype:generate - プロジェクト作成

対話方式 -「--batch-mode」なし

$ mvn archetype:generate
  :
1864: remote -> org.apache.maven.archetypes:maven-archetype-quickstart
                (An archetype which contains a sample Maven project.)
  :
Choose a number or apply filter
  (format: [groupId:]artifactId, case sensitive contains): 1864: 
Choose org.apache.maven.archetypes:maven-archetype-quickstart version: 
1: 1.0-alpha-1
<略>
4: 1.0-alpha-4
5: 1.0
<略>
8: 1.4
Choose a number: 8: 
Define value for property 'groupId': jp.end0tknr
Define value for property 'artifactId': javaci
Define value for property 'version' 1.0-SNAPSHOT: : 
Define value for property 'package' jp.end0tknr: : 
  :
$ find javaci -type f
javaci/pom.xml
javaci/src/main/java/jp/end0tknr/App.java
javaci/src/test/java/jp/end0tknr/AppTest.java

バッチ方式 -「--batch-mode」あり

$ mvn archetype:generate \
    --batch-mode \
    -DarchetypeArtifactId=maven-archetype-quickstart \
    -DgroupId=jp.end0tknr \
    -DartifactId=javaci \
    -Dversion=1.0-SNAPSHOT \
    -Dpackage=jp.end0tknr

2 mvn compile コンパイル

$ cd javaci/
$ find . -type f
./pom.xml
./src/main/java/jp/end0tknr/App.java
./src/test/java/jp/end0tknr/AppTest.java

$ mvn compile

$ find . -type f
./pom.xml
./src/main/java/jp/end0tknr/App.java
./src/test/java/jp/end0tknr/AppTest.java
<略>
./target/classes/jp/end0tknr/App.class

3 mvn test-compile テスト群のコンパイル

$ mvn test-compile

$ find . -type f
./pom.xml
./src/main/java/jp/end0tknr/App.java
./src/test/java/jp/end0tknr/AppTest.java
<略>
./target/classes/jp/end0tknr/App.class
./target/test-classes/jp/end0tknr/AppTest.class

5 mvn package パッケージ作成(jar,war)

$ mvn package

$ find . -type f
./pom.xml
./src/main/java/jp/end0tknr/App.java
./src/test/java/jp/end0tknr/AppTest.java
<略>
./target/classes/jp/end0tknr/App.class
./target/test-classes/jp/end0tknr/AppTest.class
./target/surefire-reports/jp.end0tknr.AppTest.txt
./target/surefire-reports/TEST-jp.end0tknr.AppTest.xml
./target/maven-archiver/pom.properties
./target/javaci-1.0-SNAPSHOT.jar

ただし、pom.xml に <packaging>jar</packaging> のような記載が必要です。

6 mvn clean = make clean

$ mvn clean

$ find . -type f
./pom.xml
./src/main/java/jp/end0tknr/App.java
./src/test/java/jp/end0tknr/AppTest.java

7 mvn exec:java メインクラスの実行

$ mvn compile
$ mvn exec:java

ただし、pom.xml での exec-maven-plugin 指定や、 メインクラスでの main( String[] args ) 実装が必要です。

pom.xml での exec-maven-plugin指定

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>exec-maven-plugin</artifactId>
  <version>3.0.0</version>
  <configuration>
    <mainClass>jp.end0tknr.App</mainClass>
  </configuration>
</plugin>

メインクラスでの main(String[] args) 実装

package jp.end0tknr;

import jp.end0tknr.lib.Lib;

public class App {
    public static void main( String[] args ) {
        Lib lib = new Lib("end0tknr","I am Happy");
        System.out.println( lib.getMessage() );
    }
}

pom.xml に mainClass がない場合の実行

も可能なようです。

$ mvn exec:java -Dexec.mainClass=[メインクラス名] -Dexec.args=[引数]

java コマンド + jar による直接実行

$ java -jar target/javaci-1.0-SNAPSHOT.jar

8 mvn eclipse:eclipse maven->eclipseプロジェクト化

といっても、.classpath と .project が生成されるだけです。

$ mvn eclipse:eclipse

$ find . -type f
./pom.xml
./src/main/java/jp/end0tknr/App.java
./src/test/java/jp/end0tknr/AppTest.java
./.classpath
./.project

9 mvn eclipse:to-maven eclipse->mavenプロジェクト化

試していませんが、.project から pom.xml が生成される気がします。

10 mvn eclipse:clean eclipse->mavenプロジェクト化?

「mvn eclipse:eclipse」で生成された .classpath や .project が削除されます。

11 mvn install ローカルリポジトリへの登録

$ mvn install
   :
[INFO] Installing /home/end0tknr/tmp/mvn-lib-1.0-SNAPSHOT.jar
    to /home/end0tknr/.m2/repository/jp/end0tknr/mvn-lib/1.0-SNAPSHOT/mvn-lib-1.0-SNAPSHOT.jar
[INFO] Installing /home/end0tknr/tmp/mvn-lib/pom.xml to
    /home/end0tknr/.m2/repository/jp/end0tknr/mvn-lib/1.0-SNAPSHOT/mvn-lib-1.0-SNAPSHOT.pom

または

$ mvn install:install-file \
    -Dfile=/home/end0tknr/tmp/mvn-lib/target/mvn-lib-1.0-SNAPSHOT.jar \
    -DgroupId=jp.end0tknr \
    -DartifactId=mvn-lib \
    -Dversion=1.0-SNAPSHOT \
    -Dpackaging=jar

12 mvn jetty:run jetty-maven-pluginでのweb実行

$ mvn archetype:generate \
    --batch-mode \
    -DarchetypeGroupId=org.apache.maven.archetypes \
    -DarchetypeArtifactId=maven-archetype-webapp \
    -DgroupId=jp.end0tknr \
    -DartifactId=mvn-web-app \
    -Dversion=1.0-SNAPSHOT \
    -Dpackage=jp.end0tknr

$ find . -type f
./pom.xml
./src/main/webapp/WEB-INF/web.xml
./src/main/webapp/index.jsp

$ mvn jetty:run

その後、ブラウザで、8080ポートへアクセス 

pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
               http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>jp.end0tknr</groupId>
  <artifactId>mvn-web-app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>mvn-web-app Maven Webapp</name>
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <finalName>mvn-web-app</finalName>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-maven-plugin</artifactId>
          <version>9.4.4.v20170414</version>
          <configuration>
            <httpConnector>
              <port>8080</port>
            </httpConnector>
          </configuration>
        </plugin>
    
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

pom.xml サンプル集

その1 - hello world程度に素朴なもの

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>jp.end0tknr</groupId>
  <artifactId>javaci</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
  
  <name>javaci</name>
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <!-- ローカルパッケージのinstall -->
    <dependency>
      <groupId>jp.end0tknr</groupId>
      <artifactId>mvn-lib</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  
  <build>
    <pluginManagement>
      <plugins>
    <!-- mvn exec:java の為 -->
        <plugin>
          <groupId>org.codehaus.mojo</groupId>
          <artifactId>exec-maven-plugin</artifactId>
          <version>3.0.0</version>
          <configuration>
            <mainClass>jp.end0tknr.App</mainClass>
          </configuration>
        </plugin>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
    <!-- java -jar ~ で実行する為? -->
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
          <configuration>
            <archive>
              <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>jp.end0tknr.App</mainClass>
              </manifest>
            </archive>
          </configuration>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

その2 - web アプリ

$ mvn archetype:generate \
    --batch-mode \
    -DarchetypeGroupId=org.apache.maven.archetypes \
    -DarchetypeArtifactId=maven-archetype-webapp \
    -DgroupId=jp.end0tknr \
    -DartifactId=mvn-web-app \
    -Dversion=1.0-SNAPSHOT \
    -Dpackage=jp.end0tknr

↑こう実行すると、↓こう生成されます

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>jp.end0tknr</groupId>
  <artifactId>mvn-web-app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>mvn-web-app Maven Webapp</name>
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <finalName>mvn-web-app</finalName>
    <pluginManagement>
      <plugins>
    <!-- jetty-maven-pluginは、追加しました -->
        <plugin>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-maven-plugin</artifactId>
          <version>9.4.4.v20170414</version>
          <configuration>
            <httpConnector>
              <port>8080</port>
            </httpConnector>
          </configuration>
        </plugin>
        
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

その2 - spring-boot

$ mvn archetype:generate \
    --batch-mode \
    -DarchetypeGroupId=org.springframework.boot \
    -DarchetypeArtifactId=spring-boot-sample-jetty-archetype \
    -DgroupId=jp.end0tknr \
    -DartifactId=mvn-spring-app \
    -Dversion=1.0-SNAPSHOT \
    -Dpackage=jp.end0tknr.spring

$ mvn package

springの場合、warでなく、jarが作成されますので、 以下のように実行するだけで、ブラウザでアクセスできます。

$ java -jar target/mvn-spring-app-1.0-SNAPSHOT.jar
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.0.2.RELEASE</version>
  </parent>
  
  <artifactId>mvn-spring-app</artifactId>
  <groupId>jp.end0tknr</groupId>
  <name>Spring Boot Jetty Sample</name>
  <description>Spring Boot Jetty Sample</description>
  <version>1.0-SNAPSHOT</version>
  <url>http://projects.spring.io/spring-boot/</url>
  
  <organization>
    <name>Pivotal Software, Inc.</name>
    <url>http://www.spring.io</url>
  </organization>
  
  <properties>
    <main.basedir>${basedir}/../..</main.basedir>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jetty</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

hashcat による zip fileのパスワード解析(crack) -> ボツ

John the Ripper による zip fileのパスワード解析(crack) -> ボツ - end0tknr's kipple - web写経開発

先程の entry 同様、没ネタです。

zipファイルでは、容量と共に、抽出される hash も大きくなりますが、 hashcat では、小さな size(数文字のtext)のhash 以外、解析できないようですので、 諦めました。

hashcat でも GPU を認識はします

PS C:\Users\end0t\tmp\hashcat-6.2.5> .\hashcat.exe -I
hashcat (v6.2.5) starting in backend information mode

CUDA Info:
==========

CUDA.Version.: 11.6

Backend Device ID #1 (Alias: #2)
  Name...........: NVIDIA GeForce RTX 3060
  Processor(s)...: 28
  Clock..........: 1807
  Memory.Total...: 12287 MB
  Memory.Free....: 11281 MB
  PCI.Addr.BDFe..: 0000:30:00.0

OpenCL Info:
============

OpenCL Platform ID #1
  Vendor..: NVIDIA Corporation
  Name....: NVIDIA CUDA
  Version.: OpenCL 3.0 CUDA 11.6.58

  Backend Device ID #2 (Alias: #1)
    Type...........: GPU
    Vendor.ID......: 32
    Vendor.........: NVIDIA Corporation
    Name...........: NVIDIA GeForce RTX 3060
    Version........: OpenCL 3.0 CUDA
    Processor(s)...: 28
    Clock..........: 1807
    Memory.Total...: 12287 MB (limited to 3071 MB allocatable in one block)
    Memory.Free....: 11520 MB
    OpenCL.Version.: OpenCL C 1.2
    Driver.Version.: 511.23
    PCI.Addr.BDF...: 30:00.0

OpenCL Platform ID #2
  Vendor..: Intel(R) Corporation
  Name....: Intel(R) OpenCL HD Graphics
  Version.: OpenCL 3.0

  Backend Device ID #3
    Type...........: GPU
    Vendor.ID......: 8
    Vendor.........: Intel(R) Corporation
    Name...........: Intel(R) UHD Graphics
    Version........: OpenCL 3.0 NEO
    Processor(s)...: 24
    Clock..........: 1100
    Memory.Total...: 6453 MB (limited to 1613 MB allocatable in one block)
    Memory.Free....: 3168 MB
    OpenCL.Version.: OpenCL C 3.0
    Driver.Version.: 30.0.101.1122

OpenCL Platform ID #3
  Vendor..: Intel(R) Corporation
  Name....: Intel(R) OpenCL
  Version.: OpenCL 3.0 WINDOWS

  Backend Device ID #4
    Type...........: CPU
    Vendor.ID......: 8
    Vendor.........: Intel(R) Corporation
    Name...........: Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz
    Version........: OpenCL 3.0 (Build 0)
    Processor(s)...: 8
    Clock..........: 1600
    Memory.Total...: 16134 MB (limited to 2016 MB allocatable in one block)
    Memory.Free....: 8035 MB
    OpenCL.Version.: OpenCL C 3.0
    Driver.Version.: 2021.13.11.0.23_160000

hashcat による パスワード解析 - 100KB EXCELでの NG例

hash抽出

PS> ./john-1.9.0-jumbo-1-win64/run/zip2john.exe EXCEL_S.zip > EXCEL_S.hashcat
ver 2.0 EXCEL_S.zip/Book1.xlsx PKZIP Encr: cmplen=76365, decmplen=106981, crc=FFC62F25
【旧】
EXCEL_S.zip/Book1.xlsx:$pkzip2$1*1*2*0*12a4d*1a1e5*ffc62f25*0*28*<略>186f*$/pkzip2$:Book1.xlsx:EXCEL_S.zip::EXCEL_S.zip
【新】
$pkzip2$1*1*2*0*12a4d*1a1e5*ffc62f25*0*28*<略>186f*$/pkzip2$

パスワード解析

しかし、100KBのexcelのzipでは、 「Status: Exhausted」のままでしたので、諦めました。

PS> cd hashcat-6.2.5
PS> ./hashcat.exe -m 17200 -a 3 -w 4 -S ..\EXCEL_S.hashcat \
       --increment ?a?a?a?a --status
      :         
Approaching final keyspace - workload adjusted.

Session..........: hashcat
Status...........: Exhausted
Hash.Mode........: 17200 (PKZIP (Compressed))
Hash.Target......: $pkzip2$1*1*2*0*12a4d*1a1e5*ffc62f25*0*28*8*12a4d*f...kzip2$
Time.Started.....: Fri Feb 11 16:35:33 2022 (20 secs)
Time.Estimated...: Fri Feb 11 16:35:53 2022 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Mask.......: ?a?a?a?a [4]
Guess.Queue......: 4/4 (100.00%)
Speed.#1.........:  4156.7 kH/s (25.25ms) @ Accel:512 Loops:1 Thr:32 Vec:1
Speed.#*.........:  4156.7 kH/s
Recovered........: 0/1 (0.00%) Digests
Progress.........: 81450625/81450625 (100.00%)
Rejected.........: 0/81450625 (0.00%)
Restore.Point....: 81450625/81450625 (100.00%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Host Generator + PCIe
Candidates.#1....: LLx> ->  ~?~
Hardware.Mon.#1..: Temp: 41c Fan:  0% Util: 21% Core: 768MHz Mem:4995MHz Bus:4
Started: Fri Feb 11 16:35:31 2022
Stopped: Fri Feb 11 16:35:55 2022```
PS>

参考url

VMware ESXi 7.0 での GPU パススルー設定手順 - setodaNote

John the Ripper による zip fileのパスワード解析(crack) -> ボツ

パスワードを忘れてしまった zip ファイルを John the Ripper で解析しようとしましたが、 John the Ripper では PKZIP に対し、GPUを活用できないらしく、 諦めました。

没ネタですが、メモとして記載しておきます。

参考url

利用環境

項目 内容
PC thinkpad x1 carbon gen 8
OS Windows 11 Pro
CPU Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz 2.11GHz
MEM 16GB
GPU NVIDIA GeForce RTX 3060

install John the Ripper

今回は、以下のurlを参考に 外付GPUのある windows 11 に John the Ripper を install しています。

How to install John the Ripper and Johnny on Windows with GPU support - Life of a webmaster

install cygwin

https://www.cygwin.com/ から、インストーラである setup-x86_64.exe を ダウンロードし、実行するだけです。

install John the Ripper

https://github.com/openwall/john-packages/releases/tag/jumbo-dev から winX64_1_JtR.7z をダウンロードし、C:\cygwin64\home\end0t に解凍します。

convert cygOpenCL-1.dll by OpenCL.dll

先程、解凍した JtR 以下に cygOpenCL-1.dll がありますが、 GPUを認識させる為、c:\Windows\System32\OpenCL.dll で置き換えます

PS> cd c:\cygwin64\home\end0t\JtR\run
PS> cp c:\Windows\System32\OpenCL.dll .

check JtR with GPU

以下のコマンドで、GPUが認識されていることを確認できます。

PS C:\cygwin64\home\end0t> .\JtR\run\john.exe --help
John the Ripper 1.9.0-jumbo-1+bleeding-e4373c9 2022-01-29 19:47:54 +0100 OMP [cygwin 64-bit x86_64 AVX2 AC]
Copyright (c) 1996-2022 by Solar Designer and others
Homepage: https://www.openwall.com/john/

Usage: john [OPTIONS] [PASSWORD-FILES]
<略>


PS C:\cygwin64\home\end0t> .\JtR\run\john.exe --list=opencl-devices
Platform #0 name: Intel(R) OpenCL HD Graphics, version: OpenCL 3.0
    Device #0 (1) name:     Intel(R) UHD Graphics
    Device vendor:          Intel(R) Corporation
    Device type:            GPU (LE)
    Device version:         OpenCL 3.0 NEO
    Driver version:         30.0.101.1122
    Native vector widths:   char 16, short 8, int 4, long 1
    Preferred vector width: char 16, short 8, int 4, long 1
    Global Memory:          6453 MiB
    Global Memory Cache:    512 KiB
    Local Memory:           64 KiB (Local)
    Constant Buffer size:   3226 MiB
    Max memory alloc. size: 3226 MiB
    Max clock (MHz):        1100
    Profiling timer res.:   83 ns
    Max Work Group Size:    256
    Parallel compute cores: 24
    Stream processors:      192  (24 x 8)
    Speed index:            211200

Platform #1 name: NVIDIA CUDA, version: OpenCL 3.0 CUDA 11.6.58
    Device #0 (2) name:     NVIDIA GeForce RTX 3060
    Device vendor:          NVIDIA Corporation
    Device type:            GPU (LE)
    Device version:         OpenCL 3.0 CUDA
    Driver version:         511.23 [recommended]
    Native vector widths:   char 1, short 1, int 1, long 1
    Preferred vector width: char 1, short 1, int 1, long 1
    Global Memory:          12287 MiB
    Global Memory Cache:    784 KiB
    Local Memory:           48 KiB (Local)
    Constant Buffer size:   64 KiB
    Max memory alloc. size: 3071 MiB
    Max clock (MHz):        1807
    Profiling timer res.:   1000 ns
    Max Work Group Size:    1024
    Parallel compute cores: 28
    CUDA INT32 cores:       1792  (28 x 64)
    Speed index:            3238144
    Warp size:              32
    Max. GPRs/work-group:   65536
    Compute capability:     8.6 (sm_86)
    Kernel exec. timeout:   yes
    PCI device topology:    30:00.0

Platform #2 name: Intel(R) OpenCL, version: OpenCL 3.0 WINDOWS
    Device #0 (3) name:     Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz
    Device vendor:          Intel(R) Corporation
    Device type:            CPU (LE)
    Device version:         OpenCL 3.0 (Build 0)
    Driver version:         2021.13.11.0.23_160000
    Native vector widths:   char 32, short 16, int 8, long 4
    Preferred vector width: char 1, short 1, int 1, long 1
    Global Memory:          16134 MiB
    Global Memory Cache:    256 KiB
    Local Memory:           32 KiB (Global)
    Constant Buffer size:   128 KiB
    Max memory alloc. size: 4033 MiB
    Max clock (MHz):        1600
    Profiling timer res.:   100 ns
    Max Work Group Size:    8192
    Parallel compute cores: 8
    Speed index:            51200

ZIP ファイルのパスワード解析

zipファイルからhashの取り出し

PS> .\JtR\run\zip2john.exe .\EXCEL_MIN.zip > .\EXCEL_MIN.hash
ver 2.0 EXCEL_MIN.zip/EXCEL_MIN.xlsx PKZIP Encr: cmplen=76365, decmplen=106981, crc=FFC62F25 ts=A657 cs=ffc6 type=8

*.hash ファイルのDOS -> UNIX改行化

windows環境で zip2john を使用した場合、DOS改行コードとなる為 john.exe 実行時に以下のようなエラーとなります。

これを避ける為、*.hash ファイルのDOS -> UNIX改行化して下さい。

> .\JtR\run\john.exe .\EXCEL_MIN.hash
Warning: UTF-16 BOM seen in password hash file. File may not be read properly unless you re-encode it
Warning: invalid UTF-8 seen reading .\EXCEL_MIN.hash
Using default input encoding: UTF-8
No password hashes loaded (see FAQ)

ZIP ファイルのパスワード解析 (単純実行)

4文字英大小数字+記号のパスワードを解析しようとしました。

以下から「8 OpenMP threads」実行されているようですが、 windowsのタスクマネージャーでは、GPUが利用されておらず、 30分経過しても解析は完了しませんでした。

PS C:\cygwin64\home\end0t> .\JtR\run\john.exe .\EXCEL_MIN.hash
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 8 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Almost done: Processing the remaining buffered candidate passwords, if any.
Proceeding with wordlist:/run/password.lst
Proceeding with incremental:ASCII
 :

ZIP ファイルのパスワード解析 (--devices=0,1,2)

johnコマンドには、「--devices」オプションがありますので、 これを指定し、実行しましたが、やはりエラー。

PS C:\cygwin64\home\end0t> .\JtR\run\john.exe --devices=0,1,2 .\EXCEL_MIN.hash
Using default input encoding: UTF-8
The "--devices" option is valid only for OpenCL or ZTEX formats

更に「.\JtR\run\john.exe --list=formats」で対応する format を確認しましたが、PKZIP-opencl がない為、 GPUを使用したzipパスワードの解析は、諦めました。

python3 for win で、UnicodeEncodeError 'cp932' codec can't encode character

disp_cols_str = "\t".join(disp_cols)
print(disp_cols_str)

のような記述を含む python script を以下のようにredirect付きで実行すると windowsはcp932な環境の為、エラーとなる場合があるみたい。

PS C:\Users\end0tknr\tmp\JIKO> ..\python38\python.exe .\aggregate_4.py .\JIKO_SRC_2021 > foo.txt
Traceback (most recent call last):
  File ".\aggregate_4.py", line 214, in <module>
    main()
  File ".\aggregate_4.py", line 30, in main
    aggregate_xlsx(xlsx_path,"")
  File ".\aggregate_4.py", line 100, in aggregate_xlsx
    print(disp_cols_str)
UnicodeEncodeError: 'cp932' codec can't encode character '\ufffd' in position 63: illegal multibyte sequence

なので、以下のように .encode('cp932',"ignore") を追加し、回避。

disp_cols_str = "\t".join(disp_cols)
disp_cols_str = disp_cols_str.encode('cp932',"ignore")
disp_cols_str = disp_cols_str.decode('cp932')
print(disp_cols_str)

javasciprt class構文、アロー関数の手習い

jqueryやbootstrap非依存な responsive & tab menu & carousel html - end0tknr's kipple - web写経開発

手習いとして、上記entryにある js を class & arrow function 化しました。

https://end0tknr.github.io/sandbox/responsive/index2.html

'use strict';

class WindowBase {
    constructor() {}
    
    init_window =()=> {
        this.init_sp_menu();
        
        let tab_menus = document.querySelectorAll('.tab_menu');
        tab_menus.forEach(tab_menu=>{
            this.init_tab_menu( tab_menu );
        });
        
        let carousels = document.querySelectorAll('.carousel');
        carousels.forEach(carousel=>{
            this.init_carousel( carousel );
            this.update_carousel_buttons( carousel );
        });
        
        // カルーセルのサイズをwinサイズに追従
        window.addEventListener('resize', () => {
            carousels.forEach(carousel=>{
                this.slide_carousel( carousel );
            });
        });
    }
    
    init_sp_menu=()=>{
        let pc_menu_ul = document.querySelector('#pc_menu nav ul');
        let sp_menu_ul = pc_menu_ul.cloneNode(true);
        
        let sp_menu_nav = document.querySelector('#sp_menu_overlay nav');
        sp_menu_nav.after(sp_menu_ul);
        
        this.sp_menu_open   = document.getElementById('sp_menu_open');
        this.sp_menu_close  = document.getElementById('sp_menu_close');
        this.sp_menu_overlay= document.getElementById('sp_menu_overlay');
        
        this.sp_menu_open.addEventListener('click', () => {
            this.sp_menu_overlay.classList.add('show');
            this.sp_menu_open.classList.add('hide');
        });
        this.sp_menu_close.addEventListener('click', () => {
            this.sp_menu_overlay.classList.remove('show');
            this.sp_menu_open.classList.remove('hide');
        });
    }
    
    init_carousel=(carousel)=>{
        carousel.current_index = 0;
        carousel.prev_button = carousel.querySelector('.carousel_prev');
        carousel.next_button = carousel.querySelector('.carousel_next');
        carousel.ul     = carousel.querySelector('ul');
        carousel.slides = carousel.querySelectorAll('ul li');
        carousel.dots   = [];
        
        // ボタンによる左右スライド
        carousel.prev_button.addEventListener('click', () => {
            carousel.current_index -= 1;
            this.update_carousel_buttons(carousel);
            this.update_carousel_dots(carousel);
            this.slide_carousel(carousel);
        });
        carousel.next_button.addEventListener('click', () => {
            carousel.current_index += 1;
            this.update_carousel_buttons(carousel);
            this.update_carousel_dots(carousel);
            this.slide_carousel(carousel);
        });
        
        // カルーセル下部に表示する丸ボタン生成
        for (let i = 0; i < carousel.slides.length; i++) {
            let button = document.createElement('button');
            button.addEventListener('click', () => {
                carousel.current_index = i;
                this.update_carousel_dots(carousel);
                this.update_carousel_buttons(carousel);
                this.slide_carousel(carousel);
            });
            carousel.dots.push(button);
            carousel.querySelector('nav').appendChild(button);
        }
        
        carousel.dots[0].classList.add('current');
    }
    
    init_tab_menu=(tab_menu)=>{
        let this_obj = this;
        
        let tab_menu_items    = tab_menu.querySelectorAll('ul li a');
        let tab_menu_contents = tab_menu.querySelectorAll('section');
        
        for (let i = 0; i < tab_menu_items.length; i++) {
            tab_menu_items[i].addEventListener('click', event => {
                event.preventDefault();
                
                tab_menu_items.forEach(item => {
                    item.classList.remove('active');
                });
                tab_menu_items[i].classList.add('active');
                
                tab_menu_contents.forEach(content => {
                    content.classList.remove('active');
                });
                tab_menu_contents[i].classList.add('active');
            });
        }
    }
    
    update_carousel_buttons=(carousel)=>{
        carousel.prev_button.classList.remove('hidden');
        carousel.next_button.classList.remove('hidden');
        
        if (carousel.current_index == 0) {
            carousel.prev_button.classList.add('hidden');
            
        }
        if (carousel.current_index === carousel.slides.length - 1) {
            carousel.next_button.classList.add('hidden');
        }
    }
    
    slide_carousel=(carousel)=>{
        let slide_w = carousel.slides[0].getBoundingClientRect().width;
        let current_index = carousel.current_index;
        
        carousel.ul.style.transform =
            `translateX(${-1 * slide_w * current_index}px)`;
    }
    
    update_carousel_dots=(carousel)=>{
        carousel.dots.forEach(dot => {
            dot.classList.remove('current');
        });
        carousel.dots[carousel.current_index].classList.add('current');
    }
    
}

let win_base = new WindowBase();
win_base.init_window();

tabula for java で pdfに記載された表から、table情報を抽出

参考url

実行方法

step.1

https://tabula.technology/ から、 例えば、tabula-win-1.2.1.zip をダウンロード & 解凍

step.2

以下のような .batファイル(※1)を作成し、実行するると、ブラウザが起動し、 後は分かると思います。

set RUBYOPT=-EUTF-8
tabula.exe

※1

*.bat を作成せず、直接、tabula.exe を実行すると、 以下のようなエラーとなるはずです

f:id:end0tknr:20220129175005p:plain

perl による文字列の可逆暗号化

なんとなく、以下のような感じでしょうか

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my $SEED_BASE =
    '(3hvKT1w0!W5xA}_/9^eDpR{Gt4S[coPNMnkHiL'
    'jUmY27r).Xz]lZFyECs=qgBaOVbId8~-J6Qfu';
my $PCP_TABLE = {};
my $FIXED_NUM = 383;

main();

sub main {
    my $encoded = pcp_encode('end0tknr','crt');
    print "$encoded\n";
    my $decoded = pcp_decode($encoded,'crt');
    print "$decoded\n";
}

sub pcp_encode {
    my($comment,$key_str) = @_;
    
    $comment .="\0" if length($comment) % 2;
    my @key = split(//,$key_str);
    my $j = pcp_make_table(@key);
    my $i = 0;
    $comment =~
        s/./sprintf("%03o",ord($&)^(ord($key[$i++ % @key])+($j++ % $FIXED_NUM)))/ges;
    $comment=~ s/../$PCP_TABLE->{$&}/g;
    
    return $comment;
}

sub pcp_decode {
    my($comment,$key_str) = @_;

    $comment = $_[0];
    my @key = split(//,$key_str);
    my $j = pcp_make_table(@key);
    $comment=~ s/./$PCP_TABLE->{$&}/g;
    my $i = 0;
    $comment =~
        s/.../sprintf("%c",oct($&)^(ord($key[$i++ % @key]) +($j++ % $FIXED_NUM)))/ges;
    $comment=~s/\0$//;
    return $comment;
}

sub pcp_make_table{
    my(@key) = @_;
    
    my @list;
    my @seed = split(//,$SEED_BASE);
    my $k = scalar(@key);
    my $init_j=0;
    for(my $i=0;$i<64;$i++){
        my $j=ord($key[$i % $k]);
        $init_j +=$j;
        $list[$i]=splice(@seed,(($j+$k) % (64-$i)),1);
    }
    $k=0;
    for(my $i=0;$i<8;$i++){
        for(my $j=0;$j<8;$j++,$k++){
            $PCP_TABLE->{"$i$j"}=$list[$k];
            $PCP_TABLE->{$list[$k]}="$i$j";
        }
    }
    return ($init_j % $FIXED_NUM);
}

install Pg ver.1.9 to perl 5.26 in rhel8

https://metacpan.org/pod/Pg

Pg moduleは、既にサポート終了していますが、インストールしてみた。

$ wget https://cpan.metacpan.org/authors/id/M/ME/MERGL/pgsql_perl5-1.9.0.tar.gz
$ tar -xvf pgsql_perl5-1.9.0.tar.gz
$ cd pgsql_perl5-1.9.0

$ export POSTGRES_LIB=/usr/lib64
$ export POSTGRES_INCLUDE=/usr/include/pgsql

$ /usr/bin/perl Makefile.PL PREFIX=~/prj04/kai/cgi-bin/perl-lib
$ make
$ make install

政府統計 e-stat の データ一覧を BeautifulSoup for python で取得

www.e-stat.go.jp

政府統計 e-stat の データ一覧は、上記urlからダウンロードできるのかもしれませんが、 よく分かりませんでしたので、BeautifulSoup for python で scraping

#!python3
# -*- coding: utf-8 -*-

from bs4 import BeautifulSoup
import requests
import csv
import re
import sys
import time

base_url = "https://www.e-stat.go.jp"
search_path = "/stat-search"
max_page_no = 13

conf = {
    "retry_limit" : 10,
    "retry_sleep" : 10,
}


def main():

    data_list = []
    page_no = 0
    while page_no <= max_page_no:
        page_no+=1
        print("page:",page_no, file=sys.stderr,flush=True)
        
        search_base_url = base_url + search_path
        data_list_tmp = get_data_list(search_base_url, page_no)
        data_list.extend(data_list_tmp)

    disp_data_list(data_list)

def disp_data_list(data_items):
    for data_item in data_items:
        disp_str = \
            "\t".join([
                data_item["id"],
                data_item["name"],
                data_item["url_1"],
                data_item["url_2"]  ])
        print( disp_str )

def get_data_list(search_base_url, page_no):
    
    http_result = get_http_requests(search_base_url, page_no)
    if not http_result:
        return []

    soup = BeautifulSoup(http_result.content, 'html.parser')

    data_lis = soup.select("ul.stat-search_result-list li")
    data_list = []
    
    for data_li in data_lis:
        data_id   = data_li["data-value"]
        
        spans = data_li.select(
            "div.stat-toukei_name_items span.stat-title" )
        data_name = spans[0].text.strip()


        a_hrefs_1  = data_li.select("div.stat-search_result-item1-main a" )
        data_url_1 = base_url + a_hrefs_1[0]["href"]

        a_hrefs_2  = data_li.select("div.stat-pc_detail a" )
        data_url_2 = base_url + a_hrefs_2[0]["href"]

        data_list.append(
            {"id"   :data_id,
             "name" :data_name,
             "url_1":data_url_1,
             "url_2":data_url_2 })

    return data_list

def get_http_requests(search_base_url, page_no):
    result_url = search_base_url + "?page="+ str(page_no)

    i = 0
    while i < conf["retry_limit"]:
        i += 1
        result = None
        try:
            result = requests.get(result_url)
            return result
        except:
            print("WARN retry requests.get()", result_url ,file=sys.stderr)
            time.sleep(conf["retry_sleep"])

    print("ERROR requests.get()", result_url ,file=sys.stderr)
    return None


if __name__ == '__main__':
    main()