dak ブログ

python、rubyなどのプログラミング、MySQL、サーバーの設定などの備忘録。レゴの写真も。

外接矩形で画像をクロップ

2022-09-24 22:57:10 | python
外接矩形で画像をクロップする方法のメモ。
import sys
import cv2

def main():
    in_file = sys.argv[1]
    out_file = sys.argv[2]
    
    img = cv2.imread(in_file)

    # グレースケール
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    res, img_bw = cv2.threshold(img_gray, 0, 255,
                                cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

    # 輪郭
    cs, h = cv2.findContours(img_bw,
                             cv2.RETR_EXTERNAL,
                             cv2.CHAIN_APPROX_SIMPLE)
    
    # x, y の最小, 最大でトリミング
    min_x, min_y, w, h = cv2.boundingRect(cs[0])
    max_x = min_x + w
    max_y = min_y + h
    
    for i in range(1, len(cs)):
        x1, y1, w, h = cv2.boundingRect(c)
        x2 = x1 + w
        y2 = y1 + h

        if x1 < min_x: min_x = x1
        if y1 < min_y: min_y = y1

        if x2 > max_x: max_x = x2
        if y2 > max_y: max_y = y2

    # トリミング
    tgt_img = img[min_y:max_y, min_x:max_x]
    cv2.imwrite(out_file, tgt_img)
    
    return 0

if __name__ == '__main__':
    res = main()
    exit(res)


Selenium で User Agent を変更する方法

2022-09-23 19:53:46 | python
Selenium で User Agent を変更するには、set_preference() で
general.useragent.override に User Agent を指定します。
■プログラム
import time
from selenium import webdriver
from selenium.webdriver.firefox.options import Options

opts = Options()
opts.headless = True
opts.set_preference('general.useragent.override', 'test-user-agent')
driver = webdriver.Firefox(options=opts)

url = 'http://localhost/?ua_test'
driver.get(url)
time.sleep(3)
driver.close()

■web サーバのログ
127.0.0.1 - - [23/Sep/2022:03:49:58 -0700] "GET /?ua_test HTTP/1.1" 200 141 "-" "test-user-agent"


linux のデフォルトブラウザを google-chrome に設定

2022-09-17 11:34:50 | linux
linux のデフォルトブラウザを google-chrome に設定する方法のメモ。

■確認
$ update-alternatives --list

libnssckbi.so.x86_64    auto    /usr/lib64/pkcs11/p11-kit-trust.so
python                  auto    /usr/libexec/no-python
...
java_sdk_1.8.0_openjdk  auto    /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.302.b08-0.el8_4.x86_64
google-chrome           auto    /usr/bin/google-chrome-stable


■デフォルトブラウザを /usr/bin/google-chrome に設定
$ sudo update-alternatives --install /usr/bin/x-www-browser x-www-browser /usr/bin/google-chrome 1

末尾の 1 は優先度です

■確認
$ update-alternatives --list

libnssckbi.so.x86_64    auto    /usr/lib64/pkcs11/p11-kit-trust.so
python                  auto    /usr/libexec/no-python
...
java_sdk_1.8.0_openjdk  auto    /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.302.b08-0.el8_4.x86_64
google-chrome           auto    /usr/bin/google-chrome-stable
x-www-browser           auto    /usr/bin/google-chrome


python で selenium を使ってクロール

2022-09-16 23:19:53 | python
python で selenium でウェブページをクロールする方法のメモ。
selenium でブラウザを使ってクロールすると、javascript も実行してくれます。

■firefox のインスト―ル
sudo yum install firefox


■gecodriver のインストール
https://github.com/mozilla/geckodriver/releases/tag/v0.31.0 から gecodriver をダウンロードします。
gtar zxvf geckodriver-v0.31.0-linux64.tar.gz
sudo cp geckodriver /usr/bin


■プログラム
import time
from selenium import webdriver
from selenium.webdriver.firefox.options import Options

opts = Options()
opts.headless = True
driver = webdriver.Firefox(options=opts)

urls = [
    'https://www.goo.ne.jp/',
    'https://news.goo.ne.jp/',
    'https://search.goo.ne.jp/',
]

for url in urls:
    print(url)
    driver.get(url)
    time.sleep(3)
    html = driver.page_source
    print(html)

driver.close()


MySQL の blob に登録したデータをテキスト化

2022-09-13 22:06:25 | mysql
MySQL の blob に登録したデータをテキスト化する方法のメモ。
HTML のバイトデータを blob に保存し、エンコーディングを指定してテキスト化します。
■select
select convert(body using utf8) from test_base1 limit 1\G

■実行結果
*************************** 1. row ***************************
convert(body using utf8): <!DOCTYPE HTML>

<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="referrer" content="unsafe-url">
<!--[if !IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->

<title>goo</title>
<meta name="csrf-token" content="9xtJ4WTRoHOPV1kb2ElCk5jA60yL8HGwX1v0Y0GP">
<meta name="keywords" content="goo,グー,ぐー,ポータル,portal,検索">
...


Python で MySQL の blob にデータを登録

2022-09-12 23:51:03 | python
Python で MySQL の blob にデータを登録する方法のメモ。
■登録
import sys
import requests
import MySQLdb

def main():
    db = MySQLdb.connect(
        host='localhost',
        user='***',
        passwd='***',
        db='***'
    )

    url = 'https://www.goo.ne.jp'
    resp = requests.get(url)

    sql = f"insert into test_blob1 set url = %(url)s, body = %(body)s"
    cursor = db.cursor()
    cursor.execute(sql, {'url': url, 'body': resp.content})
    db.commit()
    cursor.close()

    db.close()

    return 0

if __name__ == '__main__':
    res = main()
    exit(res)

■検索
import sys
import requests
import MySQLdb

def main():
    db = MySQLdb.connect(
        host='localhost',
        user='***',
        passwd='***',
        db='***'
    )

    url = 'https://www.goo.ne.jp'
    sql = f"select * from test_blob1"
    cursor = db.cursor()
    cursor.execute(sql)
    rows = cursor.fetchall()
    for row in rows:
        print(f"url: {row[0]}")
        print(f"body: {row[1].decode('utf-8')}")
    cursor.close()
    db.close()
    return 0

if __name__ == '__main__':
    res = main()
    exit(res)

■実行結果
url: https://www.goo.ne.jp
body: <!DOCTYPE HTML>

<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="referrer" content="unsafe-url">
<!--[if !IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
...


python での例外発生時の except と finally の実行順序

2022-09-09 12:29:20 | python
python で例外が発生した場合の except と finally の実行順序を調べてみました。
例外発生時は except を実行後に finally を実行し、except 内の raise によろ呼び出し元で例外が補足されます。
以下のプログラムで検証を行いました。

■プログラム
def func1():
    try:
        print("func1: start")
        func2()
    except Exception as e:
        print("func1: except")
        raise
    finally:
        print("func1: finally")

    print("func1: end")


def func2():
    try:
        print("func2: start")
        func3()
    except Exception as e:
        print("func2: except")
        raise
    finally:
        print("func2: finally")

    print("func2: end")

def func3():
    try:
        print("func3: start")
        raise
    except Exception as e:
        print("func3: except")
        raise
    finally:
        print("func3: finally")

    print("func3: end")

try:
    func1()
except Exception as e:
    pass

■実行結果
func1: start
func2: start
func3: start
func3: except
func3: finally
func2: except
func2: finally
func1: except
func1: finally


TypeScript での catch と finally の処理順

2022-09-09 00:24:09 | Node.js
TypeScript で例外が発生した場合に catch と finally がどのような順に実行されるかを調べてみました。
以下のプログラムでは、func1() から func2() を呼び出し、func2() からはさらに func3() を呼び出します。
func3() 内で throw した場合に、catch と finally がどのような順で呼び出されるかを確認します。

■プログラム
function func1() {
  try {
    console.log("func1: start");
    func2();
  }
  catch (e) {
    console.log("func1: catch");
  }
  finally {
    console.log("func1: finally");
  }

  console.log("func1: end");
}

function func2() {
  try {
    console.log("func2: start");
    func3();
  }
  catch (e) {
    console.log("func2: catch");
    throw e;
  }
  finally {
    console.log("func2: finally");
  }

  console.log("func2: end");
}

function func3() {
  try {
    console.log("func3: start");
    throw 'func3';
  }
  catch (e) {
    console.log("func3: catch");
    throw e;
  }
  finally {
    console.log("func3: finally");
  }

  console.log("func3: end");
}

func1();

■実行結果
func1: start
func2: start
func3: start
func3: catch
func3: finally
func2: catch
func2: finally
func1: catch
func1: finally
func1: end


実行結果をみると、finally が定義されている場合には catch が実行された後に finally が呼び出されていますが、catch 内で throw した場合には呼び出し元の処理に戻る前に finally が実行されています。


Typescript で id を生成

2022-09-03 00:00:45 | Node.js
Typescript でランダムな id を生成する方法のメモ。
uuid を利用します。
■インストール
npm install uuid
npm i --save-dev @types/uuid

■プログラム
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4();
console.log(id);

■実行結果
342f3d57-e1e0-45c0-a19f-fe5108eb823b