#4 Seleniumをexeファイル化し、クリック1つで認証を完了させる ~Python + GoogleChrome + Selenium でマトリクス認証を突破する~

1. マトリクス認証とは
2. SeleniumでWebを自動操作してみる
3.マトリクス認証でパスワードを自動入力する
4. Seleniumをexeファイル化し、クリック1つで認証を完了させる
← 今回

注意事項

* クラッキング目的ではありません。あくまで個人目的で使用しましょう。
* プログラムが流出するとマトリクス認証を破られます。管理には気を付けてください。
* テストには自分で作成したWebサイトを使用します。エンタープライズのマトリクス認証でテストをするのは避けましょう。

1クリックで認証を成功させるために

Seleniumを1クリックで起動させるためには、PythonプログラムとWebDriverをまとめてexe化しなければなりません。

exe化の方法

ディレクトリ構成
自動でパスワードを入力するスクリプトをauto_password.pyとし、以下のようなディレクトリ構成にします。

.
├── auto_password.py
└── driver
   └── chromedriver.exe

②コマンド
コマンドプロンプトで、以下のコマンドを入力します。

pyinstaller ./auto_passlogic.py --onefile --noconsole --add-binary "./driver/chromedriver.exe;./driver"

実行後、追加でファイルが出来上がります。

.
├ auto_password.py
├ auto_password.spec
├ driver
│ └── chromedriver.exe
├dist
│  └── auto_password.exe
.
.
.

dictフォルダ配下に出来上がったexeファイルがあります。
試しにexeファイルからSeleniumを実行してみます。

f:id:lc-xx16:20200506224310p:plain

起動できました。

まとめ

今回は作成したSeleniumを1クリックで起動させる方法をまとめました。
このexeファイルはデスクトップなどに移動させるとスムーズに使用することができるようになります。

#3 マトリクス認証でパスワードを自動入力する ~Python + GoogleChrome + Selenium でマトリクス認証を突破する~

1. マトリクス認証とは
2. SeleniumでWebを自動操作してみる
3. マトリクス認証でパスワードを自動入力する ← 今回
4. Seleniumをexeファイル化し、クリック1つで認証を完了させる

注意事項

* クラッキング目的ではありません。あくまで個人目的で使用しましょう。
* プログラムが流出するとマトリクス認証を破られます。管理には気を付けてください。
* テストには自分で作成したWebサイトを使用します。エンタープライズのマトリクス認証でテストをするのは避けましょう。

Seleniumを使ってオブジェクトを取得する

Seleniumを使ってデータを取得する際に、基本的に使われる属性としては以下のようなものがあります。

# idから取得
driver.find_element_by_id('xxx')

# classから取得
driver.find_element_by_class_name('xxx')

# nameから取得
driver.find_element_by_name('xxx')

しかしながら、id, class, nameがないタグも存在します。
属性がないデータを取得する際には、XPathを利用すると便利です。

XPathとは?

XML形式のデータは、ツリー形式の構造で表現できます。
XPathはその特徴を利用して位置を識別できるようにするPathのことです。

XPathの確認の仕方

XPathGoogleChromeの開発者ツールから確認できます。WindowのF12キーまたは右クリックから「検証」を選択し、開発者ツールを起動させましょう。
開発者ツールの左上のクリックマークからXPathを確認したい要素を選択します。

f:id:lc-xx16:20200506224300p:plain

HTMLのコードが表示されるので、右クリックから「Copy」-「Copy XPath」でXPathが取得されます。
f:id:lc-xx16:20200506224303p:plain

/html/body/table/tbody/tr[2]/td[2]

このようにツリーのルートから要素までのパス(XPath)がコピーされます。
XPathを用いてSeleniumからオブジェクトを取得しましょう。

SeleniumXPathに存在するデータ取得する
obj = driver.find_element_by_xpath('/html/body/table/tbody/tr[2]/td[2]')
print(obj.text)

=> 2

XPathでデータが取得できました。
このようにHTMLドキュメントのルートからのPathが変わらなければnameやidなどの属性がなくとも値を取得できます。

マトリクス認証を突破してみる

マトリクス認証においてテーブルのデータが変化しても位置が変わらなければデータを取得し、パスワードを入力することが可能です。

from selenium import webdriver

# WebDriverを保存したURL
DRIVER_URL = 'D:\selenium\chromedriver.exe'

# 操作対象のWebURL(今回はローカルのhtmlを操作)
WEB_URL = 'file:///D:/selenium/sample.html'

# ドライバーを読み込む
driver = webdriver.Chrome(DRIVER_URL)

# ページを開く
driver.get(WEB_URL)

# 'password'というnameのオブジェクトを取得する
password = driver.find_element_by_name('password')

# XPathでパスワードの位置を定義する
pass_list = []
pass_list.append(driver.find_element_by_xpath('/html/body/table/tbody/tr[2]/td[2]').text)
pass_list.append(driver.find_element_by_xpath('/html/body/table/tbody/tr[2]/td[3]').text)
pass_list.append(driver.find_element_by_xpath('/html/body/table/tbody/tr[2]/td[4]').text)
pass_list.append(driver.find_element_by_xpath('/html/body/table/tbody/tr[2]/td[6]').text)
pass_list.append(driver.find_element_by_xpath('/html/body/table/tbody/tr[2]/td[7]').text)
pass_list.append(driver.find_element_by_xpath('/html/body/table/tbody/tr[3]/td[7]').text)
pass_list.append(driver.find_element_by_xpath('/html/body/table/tbody/tr[3]/td[8]').text)
pass_list.append(driver.find_element_by_xpath('/html/body/table/tbody/tr[3]/td[9]').text)
pass_list.append(driver.find_element_by_xpath('/html/body/table/tbody/tr[4]/td[9]').text)
pass_list.append(driver.find_element_by_xpath('/html/body/table/tbody/tr[4]/td[11]').text)

# passwordのオブジェクトにパスワードを入力する
password.send_keys(pass_list)

# passwordをsubmit
password.submit()

f:id:lc-xx16:20200506224310p:plain
自分が定義した位置と順番でパスワードを入力できました。最終行の

password.submit()

でパスワードがsubmitされ認証が完了します。

まとめ

今回はSeleniumXPathでマトリクス認証を突破しました。
しかし実際にサイトログインする際に、わざわざpythonコマンドラインや実行環境から実行するのは面倒だと思います。
そこで、次回は1クリックで起動できるようにexe化する方法を解説したいと思います。

#2 SeleniumでWebを自動操作してみる ~Python + GoogleChrome + Selenium でマトリクス認証を突破する~

1. マトリクス認証とは
2. SeleniumでWebを自動操作してみる ← 今回
3. マトリクス認証でパスワードを自動入力する
4. Seleniumをexeファイル化し、クリック1つで認証を完了させる

注意事項

* クラッキング目的ではありません。あくまで個人目的で使用しましょう。
* プログラムが流出するとマトリクス認証を破られます。管理には気を付けてください。
* テストには自分で作成したWebサイトを使用します。エンタープライズのマトリクス認証でテストをするのは避けましょう。

前提

pythonがインストールされていること

セットアップ

seleniumのインストール
コマンドラインから以下のコマンドを実行してインストールします。

pip install selenium

Chrome用のWebDriverをダウンロード
自分の使用しているGoogleChromeのバージョンをチェックしましょう。
※ [設定] - [Chromeについて]から確認できます。

f:id:lc-xx16:20200505214254p:plain

GoogleChromeのバージョンに合ったWebDriverをダウンロードします。
sites.google.com

※WebDriverのバージョンが異なるとエラーになります。定期的にブラウザがバージョンアップするので、作成したSeleniumが動かなくなった場合は、バージョンを確認しましょう。

selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 79
実際に試してみる

Seleniumが実行できるか試してみます。
今回は実行したときに、Webページを開き、InputBoxにデータを自動入力するサンプルを使います。

from selenium import webdriver

# WebDriverを保存したURL
DRIVER_URL = 'D:\selenium\chromedriver.exe'

# 操作対象のWebURL(今回はローカルのhtmlを操作)
WEB_URL = 'file:///D:/selenium/sample.html'

# ドライバーを読み込む
driver = webdriver.Chrome(DRIVER_URL)

# ページを開く
driver.get(WEB_URL)

# 'password'というnameのオブジェクトを取得する
password = driver.find_element_by_name('password')

# passwordのオブジェクトに'test input'を入力する
password.send_keys('test input')

これを実行すると自動でWebブラウザが立ち上がり、"test input"がInputBoxに自動入力されます。

まとめ

今回は自動でWebブラウザを操作できる環境が整備しました。
実際にマトリクス認証を突破できるようにしていきたいと思います。

賞味期限を通知してくれるラインボットを作ってみた

主にユーザ向けの概要記事となります。
システム上のあれやこれやを知りたい技術者の方はこちらからへ。

github.com

拙いコードですが、何か改善点があればアドバイスお願いします。
細かい技術の説明はまた投稿します。

友達登録方法

以下のQRコードまたはURLから登録してください。
f:id:lc-xx16:20200504160751p:plain https://lin.ee/6vqNKae

注意事項

※ 使用時に取得するデータは以下の通りです

* プロフィール情報 (ID, 表示名, 画像)

* 友達登録日 / ブロック日

* 登録した商品 / 賞味期限

※ 事前に告知せず、サービスの提供を停止する場合があります

操作説明

* 基本操作
全ての操作は下のメニューから開始してください。

f:id:lc-xx16:20200504161557p:plain


* 登録
1. メニューから【登録】を選択
f:id:lc-xx16:20200504161715p:plain

2. 商品名を入力
f:id:lc-xx16:20200504161739p:plain

3. 賞味期限を入力
f:id:lc-xx16:20200504161759p:plain


* 一覧
1. メニューから【一覧】を選択
f:id:lc-xx16:20200504161557p:plain

2. 商品を選択
f:id:lc-xx16:20200504161858p:plain

3. 賞味期限の変更 / 商品を削除を選択し操作
f:id:lc-xx16:20200504161922p:plain


* レシピ

1. メニューから【レシピ】を選択
f:id:lc-xx16:20200504161557p:plain

2. 商品を選択 (複数選択可能)
f:id:lc-xx16:20200504162045p:plain

3. 【レシピを検索】を選択
f:id:lc-xx16:20200504162017p:plain
f:id:lc-xx16:20200504162110p:plain


* 通知
1. 賞味期限が1週間を切ると、AM8:30に通知が来ます
2. 賞味期限が切れた商品は自動的に削除されます f:id:lc-xx16:20200504162150p:plain


その他

* システムの制約上、応答が遅いときがあります。
* 何か動きがおかしいなど、気になる点があれば連絡下さい。
* 追加機能のご要望お待ちしてお待ちしてます。

f:id:lc-xx16:20200818074528p:plain
LINEBOT

#1 マトリクス認証とは ~Python + GoogleChrome + Selenium でマトリクス認証を突破する~

長編になりそうなので、全4回で記載します。

1. マトリクス認証とは ← 今回
2. SeleniumでWebを自動操作してみる
3. マトリクス認証でパスワードを自動入力する
4. Seleniumをexeファイル化し、クリック1つで認証を完了させる

注意事項

* クラッキング目的ではありません。あくまで個人目的で使用しましょう。
* プログラムが流出するとマトリクス認証を破られます。管理には気を付けてください。
* テストには自分で作成したWebサイトを使用します。エンタープライズのマトリクス認証でテストをするのは避けましょう。

マトリクス認証とは

自分が登録した位置順番に書かれている数字を入力する認証方法です。
f:id:lc-xx16:20200504144716p:plain

上記図のように黄色の網掛けの位置情報と、赤矢印の順番を利用しパスワードを入力します。乱数表(マトリクス表)はアクセスごとに変化するため、パスワードも同時に変化します。(OTP認証) f:id:lc-xx16:20200504144931p:plain

2回目にアクセスした場合のサンプルです。マトリクス表が変化しています。2回目のログインの際には、「2636148023」を入力する必要があります。

この仕組みによりOTP認証を実現しています。マトリクス認証はショルダーハックパスワード流出への強度が高いと言われています。

マトリクス認証を使ってみた個人的の感想

* Webブラウザのパスワード自動入力が使えないためパスワードを毎回入力するのが面倒 パスワードの自動入力ができるのは従来の固定長パスワード認証方式の場合です。今回のように毎回パスワードが変化し、使い捨てするワンタイムパスワードでは使えません。

* 久々に開くと位置と順番を忘れている
記憶力の問題ですね。ただ同じように苦しむ人もいるのではないでしょうか。

マトリクス認証を楽に突破できる方法を考える

Web上でのマトリクス認証の場合、以下のようにHTMLのテーブルでマトリクス表を実現しているケースがあります。

<table border = "1" style="border-collapse: collapse">
        <tr>
            <td width="20px" align="center">2</td>
            <td width="20px" align="center">4</td>
            <td width="20px" align="center">8</td>
            <td width="20px" align="center">1</td>
            <td> </td>
            <td width="20px" align="center">5</td>
            <td width="20px" align="center">9</td>
            <td width="20px" align="center">1</td>
            <td width="20px" align="center">0</td>
            <td> </td>
            <td width="20px" align="center">8</td>
            <td width="20px" align="center">0</td>
            <td width="20px" align="center">9</td>
            <td width="20px" align="center">2</td>
        </tr>
        <tr>
            <td width="20px" align="center">5</td>
         .
         .

※マトリクス表が画像で表示されるケースは今回の対象外です。

パスワード値は変化するけれど、位置と順番は変わらない。」このマトリクス認証の特徴を利用して, Seleniumを使ってマトリクス認証を自動突破する方法を考えていきます。 詳しいSeleniumの説明、セットアップの仕方は第2回「Python + GoogleChrome + Seleniumのセットアップをする」で。

形態素解析エンジンMeCabをWindows + Pythonで使えるようにする

MeCabとは

MeCabは有名な形態素解析エンジンです。MeCabを使えば簡単に形態素解析を実行することが可能です。

MeCabWindowsでインストールする

①公式サイトからWindows版をインストール
MeCab: Yet Another Part-of-Speech and Morphological Analyzer

mecab-0.996.exeを起動し、セットアップをします。
言語設定を求められる場合は、「UTF-8」を指定します。

②Pathを通す
PATH環境変数に実行ファイル(mecab.exe)のあるディレクトリを追加しましょう。
例:C:\Program Files (x86)\MeCab\bin

Pythonで扱うためのパッケージをインストール
以下の2つを実行します。

pip install ipykernel
pip install mecab-python-windows

④libmecab.dllをpython.exeのあるディレクトリにコピーする
libmecab.dllmecab.exeディレクトリに格納されています。
python.exeのあるディレクトリへlibmecab.dllをコピーしましょう。
※Anacondaを導入している場合は、python.exeが複数ある場合があります。実行環境がどこのpython.exeを使用しているか確認しましょう。

Pythonで実行できるか試してみる

実際にPythonで実行できるか試してみます。

import MeCab
tagger = MeCab.Tagger('-Ochasen')
result = tagger.parse('日曜午前はカブの時間。')
print(result)

詳しい使い方の説明は今回は割愛しますが、形態素解析が4行で書けます。

<実行結果>

日曜    ニチヨウ        日曜    名詞-副詞可能
午前    ゴゼン  午前    名詞-副詞可能
は      ハ      は      助詞-係助詞
カブ    カブ    カブ    名詞-一般
の      ノ      の      助詞-連体化
時間    ジカン  時間    名詞-副詞可能
。      。      。      記号-句点
EOS

しっかりPythonで実行できていますね。

まとめ

今回は形態素解析エンジン MeCabをインストールしてPythonで利用できるまでをまとめました。品詞ごとに分解し、かつ品詞区別をしてくれるMeCabは活用できる場面が多々ありそう。またMeCabを利用した実装についてまとめてみたいと思います。

【Postgres】DELETEフラグによる論理削除からTRIGGERでのレコード管理へ切り替える

今日はデータベースの論理削除の実装について。
最近はまっている「fukabori.fm」にて論理削除に関するパートがあったので視聴してみました。
なるほど。論理削除のアンチパターンについて、納得できる部分が多々あり。
盲目的になんでも論理削除で設計していたことに気づかされました。
アンチパターンの解法の1つに

「論理削除フラグ設計から、別途archiveテーブルなどを設け、DELETEしたレコードをRDBの機能'TRIGGER'を使って移す」

というものがあったので、今回それを試してみようかと。


実際にトリガーを作ってみる


今回実装する内容は以下の通り。
前提)
・productテーブルとproduct_deletedテーブルを用意
実装)
・productテーブルのレコードがDELETEされた場合、product_deletedテーブルにINSERTする
参考)
PostgreSQL 8.1.9文書
https://www.postgresql.jp/document/8.1/html/plpgsql-trigger.html

①ストアドプロシージャの実装
process_backupというストアドプロシージャを作成します。

CREATE OR REPLACE FUNCTION process_backup()
 RETURNS trigger
 LANGUAGE plpgsql
AS 
'
BEGIN 
  INSERT INTO product_deleted SELECT OLD.*;
  RETURN OLD;
END
'

読めば大体わかりそうな感じのプロシージャですね。 OLDというのは、削除前のレコードのことです。 'OLD.*'で削除前レコードの全カラムのデータを取り出しています。

<参考>
作成したストアドプロシージャを見てみるとこのようなコードに変換されています。

CREATE OR REPLACE FUNCTION public.process_backup()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$
BEGIN 
    INSERT INTO product_deleted SELECT OLD.*;
    RETURN OLD;
END
$function$

a5でプロシージャをCREATEした際に、以下のようなエラーが出たため、%function%' にして実行しました。 (原因はわかっていません)

f:id:lc-xx16:20200502111327p:plain
a5エラー

②トリガーの実装

CREATE TRIGGER backup_recode 
AFTER DELETE ON product 
 FOR EACH ROW EXECUTE PROCEDURE process_backup();

トリガーの宣言はシンプルですね。
productテーブルのDELETEのタイミングで、process_backupプロシージャが呼び出されます。


試してみよう


productテーブルはシンプルに準備。

f:id:lc-xx16:20200502111551p:plain
productテーブル

1レコード消してみます

delete from product where product_name = '大根';

f:id:lc-xx16:20200502111625p:plain
productテーブル DELETE後

当然のことながら、productテーブルから消えています。
product_deletedではどうでしょう。

f:id:lc-xx16:20200502111655p:plain
product_deletedテーブル
ちゃんといました。TRIGGER成功です。


全レコード消してみる


全レコード消したときの挙動も見てみます。

delete from product;

f:id:lc-xx16:20200502111823p:plain
productテーブル 全レコード削除

productは空ですね。
product_deletedテーブルを見てみましょう。

f:id:lc-xx16:20200502111857p:plain
product_deletedテーブル 全レコード削除後

全部移っていますね。複数レコードの挙動もばっちりです。


まとめ


今回は「fukabori.fm」で紹介されていたTRIGGERの実装を試してみました。
こうしたRDBの機能を活用することでコード実装の負担が減るかもしれませんね。

今回参考にした「fukabori.fm」、面白いので是非聞いてみてください。 https://fukabori.fm/episode/27

Qittaにも投稿しました。 qiita.com