paloma blog

NWエンジニアやってます。技術の備忘など。Pythonもちょっと。タイトルは好きなカクテルから。

HTMLスクレイピングで旬の食材を確認する

元々自炊するタチなのですが、昨今の状況でリモートワークもあり料理の機会が増えています。

今は年中食材が手に入りますが、どうせなら旬のものを食べたいですよね。
あらゆるWebサイトで旬の食材を確認できますが、毎回アクセスするのも面倒です。

幸い私はITの業界で働いていますのでスクレイピングでサクッと抽出したいと思います。

スーパーに行けば旬のコーナーがあるという問題は置いておきますw

環境

メインPCのWSLで行います。

masashi@DESKTOP-986MNSO:~$ uname -a ; lsb_release -a
Linux DESKTOP-986MNSO 4.4.0-18362-Microsoft #1049-Microsoft Thu Aug 14 12:01:00 PST 2020 x86_64 x86_64 x86_64 GNU/Linux
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.4 LTS
Release:        16.04
Codename:       xenial

リソースの取得

旬の食材は更新されるものではないので、都度アクセスする必要はありません。
なのでローカルにリソースを持っておきます。

今回はこちらのサイトを参考にさせていただきました。

旬の食材カレンダー

月ごとに一覧化されているページがあるのでそちらを頂きます。

wget https://k52.org/syokuzai/all/1
…
wget https://k52.org/syokuzai/all/12

ファイル名は特に変更しないので1から12までのファイルが手に入ります。
ちゃんとHTMLファイルですよ。

masashi@DESKTOP-986MNSO:~$ file {1..12}
1:  HTML document, UTF-8 Unicode text, with very long lines
2:  HTML document, UTF-8 Unicode text, with very long lines
3:  HTML document, UTF-8 Unicode text, with very long lines
4:  HTML document, UTF-8 Unicode text, with very long lines
5:  HTML document, UTF-8 Unicode text, with very long lines
6:  HTML document, UTF-8 Unicode text, with very long lines
7:  HTML document, UTF-8 Unicode text, with very long lines
8:  HTML document, UTF-8 Unicode text, with very long lines
9:  HTML document, UTF-8 Unicode text, with very long lines
10: HTML document, UTF-8 Unicode text, with very long lines
11: HTML document, UTF-8 Unicode text, with very long lines
12: HTML document, UTF-8 Unicode text, with very long lines

構成確認

サンプル的に1月のHTMLファイルの構成を確認します。

<td class="name"><a href="/syokuzai/013">カリフラワー</a></td>
<td class="othername"><a href="/syokuzai/013">cauliflower</a></td>

nameかothernameのクラス名でひっかけられそうですね。
othernameクラスだと英語が混じっているので、ぱっとわかるようにnameクラスの方を使いましょう。
また、ページは食材の種類別に分けられていますが、スクレイピングでは取るだけで分けないことにします。

shellでやる

pythonのBeautifulSoupは使えるのですが、この単発の思い付きにわざわざコード書くのも何なのでshellからやります。

masashi@DESKTOP-986MNSO:~$ bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

xmllintで抽出

HTMLタグをgrepで何とかしようとすると難しいので簡単にできるようxmllintを使います。

クラス名でひっかければOKですね。

masashi@DESKTOP-986MNSO:~$ xmllint --xpath '//td[@class="name"]/a/text()' --html 1
カリフラワーキャベツきょうな(みずな)くわいごぼうこまつなしゅんぎくせりセロリだいこんながいも(やまいも)ながねぎなのはなのざわなはくさいブロッコリーほうれんそうめキャベツゆりねれんこんいよかんオレンジキウイシークワーサーみかんレモンあんこういなだ・はまちきんき(きちじ)きんめだいこはだ(このしろ)さわらたらひらめふぐぶりほうぼうぼらわかさぎあかがいあまえびイイダコヤリイカいせえびかきずわいがにタラバガニけがにしじみたらこのりほたてあずきあんこおからこんにゃく・しらたきとうふなっとう

あら、全部くっついて出てしまいましたね。
text()で出力すると改行ができないようです。

じゃあaタグまでにする?

masashi@DESKTOP-986MNSO:/mnt/c/Users/tsuru$ xmllint --xpath '//td[@class="name"]' --html 1 | sed 's/<\/a>/<\/a>\n/g'
<td class="name">食材名</td><td class="name"><a href="/syokuzai/013">カリフラワー</a>
</td><td class="name"><a href="/syokuzai/015">キャベツ</a>
</td><td class="name"><a href="/syokuzai/017">きょうな(みずな)</a>

sedは使ったものの、一行ごとに並びました。
が、ここからタグの中身を出力するなら初めからgrepで取っても手間は同じですね。

grepでやり直します。

grepスクレイピング

<td class="name"><a href="/syokuzai/013">カリフラワー</a>

このHTMLの「カリフラワー」の部分だけを抜きます。

早速ですが、コマンドはこちらです。

masashi@DESKTOP-986MNSO:~$ grep -oP "<td class=\"name\"><a[^>]*?>\K.*(?=</a>)" 1 | head -1
カリフラワー
  • 簡単な解説
    • -oで対象の文字列のみを出力。
    • -Pでperl正規表現が使えます。(下記の\Kのため)
    • \Kで\Kより左側がgrepの対象になるようです。(-o付きなので出力の対象外になる)

なのでnameクラスのタグ内で、aタグで閉じられる文字列が抽出の対象という事になります。

11月の旬を確認

ここまで出来たらもう完成ですね。
本日は10月最終日なので来月の旬の食材を確認しましょう。

1行ずつだと長いので記事用にcolumnで整形します。

masashi@DESKTOP-986MNSO:~$ grep -oP "<td class=\"name\"><a[^>]*?>\K.*(?=</a>)" 11 | column
えのき                  しゅんぎく              ゆりね                  きんき(きちじ)        いくら
エリンギ                だいこん                ルッコラ                こはだ(このしろ)      いせえび
かぶ                    ちんげんさい            レタス                  さけ                    タラバガニ
かぼちゃ                ながいも(やまいも)    れんこん                さば                    けがに
カリフラワー            ながねぎ                かき                    さわら                  たらこ
ぎんなん                なめこ                  かりん                  ししゃも                のり
くわい                  にんじん                キウイ                  たちうお                あずき
ごぼう                  のざわな                みかん                  にしん                  あんこ
さつまいも              はくさい                ゆず                    はたはた                こんにゃく・しらたき
さといも                ブロッコリー            りんご                  はも                    そば
さんしょう              ほうれんそう            いなだ・はまち          ひらめ                  ピーナッツ
しいたけ                マッシュルーム          うなぎ                  ふぐ
じゃがいも              むかご                  かます                  ぼら

OK!
対象にしたタグの都合上ひらがなで出てしまいますが、まあいいでしょう。

11月はまだ秋と言っていいんでしょうか?食欲の秋でいい食材が揃いますね。
来月はこの出力内容をスマホに入れてスーパーに行きましょう。

むすび

という訳で今回はshellからのスクレイピングでした。
今はインターネット上に膨大なデータがありますから、この技を身につけておけばいろんな資料が作れますね。

これでshellを使ったちょっとしたスクレイピングができるようになりました!

参考サイト

プリキュアで学ぶワンライナーWebスクレイピング - Qiita

XPath Cheat Sheet

基本的な正規表現一覧 | murashun.jp

Sublime Text 3をコマンドラインから起動する

私はエディタは主にvimsublime text3を使っています。
vimは昔からでプログラミングを勉強するようになってからそっちよりのエディタも使うようになりました。

最初はatomを使っていましたが開発が止まってしまったようで、そうなると後継の問題です。
githubMicrosoftに買収されたのでVScodeでも使うかなと思ってみましたが、どうしても重いイメージがあります。
(実際使ってみるとそんなことはないんだろうけど)

そんな時に出会ったのがsublime text3でした。
コーディングする動画などよく見るんですが、海外の方の動画で使っている人が多くてそんなにいいのかと興味を持ったのがきっかけです。

本題

とあるハッキングの動画を見ていたんですが、 その方がコマンドからsublime text3を起動していてカッコいい!と思ったので私もやってみることにしました。

環境

sublime textはubuntuwindowsにそれぞれインストールしていますがubuntuでやります。

masashi@PC-ubuntu:~$ uname -a ; lsb_release -a
Linux PC-ubuntu 5.4.0-51-generic #56-Ubuntu SMP Mon Oct 5 14:28:49 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.1 LTS
Release:    20.04
Codename:   focal

やり方

インストール時にCLI起動のコマンドも入ってるのかと思ったら無い...
公式ドキュメントを見るとシンボリックリンク作るだけの様ですね。
簡単だ。

Command Line Interface – Sublime Text Documentation

実行ファイルはここでした。

masashi@PC-ubuntu:~$ ls -l /opt/sublime_text/sublime_text 
-rwxr-xr-x 1 root root 8803928 101  2019 /opt/sublime_text/sublime_text
  • ファイル情報
masashi@PC-ubuntu:~$ file /opt/sublime_text/sublime_text 
/opt/sublime_text/sublime_text: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, stripped
masashi@PC-ubuntu:~$ sudo ln -s /opt/sublime_text/sublime_text /usr/local/bin/subl

動かしてみる

これでsublコマンドで起動できるようになりました。

  • ヘルプ
masashi@PC-ubuntu:~$ subl --help
Sublime Text build 3211

Usage: subl [arguments] [files]         Edit the given files
   or: subl [arguments] [directories]   Open the given directories

Arguments:
  --project <project>: Load the given project
  --command <command>: Run the given command
  -n or --new-window:  Open a new window
  -a or --add:         Add folders to the current window
  -w or --wait:        Wait for the files to be closed before returning
  -b or --background:  Don't activate the application
  -h or --help:        Show help (this message) and exit
  -v or --version:     Show version and exit

Filenames may be given a :line or :line:column suffix to open at a specific
location.

テストファイルを作ってみます。

sbul test.txt

でOK。

動画だとこんな感じです。(sublimeのライセンスはまだ買ってないんだ。すまない。)

f:id:paloma69:20201021223908g:plain

これでわざわざアイコンをクリックしなくてもよくなりました。
これは楽ちんです。

gitで初めてbranchを切ってみた

自宅環境での話ですが、自分で使うツール類をgitでバージョン管理しています。
個人用かつ作るのも自分一人ということで各ツールずっとmasterのブランチで更新を行っていました。

特に問題もなかったのですが、この度ブランチ作りをやってみたので記録しておきます。

作成の理由

  • 本業の人に開発の仕方を聞いた

ちょっと前にプログラマの方と話す機会があったのですが、開発用のブランチを切ってそのあとプロダクト用のブランチにマージしているということです。

プロダクトに行く前に複数層のブランチを挟むそうです。
まあ仕事でやるならそうですよね。

私の本業はSI系のインフラなのでいまだにExcel方眼紙の設計書を日付ファイル管理ですw

gitの使い方のサイト・動画は山ほどありますが、ブランチとは何ぞやという情報が無かったので改めてチュートリアルを読みました。

Bitbucketのサイトがわかりやすかったです。

www.atlassian.com

ブランチを作る理由は以下のようです。

  1. ブランチは変更時のSnapshotへのポインタとなる
  2. ブランチは機能追加やバグ取り用に作る
  3. メインブランチのコード履歴を綺麗にする

ブランチは複数人の平行開発用というイメージがありましたが、2と3の理由だと1人の開発でも作るメリットはありそうですね。

新機能用のブランチ作成

5月くらいから着手しているスリーカードポーカーゲームですが、CLIでは何とか遊べるようになりました。
後はGUI化したいというタスクがあるので、こちらのリポジトリでブランチを作ってみましょう。

github.com

ちなみに開発環境はubuntu20.04LTSです。

  • ブランチ確認

現在のブランチ確認。

masashi@PC-ubuntu:~/Three-card-poker$ git branch
* master

1つしかないですね。

  • ブランチ作成

GUI機能ということでgraphicalという名のブランチを作ります。

masashi@PC-ubuntu:~/Three-card-poker$ git branch graphical
  • ブランチ移動

作成したブランチに移動します。
branchは作るだけで、移動はcheckoutコマンドです。

masashi@PC-ubuntu:~/Three-card-poker$ git checkout graphical 
Switched to branch 'graphical'

確認。

masashi@PC-ubuntu:~/Three-card-poker$ git branch
* graphical
  master

OKですね。
移動できました。

ブランチでファイル作成

GUI用のファイルを作成します。
GUIでの処理の仕方がさっぱりなので枠だけです。
ラシャの感じは出せてるかなw

f:id:paloma69:20201017141739p:plain

このファイルをコミットしてみます。

masashi@PC-ubuntu:~/Three-card-poker$ git status
ブランチ graphical
追跡されていないファイル:
  (use "git add <file>..." to include in what will be committed)
    game.py

nothing added to commit but untracked files present (use "git add" to track)
masashi@PC-ubuntu:~/Three-card-poker$ git add game.py 
masashi@PC-ubuntu:~/Three-card-poker$ git commit -m "Create GUI file"
[graphical 583a058] Create GUI file
 1 file changed, 19 insertions(+)
 create mode 100644 game.py

masterブランチに影響ないか確認

他のブランチに影響がないか確認してみます。

masashi@PC-ubuntu:~/Three-card-poker$ ls
README.md  __pycache__  game.py  pokerapp.py  simulater.py  test_pokerapp.py

game.pyがGUI用のファイルです。

ブランチをmasterに変更。

masashi@PC-ubuntu:~/Three-card-poker$ git checkout master 
Switched to branch 'master'
Your branch is up to date with 'origin/master'.

再度lsすると

masashi@PC-ubuntu:~/Three-card-poker$ ls
README.md  __pycache__  pokerapp.py  simulater.py  test_pokerapp.py

game.pyファイルが無いですね。
OKです。

これで画面系のコードをメインブランチに影響を与えることなく作成し放題です。
画面処理の作り方が全然わからないのですが、じっくり進めていこうと思います。

おまけ pygame再インストール

画面処理はpygameを使おうと思っていますが、以前20.04LTSにアップデートした後aptのautoremoveを実行したのですが、
必要なライブラリを削除してしまった様で仮想環境のpygameが動かなくなってしまいました。
再インストールしようにも、

(pygames) masashi@PC-ubuntu:~$ pip install pygame
Collecting pygame
  Using cached pygame-1.9.6.tar.gz (3.2 MB)
    ERROR: Command errored out with exit status 1:
     command: /home/masashi/pygames/bin/python3 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-kwypge18/pygame/setup.py'"'"'; __file__='"'"'/tmp/pip-install-kwypge18/pygame/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-edtsy3uy
         cwd: /tmp/pip-install-kwypge18/pygame/
    Complete output (29 lines):

...    

    Hunting dependencies...
    WARNING: "sdl-config" failed!
    WARNING: "pkg-config freetype2" failed!
    WARNING: "freetype-config" failed!
    Unable to run "sdl-config". Please make sure a development version of SDL is installed.
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

このように失敗してしまうのですが、
このコマンドで必要なライブラリをインストールしてpygameも再インストールできました。

(pygames) masashi@PC-ubuntu:~$ sudo apt-get build-dep python-pygame
(長いので割愛)
(pygames) masashi@PC-ubuntu:~$ pip install pygame
Collecting pygame
  Using cached pygame-1.9.6.tar.gz (3.2 MB)
Using legacy 'setup.py install' for pygame, since package 'wheel' is not installed.
Installing collected packages: pygame
    Running setup.py install for pygame ... done
Successfully installed pygame-1.9.6

python - Installing pygame with pip - Ask Ubuntu

ubuntu18.04LTS -> 20.04LTSにアップデート

今年はubuntuのLTSリリースの年です。
2年ぶりにアップデートの時期がやってまいりました。
LTSは4月にリリースされますが、不具合報告とか手順のナレッジ等で半年ほど待って作業してます。

paloma69.hatenablog.com

私のubuntuはサブ機なんで不具合があってもそんなに問題ないんですが、そのままでも特に困ってなかったので放置していました。

今週は台風でどこにも行けないということで作業を実行しました。

事前バックアップ

一応作業前にバックアップ取っておきます。
と言っても使っているツールはgithubに乗せてあるのでローカルwikiDokuwikiのバックアップだけ取っておきます。

前回と同じくtarで固めて逃がすだけなので割愛。

状態はこんな感じです。

  • バージョン
masashi@PC-ubuntu:~$ uname -a ; lsb_release -a
Linux PC-ubuntu 4.15.0-118-generic #119-Ubuntu SMP Tue Sep 8 12:30:01 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.5 LTS
Release:        18.04
Codename:       bionic
  • デスクトップはこんな感じ

f:id:paloma69:20201010183346p:plain

ロサンゼルスではなくGTA Vのロスサントスです。
4:3なのは余っていたディスプレイを使っているからですw

バージョンアップ

サイトの手順通りです。
今回はostechnixの手順を参考にしました。

ostechnix.com

OSアップデート

最新版にして再起動しておきます。

masashi@PC-ubuntu:~$ sudo apt update && sudo apt dist-upgrade
masashi@PC-ubuntu:~$ sudo reboot
バージョンアップ用のセットアップ

アップデートマネージャをインストール。
定期的にアップデートしてるので、先のコマンド含め今回特にアップデートするパッケージはありませんでした。

masashi@PC-ubuntu:~$ sudo apt install update-manager-core
masashi@PC-ubuntu:~$ sudo apt install ubuntu-release-upgrader-core

設定ファイルを書き換え。
18.04LTSからアップデートする場合はPrompt=ltsにするそうです。
ファイルは変更なしでOKでした。

masashi@PC-ubuntu:~$ tail /etc/updatemanager/release-upgrades
#  normal - Check to see if a new release is available.  If more than one new
#           release is found, the release upgrader will attempt to upgrade to
#           the supported release that immediately succeeds the
#           currently-running release.
#  lts    - Check to see if a new LTS release is available.  The upgrader
#           will attempt to upgrade to the first LTS release available after
#           the currently-running one.  Note that if this option is used and
#           the currently-running release is not itself an LTS release the
#           upgrader will assume prompt was meant to be normal.
Prompt=lts
アップデート開始

下記コマンドで開始します。

masashi@PC-ubuntu:~$ sudo do-release-upgrade -d

途中でインストール済みのパッケージをどうするか聞かれますが、そのままで進めます。
baculaとか昔ちょっと勉強して使ってないなあ…。

f:id:paloma69:20201010183459p:plain

f:id:paloma69:20201010183511p:plain

f:id:paloma69:20201010183526p:plain

再起動

最後に再起動するか聞かれるのでyで選択。

f:id:paloma69:20201010183546p:plain

再起動後はこうなりました。

  • OSの起動

起動のデザインが変わりましたね。
黒ベースになってかっこいいです。

f:id:paloma69:20201010183732j:plain

  • バージョン

20.04になってます。
OKですね。
カーネルも5系になりました。

masashi@PC-ubuntu:~$ uname -a ; lsb_release -a
Linux PC-ubuntu 5.4.0-48-generic #52-Ubuntu SMP Thu Sep 10 10:58:49 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.1 LTS
Release:        20.04
Codename:       focal
  • デスクトップ

デザインはほとんど変わっていません。

f:id:paloma69:20201010183845p:plain

トップとサイドバーが黒くなりましたね。
半透明に変更したいな。

アイコンも微妙に今風のフラットデザインに変わりました。
サポートされなくなったソフトは削除されちゃいました。

参考手順でやらなかったこと

手順内の

  • screen
    • ubuntuの物理マシンで操作したため
  • iptables
    • デスクトップ版なので元々動いていない

という理由で行いませんでした。

参考まで。

アップデート完了です。

デスクトップ版なんでパッケージが多いのかアップデートを実行してから1時間40分ほどかかりました。
が、特に破損等の不具合もなく無事にアップデート完了しました。
使い勝手はまた使ってみてという感じですね。

18.04にアップデートしたのは記憶に新しいですが、あれから早2年も経ってしまったんですね。
一応振り返ってみるとインフラの技術はそんなに変わらずですが、pythonは割と書けるようになったと思います。

ubuntuは毎年新バージョンが出るので毎回アップデートしてもいいですが、2年おきくらいにこの記事を書くのがちょうどいいですね。
新機能を何も紹介してなくて申し訳ないですが…

という訳で、また2年後にお会いしましょう。

7zipのコマンドラインで圧縮と解凍

私の現場はオンプレ環境なのでマシン室に入っての作業があるのですが、作業ログを固めて事務所に持って帰るという作業が発生します。
サーバのログはtarで固めればいいですが、teraterm等のローカル側でのログも回収しないといけません。

マシン室の端末での作業を余儀なくされますが、圧縮の際毎回ポチポチと作業するのは面倒です。

幸いにも圧縮ツールは7zipがインストールされています。
7zipはCLIでの操作が出来ますので、楽するために今回はこれを覚えようと思います。

ググれば沢山出てきますが自分のブログの方が探しやすいですからね。

環境

サブWindowsPCで検証します。
7zipはインストールしてあるものとし、パスは通してません。

  • OSバージョン
PS C:\Users\masashi\7ziptest> Get-WmiObject Win32_OperatingSystem


SystemDirectory : C:\WINDOWS\system32
Organization    :
BuildNumber     : 18363
RegisteredUser  : user
SerialNumber    : 00330-80000-00000-AA868
Version         : 10.0.18363
  • 7zipバージョン

実行ファイルは7z.exeです。

PS C:\Users\masashi\7ziptest> & 'C:\Program Files\7-Zip\7z.exe' --help

7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30

Usage: 7z <command> [<switches>...] <archive_name> [<file_names>...]

ヘルプを見ると機能が沢山ありますが、断トツに使うフォルダの圧縮・解凍のみ確認します。
コマンドがバーッと出てきますが長いのでここでは割愛。

ちなみに7zipでは必須引数をcommand、オプション引数をswitchiesと言うそうです。
以下コマンド、スイッチで表記します。

圧縮

  • フォルダ構成

サンプル的に数フォルダとファイル作りました。

PS C:\Users\masashi\7ziptest> ls -r


    ディレクトリ: C:\Users\masashi\7ziptest


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2020/10/03     12:47                folder1
d-----       2020/10/03     12:48                folder2


    ディレクトリ: C:\Users\masashi\7ziptest\folder1


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2020/10/03     12:47             24 file1.txt
-a----       2020/10/03     12:47             24 file2.txt


    ディレクトリ: C:\Users\masashi\7ziptest\folder2


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2020/10/03     12:48             24 file3.txt
  • 圧縮

コマンドaで圧縮です。
スイッチは-pでパスワードをかけられます。
-pの後に文字列を対話無しでかけられますが、履歴に残るし定期的にやるわけでもないので手動入力にしました。

archive.zipという名前で固めます。
コマンドはtarとほとんど一緒ですね。

PS C:\Users\masashi\7ziptest> & 'C:\Program Files\7-Zip\7z.exe' a -p archive.zip .\folder1 .\folder2\

7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30

Scanning the drive:
2 folders, 3 files, 72 bytes (1 KiB)

Creating archive: archive.zip

Add new data to archive: 2 folders, 3 files, 72 bytes (1 KiB)


Enter password (will not be echoed):

Files read from disk: 3
Archive size: 824 bytes (1 KiB)
Everything is Ok

圧縮ファイルの中身確認

コマンドlです。
Listのエルです。

PS C:\Users\masashi\7ziptest> & 'C:\Program Files\7-Zip\7z.exe' l .\archive.zip

7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30

Scanning the drive for archives:
1 file, 824 bytes (1 KiB)

Listing archive: .\archive.zip

--
Path = .\archive.zip
Type = zip
Physical Size = 824

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2020-10-03 12:47:47 D....            0            0  folder1
2020-10-03 12:47:41 ....A           24           36  folder1\file1.txt
2020-10-03 12:47:47 ....A           24           36  folder1\file2.txt
2020-10-03 12:48:13 D....            0            0  folder2
2020-10-03 12:48:13 ....A           24           36  folder2\file3.txt
------------------- ----- ------------ ------------  ------------------------
2020-10-03 12:48:13                 72          108  3 files, 2 folders

解凍

解凍はファイルのみ展開するのと、パスを保持したままの展開ができます。
私はフォルダ名のまま展開という方法しかやらないので、その方法のみ記載します。

パス保持したまま展開はコマンドx、
スイッチ-spfでサブフォルダまで保持して展開できます。
-oで展開用のフォルダを作成できます。
自動で同名のまま展開できなかったのでunzipという名前にしてしまいましたが、
同じ名前にしたいなら一細工する必要がありそうです。

パスワードがあれば展開時に聞かれますので、特に引数は不要です。

PS C:\Users\masashi\7ziptest> & 'C:\Program Files\7-Zip\7z.exe' x -spf -o'unzip' .\archive.zip

7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30

Scanning the drive for archives:

Extracting archive: .\archive.zip
--
Path = .\archive.zip
Type = zip
Physical Size = 824


Enter password (will not be echoed):
Everything is Ok

Folders: 2
Files: 3
Size:       72
Compressed: 824
PS C:\Users\masashi\7ziptest> ls


    ディレクトリ: C:\Users\masashi\7ziptest


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2020/10/03     12:47                folder1
d-----       2020/10/03     12:48                folder2
d-----       2020/10/03     12:59                unzip
-a----       2020/10/03     12:49            824 archive.zip

展開したフォルダを確認すると圧縮したものと同じですね。

PS C:\Users\masashi\7ziptest> ls -r unzip


    ディレクトリ: C:\Users\masashi\7ziptest\unzip


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----       2020/10/03     12:47                folder1
d-----       2020/10/03     12:48                folder2


    ディレクトリ: C:\Users\masashi\7ziptest\unzip\folder1


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2020/10/03     12:47             24 file1.txt
-a----       2020/10/03     12:47             24 file2.txt


    ディレクトリ: C:\Users\masashi\7ziptest\unzip\folder2


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2020/10/03     12:48             24 file3.txt

むすび

今回は7zipの圧縮、解凍のみの簡単なコマンドを見てみました。

7zipコマンドラインの情報は各サイトいろいろありますが、
意外と自分が知りたい情報が無かったので整理してみました。

パスを全て保持したまま展開というのが意外と難しく何回も失敗しました。
(展開時にフォルダだけできて、ファイルは1階層目に展開しちゃうなど。-spfで解決)

ヘルプを見るとまだまだコマンドがありますが、とりあえずは圧縮・解凍を簡単にできそうです。

あとはdateコマンドのフォーマットをうまく使って一発圧縮ツールでも作りたいですね。

参考サイト

-spf (Use fully qualified file paths) switch

本当はやりたかったpythonの引数処理でのdry run

前回の映画視聴ツールの改修でやむなくフローの途中にechoを挟みましたが、
本当にやりたかったのは引数で出力を分岐させるというものです。

もともとpythonでやろうとして調べたのですが、このまま眠らせると忘れそうなので残しておきます。

argparseモジュール

通常の引数処理なら何個めの引数がこの場合うんたらかんたら...の処理を書くと思いますが
pythonには組み込みでargparseという引数解析のライブラリが付いてきます。

これを使って作ってみましょう。

コード

引数の有無で分岐させるという簡単な内容です。

masashi@PC-ubuntu:~$ cat dryrun.py
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--dry-run', help='Pre-execution',
                    action='store_true')
args = parser.parse_args()

if args.dry_run:
    print('映画情報の出力')
    print('この内容で投稿しますか?')
else:
    print('投稿しました!')

実行

  • ヘルプ

自動でヘルプ機能、ヘルプ文が作成されます。
便利ですね。

masashi@PC-ubuntu:~$ python3 dryrun.py --help
usage: dryrun.py [-h] [--dry-run]

optional arguments:
  -h, --help  show this help message and exit
  --dry-run   Pre-execution
  • dry run
masashi@PC-ubuntu:~$ python3 dryrun.py --dry-run
映画情報の出力
この内容で投稿しますか?

--dry-runの引数を付けると内容を出力させて確認できます。
投稿は行いません。

  • post
masashi@PC-ubuntu:~$ python3 dryrun.py
投稿しました!

引数なしだと今まで通り投稿を実行します。

この形にしたかったんだよ。

メモ

  • 構文

この辺はお約束の構文です。

parser = argparse.ArgumentParser()
parser.add_argument('--dry-run', help='Pre-execution',
                    action='store_true')
args = parser.parse_args()

引数のアクションをstore_trueにするとフラグとして扱われるようになります。

これが無いと値を取る引数として認識されます。
store_trueをつけておかないと上記の使い方ができません。

store_true無しの場合引数を求められます。

masashi@PC-ubuntu:~$ python3 dryrun.py --dry-run
usage: dryrun.py [-h] [--dry-run DRY_RUN]
dryrun.py: error: argument --dry-run: expected one argument
  • 作成した引数の指定

add_argumentで定義した引数名の先頭のハイフンを抜いたものに変換されるようです。
間のハイフンはアンダーバーになります。

parser.add_argument('--dry-run'

--dry-runが

if args.dry_run:

dry_runとして呼び出せるということですね。

まとめ

似たようなライブラリでclickというのがあるのですがインストールが必要なので今回はargparseで確認しました。
使っているツールには導入できなかったので簡単な検証になってしまいましたが、機会があれば活用したいと思います。

引数の処理ができるようになるとCLIのツールでも幅が広がりますね。

参考サイト

Argparse チュートリアル — Python 3.8.6 ドキュメント

Welcome to Click — Click Documentation (7.x)

映画視聴ツールにdry run的な機能を追加する

週末に映画を見てその記録をtwitterに残しておくという生活を送っているのですが、前回ツール使用時にこんな事象が発生しました。

(python3) masashi@PC-ubuntu:~/movietweet$ bash twmovieinfo.sh hot fuzz
Traceback (most recent call last):
  File "posttw.py", line 9, in <module>
    api.update_status(sys.argv[1])
  File "/home/masashi/python3/lib/python3.6/site-packages/tweepy/api.py", line 193, in update_status
    )(post_data=post_data, *args, **kwargs)
  File "/home/masashi/python3/lib/python3.6/site-packages/tweepy/binder.py", line 250, in _call
    return method.execute()
  File "/home/masashi/python3/lib/python3.6/site-packages/tweepy/binder.py", line 233, in execute
    raise TweepError(error_msg, resp, api_code=api_error_code)
tweepy.error.TweepError: [{'code': 186, 'message': 'Tweet needs to be a bit shorter.'}]

投稿できる文字数超過みたいですね。
今までこんなことなかったのに何が起きたのでしょうか?

原因

moviesコマンド結果をgrepしているのですが製作会社に「Title」が入っていて
映画タイトルと一緒にgrepして拾ってしまい投稿時の文字数超過エラーとなってしまったようです。

headコマンドを追加して回避しましたが、事前に出力確認する機能があれば怪しそうなところが発見できますよね。
という訳でdry run的な機能を追加しようと思います。

やりたいこと

  • 投稿前に出力させて内容を確認できるようにする
  • ついでに文字数確認

今までmoviesコマンド打って映画がヒットするの確認してからツールを打ってました。
出力結果が投稿ツールと違うし、チェックのフローも無いので今回のエラーが出てしまいました。

とはいったものの出来なさそうなので方向転換

よくあるdry run的な引数を作ってprintさせればいいかなんて思っていて、
pythonのargparseで引数から出力と投稿の分岐を考えたんですが、そういえば投稿ツール本体はshell scriptでした。

moviesというshell scriptを使用しているので投稿ツール本体もshellで書いたのですが、わざわざpythonで書き直すのもナンセンスです。

このままshell scriptの改修で進めよう。

実装方法

  1. 結果を出力するだけの引数処理を作る
  2. 出力、確認、投稿の処理に変更する
  3. 出力用のファイルを作る

映画のタイトルも引数で取っているので個別で1を作るのは難しそうです。
同じ様なファイルを作るのも何なので2を採用します。

映画情報を取ってきて投稿するだけなのでその前にechoとcaseで分岐すればできちゃいますね。

コード修正

diff --git a/twmovieinfo.sh b/twmovieinfo.sh
index 25d2345..7a72ae0 100644
--- a/twmovieinfo.sh
+++ b/twmovieinfo.sh
@@ -22,4 +22,21 @@ ${INFO}
 ---
 """
 
-python posttw.py "${TWEET}"
+echo "${TWEET}"
+strings=$(echo "${TWEET}" | wc -c)
+echo "${strings}文字"
+
+echo -n "投稿しますか?: [y/n]"
+read CONFIRM
+# デフォルトはNo
+case $CONFIRM in
+    [Yy]*)
+        python posttw.py "${TWEET}"
+        echo "投稿を完了しました。"
+    ;;
+    *)
+        echo "スクリプトを終了します。"
+        exit 0
+    ;;
+esac

修正はこれだけでした。
投稿しなくても、もう一度実行すればいいので特にループも無しです。
一応誤って投稿しないようにデフォルトはNoにしました。

出力結果

前回と同じHot Fuzzで打ってみます。

(python3) masashi@PC-ubuntu:~/movietweet$ bash twmovieinfo.sh 'hot fuzz' 
2020-09-23に「Hot Fuzz」を視聴しました。

Infomation
---
Year: 2007
Genre: Action, Comedy, Mystery, Thriller
Director: Edgar Wright
Actors: Simon Pegg, Martin Freeman, Bill Nighy, Robert Popper
Production: Working Title Films, Universal Pictures, StudioCanal #ここを拾って1行目のタイトルに反映されてしまっていた
---

275文字
投稿しますか?: [y/n]n
スクリプトを終了します。

いいんじゃないでしょうか。
投稿前の情報、文字数が確認できたのと投稿の選択も出来るようになりました。
投稿時のエラー判定まではできていませんが、280文字を超えないなら今まで通り使えそうです。

これで本体ツールだけで事足りる様になりました。

まとめ

本当はshellで引数を利用して出力だけ行うdry runの機構が作れたらと思ったんですが、難しいですね。
echoだけ行う判定を作ればいけそうですが、先述のとおり映画のタイトルも引数で拾っているので
その判定のために引数を分解して判定して…とやるよりは今回の方法で簡単にやってしまいました。

ふたを開ければただecho分を追加しただけですが、要件は満たせたので良しとします。

ちなみにHot Fuzzは田舎町に左遷されたエリート警官が田舎の闇とともに事件を解決していくという話です。
(警察が機能していないくらいの平和な田舎)
コメディ、サスペンス的な要素とドンパチのアクションもあり面白い映画でした。

参考サイト

2020年上半期見た映画メモ & twitter取得ツール改修 - paloma blog

Bash-Snippets - Useful BASH Scripts For Heavy Commandline Users