paloma blog

NWエンジニアやってます。主に自宅環境のお遊びを書きます。Pythonもちょっと。タイトルは好きなカクテルから。

古いNUCを買ったのでubuntuをインストールする

サブ機で使っていたUbuntuが壊れて半年以上たちます。
メインで使っているWindowsがあってWSLもあるのでLinux触るのに困ることはないのですが、たまにLinuxのデスクトップ環境を触りたくなります。
仮想ではなく物理ハードにインストールしてあるやつね。

安い中古があったら買おうと思っていたのですがこの度いい感じのを見つけました。
ジャンクワールドというショップでNUC6CAYSというモデルのOSなしがジャンク品として売っていました。

www.junkworld.jp

CPUはCeleronですが、メモリ8GあるしSSDとHDDが付いていて7000弱なので結構お買い得と思い2日ほど迷って購入しました。

1つ気にしたのがLinuxがインストールできるかです。
メーカーサイト見るとWindows10のみサポートと書いてあり動かなくては買う意味がありません。

昔、サーバ用途に安いワークステーション買ってLinuxいろいろインストールしたのですがOS起動できず原因もわからずで部屋の肥やしとなってしまいました。

ネットにもNUC7以降のインストールの記事はあるのですが今回買いたい機器の記事はなかなか...
と色々調べたら以下のサイトを見つけてLinux動きそうな雰囲気だったので購入に至りました。

  • Linux Hardware Database

Linux Hardware Database

  • Architecture Guide

Full Specifications for Intel Apollo Lake NUC Mini PC's NUC6CAYB Board Released - CNX Software

到着

届いたのはこちら。小さくていい感じです。

小さいのにそこそこ性能あるマシンはロマンがありますね。

インストール

Ubuntu22.04のLive USBをさして起動したらBIOSを特にいじることなく起動しました。
USBが認識されない問題があったけど認識されたりされなかったりで多分USBが古いデバイスだからでしょう。 (机がきたなくてすいません)

このままインストール。 ストレージが2つあるので/boot用とその他に分けてインストールしてみました。
せっかくSSD積んでるのでこっちを/bootにしてあとはHDDの方にインストール。

すんなりインストール完了です。

パーティション分けも上手いこと動きました。自分でやるとLVMを作るのは手順がいるみたい。
/homeも別に切っておけばよかったかなと思いましたが勉強というか戒めというかとりあえずこのまま使います。
知識としてはあるつもりでいたものの自分で作れないのは情けないですね。

しかしまたこの画面に出会えて嬉しい。
このマシンで何やるかはまだ決めてませんが。

ハードウェアスペック

ディスク構成

/boot/efiを作らないと警告が出たので作ってます。
先にスワップディスクを作ったのでsda1がswap領域になってしまったがまあいいか。
/homeも切っておけばよかったと少し後悔。

masashi@masashi-NUC6CAYS:~$ df
Filesystem     1K-blocks    Used Available Use% Mounted on
tmpfs             796556    1992    794564   1% /run
/dev/sda2      478612200 8387716 445838848   2% /
tmpfs            3982764       0   3982764   0% /dev/shm
tmpfs               5120       4      5116   1% /run/lock
/dev/mmcblk0p3  23973712  107564  22623012   1% /boot
/dev/mmcblk0p1   3990904    6216   3984688   1% /boot/efi
tmpfs             796552     184    796368   1% /run/user/1000
masashi@masashi-NUC6CAYS:~$ 
masashi@masashi-NUC6CAYS:~$ lsblk
NAME         MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
loop0          7:0    0     4K  1 loop /snap/bare/5
loop1          7:1    0  91.7M  1 loop /snap/gtk-common-themes/1535
loop2          7:2    0  53.3M  1 loop /snap/snapd/19457
loop3          7:3    0 349.7M  1 loop /snap/gnome-3-38-2004/143
loop4          7:4    0  73.9M  1 loop /snap/core22/858
loop5          7:5    0  63.4M  1 loop /snap/core20/1974
loop6          7:6    0  12.3M  1 loop /snap/snap-store/959
loop7          7:7    0 485.5M  1 loop /snap/gnome-42-2204/120
loop8          7:8    0   452K  1 loop /snap/snapd-desktop-integration/83
loop9          7:9    0 237.2M  1 loop /snap/firefox/2987
sda            8:0    0 465.8G  0 disk 
├─sda1         8:1    0   976M  0 part [SWAP]
└─sda2         8:2    0 464.8G  0 part /var/snap/firefox/common/host-hunspell
                                       /
mmcblk0      179:0    0  29.1G  0 disk 
├─mmcblk0p1  179:1    0   3.8G  0 part /boot/efi
├─mmcblk0p2  179:2    0   1.9G  0 part 
└─mmcblk0p3  179:3    0  23.4G  0 part /boot
mmcblk0boot0 179:8    0     4M  1 disk 
mmcblk0boot1 179:16   0     4M  1 disk 

BIOS

画面はこんな感じ。

NUCはデフォルトだとネットワークブートを行う様なので無効化。
これで再起動してもちゃんとOS起動できます。 いじったのはここだけ。

まとめ

OS無しPCを買うのは躊躇しましたがなんとか使えるところまで持ってきました。
これも動作実績のあるサイトを見つけられたからで先人たちに感謝です。

先代のマシンではフリーズの関係からKDEに買えてしまいましたがGNOMEも好きなのでこっちでriceに挑戦したいと思います。

手のひらネットワーク機器コンプリートしたので自慢

6月に新発売して少しSNSが賑わっていた手のひらネットワーク機器ですが、私もこの度コンプリートしました。
ちょっと前の9月半ばの話です。

発売した時すごく欲しかったのですがガチャ売り場探し回るのも嫌だなあと思っていたらなんと地元の行きつけの飲み屋さんのガチャコーナーに入荷していました。

その時は現金が少なかったので2回だけ回してc9300と古河電工のルータをゲット。

その3日後くらいに再チャレンジに行ったのですが残念ながら売り切れ...

6月時点の状態です。
これでもなかなかいいけどね。


その後諦めて過ごしていたのですが今月頭にフラッと行ったら「入荷したよ」の声が。
今月末の再販ニュースよりも前なのでガチャ業者に在庫があったのでしょうか。

早速連チャンで回すとまさかの被り無しでcisco MerakiとA10 thunderが!
コンプリートじゃん!と飲みもそこそこに早速帰ってラッキングしました。 4種類そろえないとラックも完成しないのですが、完成したラックはなかなか重厚感があります。

前面。

上からFITELnet、Meraki、A10 Thunder 、C9300です。
9300だけ一緒にガチャ回したお客さんに貰ったので冗長化しました。

背面。

実物のラッキングも何回もやっているのですが、このサイズでもなかなか楽しいです。

ケーブリングもう少し頑張れたけどこんなもんでいいでしょう。
欲を言えば全部冗長化したいですがこれだけでも十分見映えします。

是非サーバ版も出て欲しいですね。

jekyllをgithub pagesで公開する

映画視聴ログとして使っていたtwiteerのデータをjekyll用に移行しローカルで立ち上がるところまでやってきました。

こうなってくるとtwiteerにpostしてたみたいに公開したいと思います。

自宅ラボにデプロイしてもいいのですが触ってたjekyllをそのままgithubに公開できる様なので勉強がてらやってみます。

リポジトリ作成

pagesで公開するにはxxx.github.ioというリポジトリを作成しないといけないみたいです。
新規作成。

github.com

jekyllインストール

まずはローカルで作成です。
前回の検証用で作業してるのでインストールは割愛。
新しいサイトを作成。
Gemfile、config.yml、post配下ファイルは前回使ったサイト(movie)からコピーしてきます。

$ jekyll new --skip-bundle .
New jekyll site installed in /mnt/c/Users/masashi/gh-pages/logs-of-watched-movie.
Bundle install skipped.
$ ls
404.html  Gemfile  _config.yml  _posts  about.markdown  index.markdown
$
$ cp ../../jekyll/movie/Gemfile .
$ cp ../../jekyll/movie/_config.yml .

pages用にカスタムします。
Gemfileでjekyllをコメントアウトgithub-pagesモジュールを追記します。

# gem "jekyll", "~> 4.3.2"
gem 'github-pages', '~> 228', group: :jekyll_plugins

bundle install。

$ bundle install

_config.ymlにpages用設定を追加。

$ grep github _config.yml
github_username:  masashi69
domain: masashi69.github.io
url: https://masashi69.github.io

ローカルでテスト

まずはローカルで起動確認。

$ bundle exec jekyll serve      

/home/masashi/gems/gems/jekyll-3.9.3/lib/jekyll/commands/serve/servlet.rb:3:in `require': cannot load such file -- webrick (LoadError)

webrickエラーが出たので追加。
既知事象として公式にも記載があります。

$ bundle add webrick

再度起動して、

OKですがpagerが効いてないですね。
レイアウトも前回より変わってしまってます。
jekyllモジュールを外してしまったからだろうか。
後で直すとして一旦良しにします。

githubにpush

commitしてpushします。
この辺も何回もやってるのでコメントなし。

$ git push -u origin master
Username for 'https://github.com': masashi69
Password for 'https://masashi69@github.com':

pagesを確認

settings -> pagesからサイトにアクセスします。
でも何分経ってもリンクが作成されない。
Actionでログを見ようとしたけど動いていない様子。

よく確認したらブランチ名がmainになってました。
masterで作ったのでmain -> masterに変更。
リンクが作成されました。

Actionsも動いてます。

リンクにアクセスすると、

ローカルと同じ状態です。
課題はいくつか残りましたがデプロイ成功です!

まとめ

少し手こずりましたが割と簡単に公開できました。
本当はブログとかポートフォリオを乗せるのとかに使うのでしょうが、映画ログはしばらくこれで運用してみます。
ほかのいいコンテンツが思いついたらこの映画ログはどこかに移行してまたpagesを作り変えようと思います。

jekyllのpagerを有効にする

前回twitterに投稿していた映画データをjekyllに移植しました。
今回はpagerを設定してもう少しWebサイトっぽくします。

_config.yml

使用するpagerのプラグイン有効化、pagerの設定を記載します。 (10件ずつ表示)

#pager
plugins:
  - jekyll-paginate

paginate: 10
paginate_path: "page:num"

index.html

pager用のhtml構成に変更します。
ループで回して一定数ずつ表示という処理にすればいいんだけど、とりあえず公式のコードをコピペで済ませました。

Pagination(ページ分け) | Jekyll • シンプルで、ブログのような、静的サイト

デザインは後回しにしているのでlayout関係はいじっていません。

pluginインストール

ここで起動してみたのですが、ページが表示されません。

pager用のパッケージもインストールしないといけなかったみたいです。
(メンテされていないようで私もjekyll 4系なのですが、インストールしないと動きませんでした)

GitHub - jekyll/jekyll-paginate: NO LONGER UNDER ACTIVE DEVELOPMENT as of Jekyll 3: Pagination Generator for Jekyll

Gemfileに追記します。

masashi@DESKTOP-5RSN5EI:/mnt/c/Users/masashi/jekyll/movie$ vim Gemfile # jekyll-paginateを追加
masashi@DESKTOP-5RSN5EI:/mnt/c/Users/masashi/jekyll/movie$ bundle
masashi@DESKTOP-5RSN5EI:/mnt/c/Users/masashi/jekyll/movie$ gem install jekyll-paginate

これでOK。

mdファイルの修正

前回の記事でmdファイルのフォーマットが崩れた云々言いましたが、htmlはタグで決まるのでまずはこちらを意識しないといけないですね。
映画情報部分はrawデータを表示するようにpreタグを挟むように修正しました。
(インデント下げの処理より楽だったため)

あとtitleのFront matterも追記しました。

---
title: "Gold Brick"
---
2023-07-09に「Gold Brick」を視聴しました。

Infomation
<pre>
---
Year: 2023
Genre: Comedy, Drama
Director: J\u00e9r\u00e9mie Rozan
Actors: Rapha\u00ebl Quenard, Igor Gotesman, Agathe Rousselle
Production: N/A
---
</pre>

top画面

アーカイブ取得後に投稿したデータも手動で作成して配置しました。
topはこんな感じで追記されていきます。

index.htmlの内容をコピったのでtopにbody部の内容も表示されるようになりました。
これはこれでtwitterの状態と似た感じになりましたね。
pagerも一応機能してます。

ここは数字を出して好きな部分に飛べるよう修正したいところ。
期間の検索機能も欲しいですね。

まとめ

映画の情報を載せるだけのサイトですが何とか機能するものになってきました。
こうなってくるとどこかにホスティングしたいですね。
自宅のラボか、はたまた本件で使っているツールが置いてあるGithubでもjekyllに対応している様だし悪くないですね。

twitter archiveからjekyll用postのmdファイルを作る

映画資料記録のツールをjekyllで運用してみることにしました。
まずはtwitter archiveで取得したデータを抜き出さないといけません。
ツイートデータのフォーマットがjsonぽかったのでpythonで抜き出しjekyll用のmdファイルに落とし込みたいと思います。

ツイートデータのフォーマット

投稿データはdata/tweets.jsです。

masashi@DESKTOP-HBP3520:~/twitter-2023-07-11-de75330~$ head data/tweets.j
s
window.YTD.tweets.part0 = [
  {
    "tweet" : {
      "edit_info" : {
        "initial" : {
          "editTweetIds" : [
            "1678045323875450881"
          ],
          "editableUntil" : "2023-07-09T15:15:56.000Z",
          "editsRemaining" : "5",

中身はjsonっぽいフォーマットですが「window.YTD.tweets.part0 =」が邪魔なので削除します。

日付と投稿内容を抜き出してmdファイルを作るコード

jekyllの記事データはyyyy-mm-dd-title.mdというフォーマットなので

  • 投稿日時、映画タイトルからファイル名作成
  • 投稿内容をファイルに書き込み

という処理を行います。

twitterも数年使ってますとやはり何千行ものデータになるので、
ツールで投稿した映画情報データのみ抜き出すようプログラムを作成します。
というわけでコードはこちら。
解説は割愛します。

# coding: utf-8

import json
import re
import datetime

with open('tweets.js', 'r', encoding='utf8') as f:
    tw = f.read()

lfile = json.loads(tw)

for x in range(len(lfile)):
    if '視聴しました' in lfile[x]['tweet']['full_text']:
        posted = lfile[x]['tweet']['created_at']
        strtime = datetime.datetime.strptime(posted, "%a %b %d %H:%M:%S %z %Y")
        titlefile = strtime.strftime('%Y-%m-%d')
        content = lfile[x]['tweet']['full_text']
        try:
            title = re.search('「.+」', content).group()
            title = title[1:-1]
            titlefile = titlefile + '-' + title + '.md'
            with open(titlefile, 'w', encoding='utf-8') as md:
                md.write(content.replace('---','=====')) # jekellのfront matterと重複するので変換
        except:
            pass

実行

修正したtweets.jsを上の階層にコピーしました。

masashi@DESKTOP-HBP3520:~/twitter-2023-07-11-de75330~$ ls
'Your archive.html'   assets   create_mdfiles.py   data   tweets.js

コード実行。

masashi@DESKTOP-HBP3520:~/twitter-2023-07-11-de75330~$ python3 create_mdfiles.py

320ファイル作成できました。
実際はテスト投稿で重複データもありますが記録したものだけでも300本は映画を見てきたということですね。
これはなかなか。

masashi@DESKTOP-HBP3520:~/twitter-2023-07-11-de75330~$ ls *md | wc -l
320

ちゃんとフォーマット通りのファイルができてます。
2019年に記録ツールを作ったんですねぇ。

masashi@DESKTOP-HBP3520:~/twitter-2023-07-11-de75330~$ ls *.md | head
2019-08-24-Pulp Fiction.md
2019-08-24-Smoke.md
2019-08-31-City of Tiny Lights.md
2019-09-07-Dazed and Confused.md
2019-09-14-Ali G Indahouse.md
2019-09-22-How to Talk to Girls at Parties.md
2019-10-06-American Hustle.md
2019-10-14-Killing Them Softly.md
2019-10-19-The Internship.md
2019-10-27-Batman.md

ファイルの中見。
投稿データがそのままbody部になってます。
front matterの記述をつけ忘れたけどjekyllのデザインも決めてないし後で修正しましょう。

masashi@DESKTOP-HBP3520:~/twitter-2023-07-11-de75330~$ cat 2019-08-24-Smoke.md
2019-08-24に「Smoke」を視聴しました。

その他Infomation
=====
Year: 1995
Genre: Comedy, Drama
Director: Wayne Wang
Actors: Giancarlo Esposito, Jose Zuniga, Stephen Gevedon, Harvey Keitel
Production: Miramax
=====

jekyllにデプロイ

作成したファイルを検証環境のjekyllに入れます。
_posts配下にtarで固めたものを展開するだけ。

serveで立ち上げます。
軽量フレームワークといっても300ファイルあるとさすがに1分弱ほど起動にかかります。

Run in verbose mode to see all warnings.
                    done in 52.612 seconds.

ブラウザでアクセス

ブラウザで見てみます。

デザインはデフォルトのものなのでブログタイトル等そのままで味気ないですが最新の日付から降順で並んでますね。
twitterみたいにリンク飛ばずとも中身も表示させたいところですがブログツールなのでこんなものでいいでしょう。 pagerの設定をしていないのでスクロールがめちゃ長いです。

中身をみるとこちらもレイアウトが崩れちゃってますね。
区切りの記号か文字コードがよくなかったか。

こちらの修正はするとして、ファイルを置いていくだけで更新できるのはお手軽です。
記録ツールの代替としても機能しそう。
なのでomdb apiの情報をjekyllフォーマットで保存するツールも作らないとですね。

スクレイピングでfワードを数える2

最近映画視聴記録がどうのという記事を書いていたのですが、映画関連で昔パルプフィクション絡みのやつを書いたことを思い出しました。
内容はタイトルの通りなのですが、以前の記事ではやり残しがありました。
プログラム歴も増えてきたので今なら出来るっしょということでリメイク版です。

前回のおさらい

paloma69.hatenablog.com

  • 台本上のfワードは169個
  • やり残し
    1. セリフの成形
    2. 件数の表示
    3. 誰が何回言ったかのサマリ

コード

今回は全処理関数化してライブラリ的に呼び出せる様にしました。
(わざわざ呼び出して使う機会は無いと思うが)
引数の値もう少し統一感出せばよかったな。
今回も一応全編通して伏字にします。

from bs4 import BeautifulSoup
import re
import collections

def create_quote_list():
    with open('Pulp-fiction.html', 'r', encoding='utf-8') as f:
        soup = BeautifulSoup(f.read(), 'html.parser')

    lines = []
    for x in soup.findAll('b'):
        lines.append((x.text, x.next_sibling))

    return lines

def into_list(l, chara, quote):
    shaping_charactor = chara.replace("\n", "").replace(" ", "").replace("(O.S.)", "")
    if shaping_charactor == 'CLOSEUP・MIA':
       shaping_charactor = 'MIA'
    l.append([shaping_charactor, quote])

def scraping_words(script_list):
    s_reg = re.compile('.+[fF]xxk.+')
    flist = []
    for l in script_list:
        split_sentense = re.split('[,.!?]|and', str(l[1]))
        for x in split_sentense:
            w = re.search(s_reg, x)
            if bool(w) is True:
                s = w.group().replace("\n", " ").replace("  ", "")
                if 'AND' in l[0]:
                    for y in l[0].split('AND'):
                        into_list(flist, y, s)
                else:
                    into_list(flist, l[0], s)

    return flist

def fcounter(l):
    max_c, max_w = shapes(l)
    clist = []
    for x in l:
        clist.append(x[0])
    c = collections.Counter(clist).most_common()
    for x in c:
        c, w = x
        print(c.ljust(max_c), w)

def shapes(l):
    max_c, max_w = 0,0
    for f in l:
        if len(f[0]) > max_c:
            max_c = len(f[0])
        if len(f[1]) > max_w:
            max_w = len(f[1])
    return max_c, max_w

def fquote(l):
    max_c, max_w = shapes(l)
    n = 1
    for x in l:
        print(n, x[0].ljust(max_c), x[1].ljust(max_w))
        n +=1

def main():
    lines = create_quote_list()

    flist = scraping_words(lines)
    print('*' * 10, 'print f word list', '*' * 10)
    fquote(flist)
    print('*' * 10, 'print f word count', '*' * 10)
    fcounter(flist)

if __name__ == '__main__':
    main()

スクリプト叩いて終了では味気無いのでインタラクティブシェルでインポートして少し見ましょう。 本当はこの呼び出し方は非推奨です。

>>> from pulp import *

スクレイピング対象

前回と同じくimdbのサイトにscriptがあるので、これをダウンロードしてつかいます。

https://imsdb.com/scripts/Pulp-Fiction.html

スクレイピングのライブラリはBeautifulSoupです。

スクレイピング処理も呼び出して格納。

>>> lines = create_quote_list()

HTML構成

上記サイトのscriptファイルはしっかりと階層化はされてなくて、 bタグでシチュエーションや登場人物、次の階層(タグなし)に状況やセリフが書かれています。 タグが無くてもnext_siblingというmethodで取得できます。 create_quote_list()内でbタグとその次のセリフを取得してます。

    for x in soup.findAll('b'):
        lines.append((x.text, x.next_sibling))

取得した値はこう。

>>> lines[0]
('                                      "PULP FICTION"\n', '\n                                            By\n\n
 Quentin Tarantino & Roger Avary\n\n')
>>> lines[10]
('                                     YOUNG WOMAN\n', '
           You sound like a duck.\n                              (imitates a duck)\n                         Quack, quack, quack, quack, quack, \n                         quack, quack...\n\n')
>>> lines[20]
('                                     YOUNG WOMAN\n', '
           Did they hurt the little girl?\n\n')

スペース、改行記号の処理は別関数のshapingで行います。

ワードの取得

正規表現でワードと前後の文を抽出します。
4文字だけだと同じ文字が続くだけなので、結構バリエーションが出てくるのでせっかくだし前後も取ることにしました。
/w+等使って文章ごとに取りたかったのですが特殊文字や余剰スペースの処理で上手く全件ヒットとはならなかったのでフレーズごとに取得してます。

>>> f = scraping_words(lines)
>>> f[0]
['YOUNGMAN', ' I sound like a sensible fxxking man']
>>> f[10]
['YOUNGMAN', ' fxxk it']
>>> f[100]
['JULES', " Don't you fxxkin' do "]
>>> f[20]
['VINCENT', " but you're in the same fxxkin' "]

少し短いですが誰がどんな感じのこと言ってるかの雰囲気はわかります。

カウントのためリストに格納

上記と同じくscraping_words()の処理の話ですがカウントできるよう取得項目を人物、セリフに分割してリストにいれていきます。
文章を正規表現で抜き出すというのはやはりブレが出るため難しく、フレーズごとに分割してから対象のワードをひっかける方法にしました。
(件数が合わなくてあれ?となり何回か方法を施行しました)

一件だけ2人が同時に叫ぶ所がありますが、人物をカウントしたいのでここもさらに分割してます。

def scraping_words(script_list):
    s_reg = re.compile('.+[fF]xxk.+')
    flist = []
    for l in script_list:
        split_sentense = re.split('[,.!?]|and', str(l[1]))
        for x in split_sentense:
            w = re.search(s_reg, x)
            if bool(w) is True:
                s = w.group().replace("\n", " ").replace("  ", "")
                if 'AND' in l[0]:
                    for y in l[0].split('AND'):
                        into_list(flist, y, s)
                else:
                    into_list(flist, l[0], s)

また、スクリプト上で登場人物の表記が少しブレるので修正します。 セリフだけで画角にいないと台本に(S.O.)と言う表記が付くらしいです。
あとミアがCLOSEUPと付くシーンが一件だけあるのでこれも修正。 これらを取り除いてリストに入れるのがinto_listです。

後でアウトプットは出てくるのでコードだけおさらい。

def into_list(l, chara, quote):
    shaping_charactor = chara.replace("\n", "").replace(" ", "").replace("(O.S.)", "")
    if shaping_charactor == 'CLOSEUP・MIA':
       shaping_charactor = 'MIA'
    l.append([shaping_charactor, quote])

何回言ったかのカウンタは別関数でまとめます。

def fcounter(l):
    max_c, max_w = shapes(l)
    clist = []
    for x in l:
        clist.append(x[0])
    c = collections.Counter(clist).most_common()
    for x in c:
        c, w = x
        print(c.ljust(max_c), w)

出力

最後にアウトプット。

まずはfワードを全件出します。
罵詈雑言の嵐です(笑)

>>> fquote(f)
1 YOUNGMAN    I sound like a sensible fxxking man
2 YOUNGMAN    takin' the same fxxkin' risk as when
3 YOUNGMAN    fxxkin' A it worked
4 YOUNGMAN    but a fxxkin' phone
5 YOUNGMAN    lift a fxxkin' finger
6 YOUNGMAN    fxxkin' speak English
7 YOUNGMAN    don't know what it fxxkin' means
8 YOUNGMAN    one of those gook motherfxxkers'
9 YOUNGMAN    fifteen fxxkin' generations
10 YOUNGMAN    counter with a fxxkin' Magnum
11 YOUNGMAN    fxxk it
12 YOUNGMAN    gonna really give a fxxk you're
13 HONEYBUNNY  Any of you fxxkin' pricks move
14 HONEYBUNNY  motherfxxkers
15 JULES       man ・I'm fxxkin' goin'
16 VINCENT     they wouldn't know what the fxxk a
17 VINCENT     they fxxkin' drown 'em in it
18 VINCENT     We should have fxxkin' shotguns
19 JULES       Marsellus fxxked his ass up
20 VINCENT     fxxk her
21 VINCENT     but you're in the same fxxkin'
22 JULES       the same fxxkin' thing
23 JULES       ain't even the same fxxkin' sport
24 JULES       massages ・I'm the foot fxxkin'
25 JULES       fxxk you
26 JULES       fxxk you
27 JULES       motherfxxkin-house
28 JULES       fxxkin' up the
29 JULES       Motherfxxker do that to
30 JULES       I'd kill'a motherfxxker
31 VINCENT     That's what's so fxxkin'
32 VINCENT     fxxkin' Marsellus knew it
33 VINCENT     shoulda known fxxkin' better
34 VINCENT     his fxxkin' wife
35 JULES       You'a smart motherfxxker
36 BRETT       are about how fxxked up things got
37 JULES       English-motherfxxker-can-you-speak-
38 JULES       motherfxxker
39 JULES       Then why did you try to fxxk 'im
40 JULES       Ya tried ta fxxk
41 MARSELLUS   motherfxxker
42 MARSELLUS   that's a hard motherfxxkin' fact of
43 MARSELLUS   motherfxxkers who thought their ass
44 MARSELLUS   fxxkin' wit ya
45 MARSELLUS  fxxk pride
46 VINCENT     man's fxxkin' wife
47 LANCE       But this one's a fxxkin'
48 LANCE       any ol' day of the fxxkin' week
49 LANCE       Coke is fxxkin'
50 LANCE       in a big fxxkin' way
51 VINCENT     You know what some fxxker did to it
52 VINCENT     fxxkin' keyed it
53 LANCE       that's fxxked up
54 VINCENT     out five fxxkin' days ・five days
55 VINCENT     some dickless piece of shit fxxks
56 LANCE       They should be fxxkin' killed
57 LANCE       You don't fxxk
58 VINCENT     What the fxxk is this place
59 VINCENT     That's a pretty fxxkin'
60 VINCENT     but it's pretty fxxkin'
61 MIA         shit the fxxk up for a minute
62 MIA         like it's on fxxking fire)
63 JODY        I thought you told those fxxkin'
64 LANCE       tell this fxxkin' asshole right now
65 LANCE       this fxxkin' late
66 VINCENT     fxxkin' trouble man
67 VINCENT     fxxkin'Doing on me
68 LANCE       fxxkin' joking with you
69 LANCE       be bringing some fxxked up pooh-butt
70 LANCE       Then bite the fxxkin' bullet
71 LANCE       She ain't my fxxkin' problem
72 LANCE       fxxked her up
73 LANCE       your car in my fxxkin' house
74 LANCE       fxxkin' phone ・
75 LANCE       that fxxked up bitch in my house
76 VINCENT     This fxxked up bitch is Marsellus
77 VINCENT     Now if she fxxkin'
78 JODY        What the fxxk's goin' on
79 JODY        here being nobody knows what the fxxk they're doing
80 LANCE       Get the fxxkin' shot
81 VINCENT     Get the fxxkin' shot
82 VINCENT     I'm not fxxkin' stoppin' you
83 LANCE       My black fxxkin' medical book
84 VINCENT     fxxk the
85 VINCENT     Quit fxxkin' around man
86 VINCENT     This ain't a fxxkin' joke man
87 MARSELLUS   this motherfxxker
88 FABIENNE    Shut up fxxk head
89 BUTCH       Yes I've fxxkin' looked
90 BUTCH       What the fxxk do you think I'm doing
91 BUTCH       that was my father's fxxkin'
92 BUTCH       all I gave a fxxk about was my watch
93 BUTCH       Of all the fxxkin' things she coulda
94 MARSELLUS   I'm pretty fxxkin' far from
95 BUTCH       fxxk the bags
96 BUTCH       we gotta hit the fxxkin' road
97 JULES       blowing them all away while they're fxxkin' around
98 VINCENT     Why the fxxk didn't you tell us about
99 JULES       We should be fxxkin' dead right now
100 JULES       We should be fxxkin' dead
101 JULES       Don't you fxxkin' do
102 JULES       What just happened was a fxxkin'
103 VINCENT     Chill the fxxk out
104 JULES       We should be fxxkin' dead now
105 JULES       I want you to fxxkin' acknowledge
106 JULES       eyes are wide fxxkin' open
107 VINCENT     What the fxxk does that mean
108 VINCENT     ・you're fxxkin' freakin' out
109 JULES       What the fxxk's happening
110 JULES       Why the fxxk did you do that
111 JULES       The car didn't hit no motherfxxkin'
112 JULES       motherfxxker
113 JULES       drenched in fxxkin' blood
114 JULES       fxxk we're gonna go
115 JULES       We gotta be real fxxkin' delicate
116 JULES       What the fxxk did you just do to his
117 JULES       didn't look like a fxxkin' Maxie
118 JULES       fxxk it
119 JULES       gourmet fxxkin' shit on us
120 JIMMIE      how fxxkin' good it is
121 JIMMIE      fxxkin' business
122 JIMMIE      fxxkin' divorced
123 JIMMIE      get fxxkin' divorced
124 JIMMIE      ・don't fxxkin' Jimmie me
125 JIMMIE      than get the fxxk out of my house
126 JULES       fxxk up your shit
127 MARSELLUS   No fxxkin' shit she'll freak
128 JULES       motherfxxkin' "ifs
129 JULES       motherfxxker
130 MARSELLUS   I'm on the motherfxxker
131 THEWOLF     the fxxk outta Dodge
132 JULES       motherfxxker's tip-top
133 THEWOLF     you better fxxkin' do it
134 THEWOLF     clean the fxxkin' car
135 JULES       This is some fxxked-up
136 JULES       The motherfxxker who said that
137 VINCENT     it's fxxkin' dangerous to be
138 JULES       mushroom-cloud-layin' motherfxxker
139 JULES       fxxk am I doin' in the back
140 JULES       the motherfxxker should be on brain
141 JULES       that water's fxxkin' cold
142 JULES       motherfxxker
143 THEWOLF     does a fxxkin' thing 'til I do
144 THEWOLF     I drive real fxxkin' fast
145 JULES       motherfxxker
146 JULES       motherfxxkin' charmin' pig
147 JULES       my fxxkin' car keys
148 JULES       That's what's fxxkin' wit' me
149 VINCENT     of fxxkin' zombies
150 VINCENT     gonna be ・a fxxkin' bum
151 VINCENT     Stop fxxkin' talkin' like that
152 HONEYBUNNY  Any of you fxxkin' pricks move
153 HONEYBUNNY  motherfxxkers
154 HONEYBUNNY  Now mean fxxkin' now
155 HONEYBUNNY  do it or fxxking die
156 PUMPKIN     now git your fxxkin' ass
157 JULES       Keep your fxxkin' mouth closed
158 PUMPKIN     unload right in your fxxkin' face
159 HONEYBUNNY  your fxxkin' head off
160 HONEYBUNNY  gonna fxxkin' die bad
161 JULES       And when motherfxxkers
162 JULES       that's when motherfxxkers
163 JULES       fxxkin' fried chicken
164 VINCENT     What the fxxk's goin' on here
165 JULES       Motherfxxker on it
166 JULES       with "Bad Motherfxxker" embroidered on it
167 JULES       That's my bad motherfxxker
168 JULES       shut the fxxk up
169 JULES       say to a motherfxxker 'fore you popped

169件で前回と同じ件数です。OK。

続いて何回言ったかカウンタ。
やはり出演シーンの多い主人公達が多いですね。
本当は同一人物がいるのですが一応ネタバレになるのでここは手つけずです。

>>> fcounter(f)
JULES      59
VINCENT    35
LANCE      19
YOUNGMAN   12
MARSELLUS  9
HONEYBUNNY 8
BUTCH      7
JIMMIE     6
THEWOLF    5
JODY       3
MIA        2
PUMPKIN    2
BRETT      1
FABIENNE   1

OK。
成形もうまいこと効いていていい感じに出力できました!

まとめ

フタを開けてみると成形のコードがほとんどでスクレイピング正規表現は全然やってませんでしたw
やはりセリフを正規表現で抜き出すというのは文章やワードなどかなりのバリエーションがあり難しいです。
前述しましたが結局フレーズ毎に区切ってからワードを抜き出すという方法に落ち着きました。

とりあえず望む結果になったのでよしとします。

さすがに前回より日が経っているだけあって積み残しの解決も出来たしコードの書き方も少しは綺麗に出来たかなと思います。

最近パルプフィクション見てないのですがこの記事書いてたらまた見たくなってしまいました。

映画視聴記録として静的サイトジェネレータってどうだろう

前回のAPIの記事の続きですが、twitter APIがfreeだとPOST/DELETEしかできなくなりました。
映画視聴記録として使っていたのですが、このままでは読み(GET)ができません。
この映画見たっけなという感じで使っていたので気軽に使えないのでは不便です。

こんな感じね。(もう動かないけど)

(movies2) masashi@PC-ubuntu:~/movietweet$ python gettw.py --year=2022 | grep -P '2022-(0[7-9]|1[0-2])' | nl
     1  2022-12-25 22:55:21 Old School
     2  2022-12-25 09:35:17 The Batman
     3  2022-12-18 21:11:57 Charlie's Angels
     4  2022-12-17 23:36:10 The Ruthless
     5  2022-12-11 22:56:49 The Whole Nine Yards

他のSNSに移し替えてもいいんですがいつかまた同じ流れになるとも限りません。
ここはエンジニアとして食べている身として自分で何とかしましょう。

メモ帳とかDokuwikiとかに記録するというので十分事足りるのですが、もう少しエンジニアらしいもので記録したいです。

といっても映画タイトルとその他ちょっとのテキストのみの情報をわざわざWordpressとかのソフトウェアまで使うのかというとオーバーですよね。
じゃあDBに突っ込んどくかと言って成形したものをわざわざSQLiteとかに入れるのも違う感じがします。

そんな時昔見つけたjekyllという静的サイトジェネレータの存在を思い出しました。

jekyllrb.com

Webサーバの形を保ちつつテキストファイル配置のみで記事更新できる。
やりたいことにマッチしそうです。
静的サイトジェネレータで検索するとたくさん出てきて使い慣れてるpythonでもできそうですが、ご縁を信じてjekyllを触ってみます。

とりあえずお試しでスタンドアロンで作ります。
jekyllはruby製で詳しくありませんがフレームワーク本体をカスタムするわけでもなし、なんとかなるでしょう。

環境

サブwindows機のwslで試します。

masashi@DESKTOP-5RSN5EI:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.1 LTS
Release:        22.04
Codename:       jammy
masashi@DESKTOP-5RSN5EI:~$ ruby -v
ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux-gnu]
masashi@DESKTOP-5RSN5EI:~$ jekyll -v
jekyll 4.3.2

jekyllインストール

お試しで環境構築済みなので割愛。

こんなコマンドです。

gem install jekyll builder
jekyll new myblog
bundle exec jekyll server

movieというディレクトリでサイト作成。

masashi@DESKTOP-5RSN5EI:/mnt/c/Users/masashi/jekyll$ jekyll new movie

…

New jekyll site installed in /mnt/c/Users/masashi/jekyll/movie.

デフォルトのツリー構成です。

masashi@DESKTOP-5RSN5EI:/mnt/c/Users/masashi/jekyll/movie$ tree
.
├── 404.html
├── Gemfile
├── Gemfile.lock
├── _config.yml
├── _posts
│   └── 2023-07-21-welcome-to-jekyll.markdown
├── about.markdown
└── index.markdown

1 directory, 7 files

テンプレhtml等は触らず

jekyllの動きを見るだけなのでとりあえずテンプレートとなるhtmlや処理系は触らずデフォルトでいきます。

立ち上げてブラウザで見るとこんな感じ。

一応オートリロードで起動しました。
でもこれだけだとpost配下においても記事が読み込まれません。
ほかのオプションがあるのでしょうか。

masashi@DESKTOP-5RSN5EI:/mnt/c/Users/masashi/jekyll/movie$ jekyll serve -q --livereload &

postのテスト

投稿のテストします。
日付、タイトルの命名フォーマットはありますが、mdファイルとして配置すればいい感じにレンダリングしてくれます。
デフォルトで作成されるファイルを消して直近見た5ファイルを配置。

:がファイル名に使えないのでタイトルにあるものは除外してます。(John wick2とか)

masashi@DESKTOP-5RSN5EI:/mnt/c/Users/masashi/jekyll/movie$ tree _posts/
_posts/
├── 2023-07-02-Never Back Down 2 The Beatdown.md
├── 2023-07-03-John Wick chapter2.md
├── 2023-07-09-Gold Brick.md
├── 2023-07-17-The Guilt Trip.md
└── 2023-07-17-The Irishman.md

0 directories, 5 files

ファイルの中身です。(アイリッシュマン)

masashi@DESKTOP-5RSN5EI:/mnt/c/Users/masashi/jekyll/movie$ cat _posts/
2023-07-17-The\ Irishman.md
---
title: The Irishman
---

2023-07-17に「The Irishman」を視聴しました。

\``` # 記事の記法と被るのでエスケープしてます
Infomation
---
Year: 2019
Genre: Biography, Crime, Drama
Director: Martin Scorsese
Actors: Robert De Niro, Al Pacino, Joe Pesci
Production: N/A
---
\```
タイトルページ

いわゆるトップページです。
配置した記事ファイルが更新され謳い文句の通りブログっぽい感じになりました。

中身

アイリッシュマンのページを見てみます。

味気ない感じはありますがいいですね。
このままでも今までのTwitter投稿と同じで用途としてはokですがデザイン修正や感想のフィールドなど置いてもう少し見栄えよくなるといいかも。

mdファイル配置が記事の更新になるのでomdb APIから引っ張ったあとファイル生成の機能を作らないといけませんね。

これは次回やりたいと思います。

まとめ

Twitter投稿ツールの代わりに静的サイトジェネレータを触ってみました。
LAMPサーバと違いテキストファイルを置くだけで記事が更新されるという仕組みでお手軽です。
ちょうど自分でカスタムするようなWebサーバを触りたかったところで、かと言ってDBまで設計するといつまでも完成しない…と思っていたのでjekyllは今の自分のニーズにマッチするOSSだと思います。

今までの視聴データを乗せ換えてしばらく使ってみたいと思います。
自ラボのコンテナに乗せるかどこかのホスティングサービスに乗せるかは考え中…。