Pythonスクリプトで Imgurに画像を匿名投稿

はじめに


▼環境

1. Imgur アカウント登録

API 利用のために Imgur アカウントを作成する

2. Imgur アプリ登録

参考: https://api.imgur.com

下記サイトからアプリ登録を行う

登録後 表示される ClientID, ClientSecret をメモ

3. API 実行

公式の Python ライブラリを利用

▼ライブラリインストール
pip install imgurpython

▼コード

import sys
from imgurpython import ImgurClient

# 画像パスの指定
args = sys.argv
image_path = args[1]

print("image_path: " + image_path)

# ImgurClient 作成
client_id = 'XXXXXXXXXXXXXXXX'
client_secret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'

client = ImgurClient(client_id, client_secret)

# 画像アップロード
print("# uploading ...")
image = client.upload_from_path(image_path, config=None, anon=True)

# 画像リンク表示
print("# upload done")
print(image["link"])

▼実行


得られたリンクをコピペして Markdown記事などで利用

<img src="https://i.imgur.com/TgZDCsX.png" width=300>

Markdown ↓出力

PowerShellのキーバインドをEmacs風にする【PSReadLine】

はじめに

環境は以下の通り

手順

PSReadLine を導入する

↓ソース

PowerShell を管理者権限起動して、 Install-Module PSReadLine を実行

notepad $PROFILE を実行、プロファイルに下記設定を追加

if ($host.Name -eq 'ConsoleHost')
{
    Import-Module PSReadLine

    # キーバインドをEmacs風に変更
    Set-PSReadlineOption -EditMode Emacs

    # ### (以下追加)
    # Ctrl+i をTab と同じ "Complete" に割当
    Set-PSReadLineKeyHandler -Key Ctrl+i -Function Complete
    # Ctrl+j をEnter と同じ "AcceptLine" に割当
    Set-PSReadLineKeyHandler -Key Ctrl+j -Function AcceptLine

    # Ctrl+y を "Paste" に変更
    Set-PSReadLineKeyHandler -Key Ctrl+y -Function Paste
    # Ctrl+d を "DeleteChar" に変更
    Set-PSReadLineKeyHandler -Key Ctrl+d -Function DeleteChar
    
}

  • Ctrl+y のデフォルトFunction は "Yank"
  • Ctrl+d のデフォルトFunctionは "DeleteCharOrExit"
    • DeleteCharOrExit: カーソル位置の文字を削除、空行の場合は処理を終了
    • DeleteChar : カーソル位置の文字を削除

キーバインド

キーバインドGet-PSReadlineKeyHandler で表示できる

▼カーソル移動

Key Function 内容
Ctrl+a BeginningOfLine カーソルを行頭に移動
Ctrl+e EndOfLine カーソルを行末に移動
Ctrl+f ForwardChar カーソルを 1文字前に進める
Ctrl+b BackwardChar カーソルを 1文字前に戻す

▼編集

Key Function 内容
Ctrl+d DeleteChar カーソル位置の 1文字を削除
Ctrl+h BackwardDeleteChar カーソル前の 1文字を削除
Ctrl+y Paste クリップボードの内容をペースト

▼コマンド

Key Function 内容
Ctrl+j AcceptLine Enter と同じ
Ctrl+n NextHistory コマンド履歴表示 (次の項目)
Ctrl+p PreviousHistory コマンド履歴表示 (前の項目)

PowerShell を使ってExcel を操作する

Table of Contents

  1. はじめに
    1. 参考
  2. Excel の起動
  3. シートの追加
  4. セルの編集
  5. 表の作成
  6. グラフの作成
  7. 保存、終了

はじめに

PowerShell を使った Excel 操作のコマンドのメモ。

▼ メリット

  • Input – Output を明確化できる
  • 1つ1つのコマンド実行結果を視覚的に確認できる
  • VBA を触らずに済む

参考

PowerShellをはじめよう Powershell入門

Windows PowerShell を使ってExcel を操作する -セル操作編 vol.1

Excel の起動

### Excel の起動
$excel = New-Object -Com Excel.Application

# 可視化 (バッチファイルにするときは $Falseに)
$excel.Visible = $True

# アラートを無効に
$excel.DisplayAlerts = $False

可視化を True にすることで、これから流すコマンドの結果を1つ1つ目視確認できる。

シートの追加

### 新規シートを追加
$book = $excel.Workbooks.add()

# アクティブなシート(Sheet1) を取得
# ※ $sheet = $book.Sheets("Sheet1") でも可
$sheet = $book.ActiveSheet

# シート名を変更
$sheet.Name = "表紙"

既存ワークブックを開く場合は open() を使用する。

### AAA.xlsx を開く
$book = $excel.Workbooks.Open("C:\TEST\AAA.xlsx")

セルの編集

### A1セルに値を登録
$sheet.Cells.Item(1,1) = "報告書サンプル"

# A1セルを太字、サイズ30に
$sheet.Cells.Item(1,1).Font.Bold = $True
$sheet.Cells.Item(1,1).Font.Size = 30

# A2セルに作成日時を登録
$sheet.Cells.Item(2,1) = " 作成日:" + (Get-Date).toString()   

A1、A2 といった書き方もできる。

# A2のセルに値を設定
$sheet.Range("A2") = "200"

表の作成

# $tableRange = 登録した表の範囲
#   $sheet.Cells.Item($x1,$y1) ... 表の左上
#   $sheet.Cells.Item($x2,$y2) ... 表の右下
$tableRange = $sheet.Range($sheet.Cells.Item($x1,$y1),
               $sheet.Cells.Item($x2,$y2))
# 表の罫線を表示
$tableRange.Borders.LineStyle = $True

# 表の幅を自動調整
$tableRange.Columns.AutoFit() | Out-Null

# 表ヘッダ部分を太字、背景灰色(15) に (参考) https://www.sejuku.net/blog/32288
$sheet.Range("A1","C1").Font.Bold = $True
$sheet.Range("A1","C1").Interior.ColorIndex = 15   

グラフの作成

先程作成した表 (範囲 $tableRange) をグラフ化する。

### グラフを描画するための領域を作成
# $posX, $posY    ... 描画領域の左上座標
# $width, $height ... 描画領域の幅、高さ
$posX, $posY = 200, 10
$width, $height = 600, 400
$chart = $sheet.ChartObjects().Add($posX, $posY, $width, $height).Chart

# グラフを描画
$chart.SetSourceData($tableRange) | Out-Null

# 折れ線グラフに (参考: https://www.relief.jp/docs/excel-vba-xlchartype-list.html )
$chart.ChartType = 4 # -> xlLine

# タイトルを表示
$chart.HasTitle = $True
$chart.ChartTitle.Text = "アクセス数推移グラフ"   

保存、終了

### 保存、終了
$book.SaveAs("$workdir\報告書サンプル_2018-05.xlsx")
$excel.Quit()
$excel = $Null
[GC]::collect()   

上書きの場合は $book.Save() で良い。
最後2行はプロセス解放のために必要。

Emacs org-agenda他を運用して1年経ったのでまとめる

Table of Contents

  1. はじめに
  2. 設定内容 (init.el)
    1. agenda files 構成
    2. org-capture 構成
    3. その他
  3. 運用方法
    1. TODO items: タスクの登録
    2. org-agenda: アジェンダの表示
    3. org-capture: リマインドの登録
    4. org-clock: 工数計測
    5. org-clocktable: 工数表示
  4. 1年間運用した感想

はじめに

org-agenda や org-capture, org-clock などの自分なりの運用をまとめます。

org-agenda … (簡単に言うと) ファイル毎に散らばったTODOタスクを集約して、
管理してくれるorg-mode のタスク管理機能

org-capture … (簡単に言うと) org-mode のメモ取り機能。さっとメモを書ける。

org-clock … org-mode の計時機能


参考サイト

設定内容 (init.el)

agenda files 構成

↓ init.el (抜粋)

;; アジェンダ表示の対象ファイル
(setq org-agenda-files '(
             "c:/Users/AAA/org/aaa.org"
             "c:/Users/AAA/org/anken"
             "c:/Users/AAA/org/remind.org"
                         ))

org ディレクトリ構成は下記の通り

org/
 │  aaa.org
 │  remind.org
 │  knowledge.org
 │
 ├─anken
 │     AAA.org
 │     BBB.org
 │     CCC.org
 │     :
 │
 └─tech
       powershell.org
       lpic.org
       ccna.org
       :
ファイル名 用途
aaa.org 社内業務関係をここに書く。 **アジェンダ対象**
remind.org さっとメモを取る ( **org-capture** する)とき用。 **アジェンダ対象**
knowledge.org ちょっとした知見をメモする ( **org-capture** する)とき用。
anken フォルダ 案件ごとにorgファイルを管理。 **アジェンダ対象**
tech フォルダ 技術情報用。

org-capture 構成

↓ init.el (抜粋)

(setq org-capture-templates
      '(("t" "Todo" entry (file+headline "c:/Users/AAA/org/remind.org" "■Capture")
     "* REMIND %? (wrote on %U)")
    ("k" "Knowledge" entry (file+headline "c:/Users/AAA/org/knowledge.org" "TOP")
     "* %?\n  # Wrote on %U")

remind.org には REMIND item が溜まっていく。

knowledge.org には (ちょっとした)知識 が溜まっていく。

その他

その他雑多な設定。読み飛ばしてOK。

;; ##### org-agenda
;; C-ca で org-agenda
(define-key global-map "\C-ca" 'org-agenda)

;; アジェンダ表示で下線を用いる
(add-hook 'org-agenda-mode-hook '(lambda () (hl-line-mode 1)))
(setq hl-line-face 'underline)

;; 標準の祝日を利用しない
(setq calendar-holidays nil)

;; TODO状態
(setq org-todo-keywords
      '((sequence "TODO(t)" "WAIT(w)" "REMIND(r)" "|" "DONE(d)" "SOMEDAY(s)")))

;; DONEの時刻を記録
(setq org-log-done 'time)

;; タグリスト
(setq org-tag-alist '(("meeting" . ?m) ("office" . ?o) ("document" . ?d) ("kitting" . ?k) ("study" . ?s) ("travel" . ?t) ))


;; ###### org-capture
;; C-cc で org-capture
(global-set-key "\C-cc" 'org-capture)


;; ##### org-clock
;; clockログを隠す
(setq org-clock-into-drawer t)

;; clocktable の体裁を整える
(defun my-org-clocktable-indent-string (level)
  (if (= level 1) ""
    (let ((str " "))
      (while (> level 2)
        (setq level (1- level)
              str (concat str "--")))
      (concat str "-> "))))

(advice-add 'org-clocktable-indent-string :override #'my-org-clocktable-indent-string)

運用方法

TODO items: タスクの登録

アジェンダ対象の org の、各見出し(タスク) にTODO ステータスを付ける。
(見出し内で C-c C-t でステータス登録)

筆者は下記ステータス を init.elで登録。

ステータス 説明
TODO 未完了タスク。そのままの意味
WAIT 未完了タスク。待ち状態
REMIND 未完了タスク。リマインド (org-capture 用)
DONE 完了タスク。そのままの意味
SOMEDAY 完了タスク。いつか手を付ける

また、見出し上で C-c C-c を実行することでタスクにタグを付けられる。

筆者は下記タグを init.el で登録。後述の工数表示でタグ毎に掛けた時間をまとめて報告書にした。

タグ 用途
meeting 会議
document 設計書などの資料作成
kitting 機器構築
study 学習、調査
travel 出張
office 事務作業

org-agenda: アジェンダの表示

出社して Emacs を起動後に、 C-c a n で Agenda 表示 (TODO リストと1週間の予定)。
アジェンダ対象ファイルからTODO キーワードのタスクを抽出してリストアップしてくれる。

Agenda上で主に使用するキーは下記の通り。

キー 説明
n,p 項目の上下移動
Enter 選択タスクへバッファ移動
t 選択タスクのTODO ステータス変更
I 選択タスクの計時開始
O 選択タスクの計時終了
C-c C-s 選択タスクの予定日登録
C-c C-d 選択タスクの締切日登録
q Agenda を閉じる

定期的に org-agenda を開いて TODO 状況を把握する。

org-capture: リマインドの登録

「ちょっとこれやっといて」的なことを言われたときに使う。
案件の本筋でない支援や、社内業務など細々した(忘れそうな)タスクを org-capture でメモしていく。

C-c c で org-capture 起動。下記画面が表示されるので "t" を選択。

タスク内容を書いて C-c C-c で登録完了。
org-agenda を開くと 登録されていることが確認できる。

org-clock: 工数計測

タスク消化に掛けた時間を計測する。

▼タスクの計測開始

  • Agenda 上でタスクを選択して I
  • or タスクの見出し内で C-c C-x C-i

LOGBOOK 内に計測開始時刻が記録される。

▼タスクの計測終了

  • Agenda 上で O
  • or 任意の orgバッファで C-c C-x C-o
  • or タスクの TODO ステータスを DONE にする

LOGBOOK 内に終了時刻、経過時間が記録される。

org-clocktable: 工数表示

任意の orgファイルに下記のような内容を書く。

#+BEGIN: clocktable :maxlevel 2 :scope agenda :tstart "2018-01-01" :tend "2018-01-31"
#+END:

記述した #+BEGIN: ... 上で C-c C-c を実行すると対象期間の計測結果が表示される。

↑は 2018年1月分の計測結果を表示している。

他にも下記のようなパラメータがある。組合せて所望の計測結果を表示させる。
(詳細: https://orgmode.org/manual/The-clock-table.html#The-clock-table )

パラメータ 説明
:block thisyear 今年の計測分
:block lastweek 先週の計測分
:tags "meeting" meeting タグが付いたタスクの計測分

1年間運用した感想

★やっぱり org-mode、org-agenda は最高

複数案件を同時にこなすには org-agenda が欠かせなくなりました。
これからも org-agenda にはお世話になると思います。


org-capture も便利

これを使う前は とっさのメモを、とりあえず scratch バッファに書いて ・・・
といった対応を取っていました。

org-capture を使うことで、無駄なくリマインド登録・知識メモができるようになりました。


org-clock は下のような報告書を作成するときには役に立ちましたが、
半年ほどしか続きませんでした。

業務報告のためだけではリターンが少なかったです。

もう少し有益な分析ができるようにタグを見直したほうが良いかもしれません。
(例えばプロジェクトのフェーズ毎にタグ分けする、など)


統計

案件フォルダの orgファイル数 28個
案件フォルダの orgファイルサイズ合計 393KB
DONE(完了) にしたタスク数 700個
SOMEDAY(いつかやる) にしたタスク数 43個
org-capture でREMIND を取った数 345個
org-clock で測った時間 26日と20時間59分

【Emacs】ido-mode 導入メモ

ido-mode を使い始めたので、導入・操作メモを残していく。
ファイルオープン、バッファ移動の補完周りがめちゃめちゃ快適になった(もっと早く入れておけばよかった)…

導入

Emacs 標準に入っているため M-x ido-modeido-mode が開始される。
起動時に ido-mode が有効になるように InitFile に書いておく。

(ido-mode t)

これで終わり … だが、補完を見やすくするために ido-vertical-mode を入れておく。

  1. M-x package-install ido-vertical-mode を実行
  2. InitFile に下記追記

    (require 'ido-vertical-mode)
    (ido-vertical-mode 1)
    (setq ido-vertical-define-keys 'C-n-and-C-p-only)
    

(入れてない人向け) MELPA-stableを追加

今回 ido-vertical-mode を入れるために パッケージ管理にMELPA-stableを追加した。

  1. 下記を InitFileに書く。

    (add-to-list 'package-archives
           '("melpa-stable" . "https://stable.melpa.org/packages/") t)
    
  2. emacs の再起動後、 M-x package-list-packages を実行。

使い方

バッファ移動

▼ バッファ移動 C-x b の実行結果

そのまま Enter で"→" の部分のバッファに移動する。
C-n , C-p (上下矢印キー) で候補の移動。

▼文字入力後 Enter でマッチ(部分一致) するバッファに移動。

ファイル検索

▼ ファイル検索 C-x C-f の実行結果

そのまま Enter で"→" の部分のファイルオープン もしくはディレクトリ移動。
C-n , C-p (上下矢印キー) で候補の移動。

▼文字入力後 Enter でマッチ(部分一致) するファイルのオープン もしくはディレクトリの移動。

Python からFitbit のデータを取得する

Table of Contents

  1. はじめに
  2. 準備
    1. client_id, client_secret の取得
    2. refresh_token, access_token の取得
  3. データの取得

はじめに

主にランニング記録用に、去年の9月にFitbit charge2 (official)を購入した。

いわゆる活動量計・スマートウォッチで、歩数や心拍数、ランニングなどの記録を取ってくれる。 スマホと連動して、GPSで取得したランニングコースなども見ることができる。 各記録はスマホアプリ、Webブラウザからも確認可能。

(おすすめのバンドは こちら(Amazon) 。取り外しがとても楽。)


このFitbit、開発者向けの環境が充実している。 Fitbit API が公開されていて、最新機種のFitbit ionic では、専用のSDKまで用意されている。

Fitbit studio

今回は以下の python-fitbit を使って、これまで記録した歩数や心拍数を取得してみる。

環境

  • OS : Windows10
  • Python : 3.6.4

準備

準備の流れは以下の通り。 解説している記事は結構あるので詳細は割愛します。

  1. Fitbitのページで、 client_id, client_secret を発行する。
  2. fitbit-python を用いて refresh_token, access_token を取得する。

client_id, client_secret の取得

画面参考: Connect yout app to Fitbit

Fitbit にログインした状態で、下記にアクセスする。

https://dev.fitbit.com/apps/new

Register an application フォームに記入する。下記パラメータ以外は適当でOK。

  • OAuth 2.0 Application Type: Personal
  • Callback URL: ttp://127.0.0.1:8080/
  • Default Access Type: Read-Only

出てきたOAuth2.0 Client IDと Client Secret をメモする。

refresh_token, access_token の取得

事前にpython-fitbit をDLしておく。

Requirements を参考に以下を実行。

  1. pip install python-dateutil
  2. pip install requests-oauthlib
  3. python-fitbit-masterディレクトリ下で pip install -r .\requirements\base.txt

gather_keys_oauth2.py の実行に必要なパッケージをインストール。

  1. pip install fitbit
  2. pip install cherrypy

gather_keys_oauth2.py を実行する。

  • python gather_keys_oauth2.py [client_id] [client_secret]

出てきた access_token, refresh_token をメモする。

データの取得

今回は 1日の活動の概要を取得する activities メソッドを使用する。

import fitbit
import datetime

# CLIENT_ID, CLIENT_SECRET
CLIENT_ID = "xxx"
CLIENT_SECRET = "xxx"

# ACCESS TOKEN, REFRESH TOKEN
ACCESS_TOKEN = "xxx"
REFRESH_TOKEN = "xxx"

# get activities summary in 2017/11/20
client = fitbit.Fitbit(CLIENT_ID, CLIENT_SECRET, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN)
date = datetime.datetime.strptime("2017-11-20", "%Y-%m-%d")
print(client.activities(date=date))

cleient.activities(date=date) の返り値は下記のようなmap オブジェクト。 ちなみに、データ取得のためのリクエストには制限がある(1時間に150)。

{'activities': [],
 'goals': {'activeMinutes': 30,
           'caloriesOut': 2542,
           'distance': 5,
           'floors': 10,
           'steps': 10000},
 'summary': {'activeScore': -1,
             'activityCalories': 974,
             'caloriesBMR': 1467,
             'caloriesOut': 2353,
             'distances': [{'activity': 'total', 'distance': 6.51},
                           {'activity': 'tracker', 'distance': 6.51},
                           {'activity': 'loggedActivities', 'distance': 0},
                           {'activity': 'veryActive', 'distance': 4.38},
                           {'activity': 'moderatelyActive', 'distance': 0.3},
                           {'activity': 'lightlyActive', 'distance': 1.82},
                           {'activity': 'sedentaryActive', 'distance': 0}],
             'elevation': 270,
             'fairlyActiveMinutes': 8,
             'floors': 27,
             'heartRateZones': [{'caloriesOut': 857.86064, 'max': 98, 'min': 30, 'minutes': 602, 'name': '範囲外'},
                                {'caloriesOut': 349.27984, 'max': 137, 'min': 98, 'minutes': 64, 'name': '脂肪燃焼'},
                                {'caloriesOut': 332.46304, 'max': 166, 'min': 137, 'minutes': 34, 'name': '有酸素運動'},
                                {'caloriesOut': 62.57888, 'max': 220, 'min': 166, 'minutes': 6, 'name': 'ピーク'}],
             'lightlyActiveMinutes': 101,
             'marginalCalories': 684,
             'restingHeartRate': 67,
             'sedentaryMinutes': 1271,
             'steps': 13862,
             'veryActiveMinutes': 60
 }
}

これを数カ月分とって、 summary > restingHeartRate (安静時心拍数) のグラフをプロットしてみる。

冬は心拍数が高くなるらしい。よかった。

org-mode → Markdown → はてなブログ投稿の実験 まとめ

Table of Contents

  1. Org 8.x のMarkdown がうまくいかない
  2. Org 9.x に上げると殆ど解決した
  3. 残った問題
    1. ソースコードが適用されていない (+ハイライトしたい)
    2. 痒いところに手が届かないところは直Markdownで

Org 8.x のMarkdown がうまくいかない

M-x org-md-export-as-markdown (C-c e m M) でOrg 文章をMarkdown形式に変換できる。 はてなブログMarkdown 記法に対応しているので、これをそのまま貼り付けるだけで記事が投稿できる。

下は Org 8.x でその出力テストを行ったもの。

スケジュールやTODOリストなど、後半部分は記事の構成要素にならなさそうなので、言及しない。 他、記事を書くにあたって問題になりそうな不備を洗い出してみた。

  • (おそらく)空白行を挟まずにリストを作成すると、それをリストと認識しない
  • 表の体裁が崩れている (列グループ化が適用されていない)
  • 内部リンクが機能していない
  • 脚注のリンクが機能していない

Org 9.x に上げると殆ど解決した

どうしてこうなるのか・・・を考える前に Org-mode のバージョンを上げたら大体は解決しました。

ぱっと見たところ不備は残りこれくらい。

  • 表の列グループ化が適用されていない → 使う機会が少なそうなので、今回はスルー
  • new! ソースコードが適用されていない

残った問題

ソースコードが適用されていない (+ハイライトしたい)

リファレンスのタグ付けの部分が悪さをしていたらしい。 以下は正常に出力された。

' #+BEGIN_SRC emacs-lisp -n
' (save-excursion
'    (goto-char (point-min)))
' #+END_SRC

↑org ↓出力

1  (save-excursion
2     (goto-char (point-min)))

欲を言えばシンタックスハイライトしたい。 そこで、コードの部分をMarkdown記法で埋め込む方法をとってみる。

' #+BEGIN_EXPORT html
' ```python
' def hello():
'     str = "Hello World"
'     print(str)
' 
' # Hello!
' hello()
' ```
' #+END_EXPORT

↑org ↓出力

def hello():
    str = "Hello World"
    print(str)

# Hello!
hello()

#+BEGIN_EXPORT html ... #+END_EXPORT で囲まれた部分はMarkdownエクスポートの際、 そのまま出力される。このブロックはOrg-mode のEasy Template機能で <h [TAB] で呼び出せる。

```python ... ```Markdown記法。ソースコードの言語名を指定することで、はてなブログが 対応している言語はシンタックスハイライトしてくれる。

痒いところに手が届かないところは直Markdown

画像やURLリンク(埋め込み形式)も Markdown直打ちで対応したほうが見栄えの調節が便利だったりする。

' #+BEGIN_EXPORT html
' <img src="https://orgmode.org/img/main.jpg" width=200>
'  
' [https://www.google.co.jp/:embed]
' #+END_EXPORT

↑org ↓出力