日記/2019-2-27より前の5日分

2019-2-26

Googleカレンダーにプロ野球の日程をインポートするためスクレイピング

 

calendar.png
 
 Googleカレンダーには、「関心のあるカレンダーを探す」から追加できるように、日本のプロ野球の日程があらかじめ用意されている(参考)。
 が、球団名が英語表記だったりしてどうも気に入らない。
 そこで、日本野球機構の試合日程のページをスクレイピングして、試合日程の情報をゲットし、これをGoogleカレンダーに表示してみた。
 スクレイピングするスクリプトは勉強中のPythonで書いてみた。習作ということで。

 #!/usr/bin/python3
 #coding: utf-8
 
 #scrapingnpb.py
 
 import sys
 import re
 import datetime
 import urllib.request
 import pprint
 from bs4 import BeautifulSoup
 
 data = {}
 
 head = "Subject, Start Date, Start Time, End Date, End Time, Description, Location"
 print(head)
 
 month_days = {'03':'31', '04':'30', '05':'31', '06':'30', '07':'31', '08':'31', '09':'30', '10':'30'}
 
 for month in month_days.keys():
     data.setdefault(month, {})
     for day in range(int(month_days[month])):
         data[month].setdefault(day + 1, {})
         data[month][day + 1].setdefault('date', '2019/' + month + "/" + ('0' + str(day + 1))[-2:])
         data[month][day + 1].setdefault('id_date', 'date' + month + ('0' + str(day + 1))[-2:])
 
 for month in month_days.keys():
     html = urllib.request.urlopen("http://npb.jp/games/2019/schedule_" + month + "_detail.html")
     soup = BeautifulSoup(html, features="lxml")
     for day in data[month].keys():
         for n in range(6):
             data[month][day].setdefault(n, {})
         num = 0
         for tr in soup.find_all("tr", attrs={"id": data[month][day]['id_date']}):
             div = tr.select_one("td>div.place")
             if div:
                 p = re.sub(r'\s+', '', div.text)
                 data[month][day][num].setdefault('place', p)
             div = tr.select_one("td>div.time")
             if div:
                 data[month][day][num].setdefault('time', div.text)
             div = tr.select_one("td>div.team1")
             if div:
                 data[month][day][num].setdefault('team1', div.text)
             div = tr.select_one("td>div.team2")
             if div:
                 data[month][day][num].setdefault('team2', div.text)
             div = tr.select_one("td>div.commentLong")
             if div:
                 data[month][day][num].setdefault('comment', div.text)
             num += 1
 
 for month in month_days.keys():
     for day in data[month].keys():
         for num in range(6):
             if data[month][day][num].get('time'):
                 m = re.match(r'(\d+):(\d+)', data[month][day][num]['time'])
                 if m:
                     sthr = m.group(1)
                     stmn = m.group(2)
                     start = datetime.datetime(2019, int(month), int(day), int(sthr), int(stmn), 0)
                     delta = datetime.timedelta(hours=4)
                     end = start + delta
                     sttm = start.strftime("%H:%M:%S")
                     entm = end.strftime("%H:%M:%S")
                     summary = ''
                     if data[month][day][num].get('comment'):
                         summary = data[month][day][num]['comment']
                     else:
                         summary = data[month][day][num]['team1'] + "対" + data[month][day][num]['team2']
                     #head = "Subject, Start Date, Start Time, End Date, End Time, Description, Location"
                     if len(sys.argv) > 1:
                         m = re.search(sys.argv[1], summary)
                         if m:
                             print(f"{summary}, {data[month][day]['date']}, {sttm}, {data[month][day]['date']}, {entm}, {summary}, {data[month][day][num]['place']}")
                     else:
                         print(f"{summary}, {data[month][day]['date']}, {sttm}, {data[month][day]['date']}, {entm}, {summary}, {data[month][day][num]['place']}")

 使い方は「./scrapingnpb.py」、もしくは「./scrapingnpb.py 阪神」という風に球団名を与える。何も与えないとすべての日程が、球団名を与えるとその球団のみの日程が出力される。
 出力結果をcsvファイルとして保存し、GoogleカレンダーにインポートすればOK。


2018-10-14

ゼファー魂・続続続続続続続

 

 本日(2018/10/14)、東京競馬場の3R、芝1600mの牝馬限定の2歳新馬戦に、現在JRAの現役馬に2頭だけいる母父ヤマニンゼファーのうちの一頭、ハッピービギニングが出走した。
 掲示されている場所が、オッズ表示板を正面に見て左から二番目だったということは、どうやら掲示順の順番取りは、いつものようにトップではなく二番手だったようだが、パドックにはいつもの「ゼファー魂」の勇姿があった。

zepher.png

 結局ハッピービギニングは13着。

 2018/10/14現在、母父ヤマニンゼファー産駒は、JRAの現役馬では以下の2歳馬2頭だけ。
 

馬名性齢調教師名着度数種牡馬名母名母の父名馬主名生産者名
ハッピービギニング牝2(美)南田美知0-0-0-1パドトロワイケタイトルヤマニンゼファー鹽田久義森俊雄
シナモンシュガー牝2(美)加藤和宏0-0-0-1ジョーカプチーノスピードエアロヤマニンゼファースピードファームスピードファーム
 

関連ページ


2018-7-7

植村直己の言葉

 

 検索しても引っかかってこないので、植村直己の言葉で、私が好きなヤツを以下に引用する。
 「北極点グリーンランド単独行」収録のグリーンランド縦断の手記、最終日の一節から。

 私は何かを新しく発見したわけでもない。何かを新しくわれわれの社会へ持ち帰るわけでもない。私の行為は、私の身体に何らかの痕跡を残し、私の心に辛かった、またときに、さわやかだった思い出を残すだけだ。私のやったことが、なにがしか意義のある行為と呼べるものであったとしても、私は、相も変わらぬ私にすぎず、勝手気ままな夢をいだき、夢の実現にむかって前進するほか能のない人間なのだ。

 この後、植村は遭難死して、ある意味で、勝手気ままな夢のような人生を全うするわけだが、そんなことは知るよしもない、ティーンエイジャーだった私は、この言葉から自身の未来を信じる勇気をもらったのだった。


2018-4-4

赤外線リモコンデータの変換

 

 こちらで紹介されている格安スマートリモコンを作ってみた。半田付けに手こずったが、久々の電子工作はとても楽しかった。
 肝心の使い勝手だが、なぜか照明はダメだったが、テレビやエアコンはうまく学習、制御することができた。
 この学習がなかなか面倒。コンソールから学習のコマンドを実行後、格安スマートリモコンに向けて、学習したいリモコンの登録したいボタンをプッシュ、という作業を行うわけだが、例えばテレビのリモコンを登録しようとすると、ボタンの数だけ、何十回もこの作業を繰り返すことになる。
 どうにか一括して登録作業を行うことができないものかと、ネットを検索していると、以下のビットトレードワンのサイトで、自社の学習リモコンADRSIR向けとして、22社、265の機器のリモコンのコードが記されたCSVファイルが公開されているのを見つけた。

 ラッキー!これを登録すればいいじゃん!と喜んだのもつかの間、CSVファイルの内容は見たことがないものだった。

 同じ東芝のテレビのリモコンのコードで、両者を比較してみる。
 格安スマートリモコンで用いているpigpioのサイトで公開されている、リモコンコードの学習・再生プログラムirrp.pyで保存されるのは以下のようなもの。

"tv:on": [8950, 4440, 585, 529, 585, 529, 585, 529, 585, 529, 585, 529, 585, 529, 585, 1636, 585, 529, 585, 1636, 585, 1636, 585, 1636, 585, 1636, 585, 1636, 585, 1636, 585, 529, 585, 1636, 585, 529, 585, 1636, 585, 529, 585, 529, 585, 1636, 585, 529, 585, 529, 585, 529, 585, 1636, 585, 529, 585, 1636, 585, 1636, 585, 529, 705, 1636, 585, 1636, 585, 1636, 585, 39828, 8950, 2210, 585, 95511, 8950, 2210, 585],

 これに対して、ビットトレードワンで公開されているCSVファイルの内容は以下のようなもの。

"東芝","デジタルテレビ1","電源","5601A900180015001800140018001400190013001900140019001400170040001700150018003F0019003E0018003E0019003F0019003E00170040001800140019003E001800150018003F00180014001800140019003F0018001400170016001700150018003F001800140018003F0018003F001800140019003F0018003F0018003E0019004F03"

 なにこれ!全然違う!

 上記CSVファイルと同じビットトレードワンのサイトで公開されている、ADRSIR用のソフトウェアをいじくっていて、どうやら両者は以下のようなものであることに気づいた。

irrp.pyは、ONとOFFの期間の時間(μs)
「"tv:on": [8950, 4440, 585, 529,...」の場合、最初の「8950」は「ONが8950μS(約9ms)」、次の「4440」は「OFFが4440μS(約4.4ms)」という意味。これは、東芝のテレビが用いている赤外線リモコンのフォーマットであるNEC方式のリーダーコード、ONが9ms、OFFが4.5msにほぼ合致する。
CSVファイルは、ONとOFFの期間のパルスの数
「5601 A900 1800 1500 ...」の場合、最初の「5601」は「0156h」、十進数で「342」で「ONが342」、次の「A900」は「00A9h」、十進数で「169」で「OFFが169」という意味。多くのリモコンの赤外線信号は38kHzで変調されているため、1つのパルスの時間は1/38000=0.000026315秒、約26μsになる。これに最初の値「342」をかけると、342x26=8892、となり、これは、irrp.pyの例の最初の値「8950」とほぼ同じになる。同様に、次の値「169」に26をかけると、169x26=4394、となり、これもirrp.pyの例の二番目の値「4440」とほぼ同じ。
 どうやら、irrp.py=時間、CSVファイル=パルス数、で間違いないようだ。

 そこで、ビットワントレードのADRSIR用ソフトを元に、CSVファイルのデータ(パルス数)を、irrp.py用のデータ(時間)に変換するプログラムを作ってみた。と言っても、バイトオーダーを変えて、26をかけているだけ。
 

#!/usr/bin/python3
#coding: utf-8

#convIrData.py

import sys
import json

def conv_command(command, block):
    str_tmp = ""
    int_tmp = []
    for i in range(int(len(block)/2)):
        str_tmp = block[i*2] + block[i*2+1]
        int_tmp.append( int(str_tmp, 16))

    list = []
    ir_data = {}
    data_numH = 0;
    data_numL = 0;
    for i in range(int(len(int_tmp)/4)):
         data_numH = (int_tmp[i*4+1] * 256 + int_tmp[i*4+0]) * 26
         data_numL = (int_tmp[i*4+3] * 256 + int_tmp[i*4+2]) * 26
         list.append(data_numH)
         list.append(data_numL)

    ir_data[command] = list

    return ir_data

    
while True:
    argvc = sys.argv
    argc = len(argvc)
           
    if  (argc  == 2):
        filename = sys.argv[1]
        f = open(filename, 'r', encoding='utf-8')
        ir_data = {}
        for line in f:
            [command, block] = line.replace("\"","").split(",")
            ir_data.update(conv_command(command, block))

        print(json.dumps(ir_data,sort_keys=True).replace("],","],\n"))
        break   

    if  (argc  == 3):
        command = sys.argv[1]
        block = sys.argv[2]

        ir_data = conv_command(command, block)
        print(json.dumps(ir_data))
        break   

    print("Usage:")
    print(" python3 convIrData.py filename")
    print(" python3 convIrData.py command \"5B0018002E001800...\"")
    break

 使い方は「./convIrData.py filename」とファイル名を与える。ファイルの中身は以下のようにする。

"tv:on","5B0018002E001800..." 
"tv:off","5C0017002F001700..." 

 もしくは「./convIrData.py tv:on 5B0018002E001800...」という風に、コマンド名とCSVファイル記載のバイト列を与える。

 変換後のデータで、テレビやエアコンの制御ができることを確認した。
 東芝のテレビのデータの一括登録に成功し、格安スマートリモコンが快適に使えるようになった。
 エアコンについては、残念ながらCSVファイルに使い勝手のいいコマンドがないため、登録していない。


 

2018-3-16

点在する「京都買います」

 

 本の雑誌418号2018年4月号掲載の「坪内祐三の読書日記」のサブタイトルは「『怪奇大作戦』の第二十五話「京都買います」がDVD化されました」というもの。2018年1月18日分の記載は以下の通り。

一月十八日(木) 今場所三度目の国技館(メンバーは私、中野翠さん南伸坊さん泉麻人さん――ってシブいでしょ)。渋谷二軒、飯田橋一軒、本屋を覗くが、ディアゴスティーニのDVDコレクションの『円谷プロ特撮ドラマ』シリーズは見当たらない(売り切れたのではなく扱っていないのだろう)。その最新巻(五十一号)を先週末、東京堂書店で見つけ、その号を購入して中野さんにお見せしたかったのだ。何故ならその号には中野さんの大好きな(亀和田武さんも大好きな――たぶん泉麻人さんも大好きな)「京都買います」(『怪奇大作戦』の第二十五話)が収録されているからだ。一時半、国技館に入ると既に南さんがいらっしゃっている。

 その号(2018年1月16日発行)がこれ。

No Item.

 表紙でフィーチャーされているのはボーンフリーだが、左下に確かに「怪奇大作戦」の記載がある。目次によると、DVD収録作は以下のようなもの。

  • 怪奇大作戦
    • 第23話「呪いの壺」
    • 第25話「京都買います」
    • 第26話「ゆきおんな」
  • 恐竜探険隊ボーンフリー
    • 第1話「行け! ボーンフリー号」
    • 第2話「恐怖の肉食恐竜アロサウルス」
  • トリプルファイター
    • 第3話「殺人マシンX14号」

 ボーンフリーは2話なのに、怪奇大作戦は3話収録されており、実際にフィーチャーされているのは怪奇大作戦の方なのではないか。
 なお、怪奇大作戦の第24話「狂鬼人間」は欠番(元脳科学者で、狂人に家族を殺された過去を持つ狂わせ屋が作った脳波変調機によって、一時的に狂人と化して殺人を犯すことで罪から逃れる、という犯罪を、SRIの牧が自ら囮となって暴こうとするが、狂わせ屋に見破られて……という話。ウルトラセブンのスペル星人もそうだが、円谷プロは抗議を受けるとすぐ欠番にしちゃう嫌いがある)。

 私は十年以上前に以下のDVDを買いました。

No Item.

 こちらには22、23、25、26話が収録されている。24話はやはり欠番だが、「京都買います」はもちろん入っている。
 現在このDVDには、新品の場合ろくでもないプレミア価格がついているようなので、新たなファンの開拓という意味で、今回デアゴスティーニから再販されたのはとてもいいことだと思う。

 私ももちろん、坪内祐三や中野翠や亀和田武や泉麻人に負けず劣らず「京都買います」は大好きなのだが(怪奇大作戦の中での最高作というだけでなく、実相寺昭雄の最高作ではないかと思う)、以前、他にも、なかなかの「京都買います」ファンを見つけていた。

 多くの地方新聞社と共同通信が運営しているニュースサイト「47news」の文化面の連載コラム「洞口依子ののら猫万華鏡」の「京都大作戦」の回で、洞口は「京都買います」への愛、牧史郎役の岸田森への愛を熱く語っている。
 太秦での撮影の空き時間、洞口は「京都買います」のラストシーンのロケ地である祇王寺がすぐ近くであることに気づく(下記引用部では、文字コードの関係で連八分音符を八分音符に変更し、改行を適宜削除した)。

 「……今だ。今しかない!」
 のろのろとのら猫がすり抜けるように撮影所の門を出て、私は大通りに駆け抜けてゆくと急いでタクシーを拾って飛び乗った。
 脳内には『怪奇大作戦』のあのテーマが鳴り響く。
 「チャーラーラー♪ チャララチャラララチャラチャッチャー♪ ビヨンビヨンビヨンビヨーン♪」

(中略)

 言葉が出ない衝撃だった。
 寺の様子はあの頃のままだったのだ。
 細かいディテールは確かに多少変わっている。40年以上も前に撮影したのだからそりゃそうだ。しかし、この祇王寺の庭は、あの仏像と化した尼僧がどこかにひっそりと眠っているようにも感じられた。
 まさにわたしが立っている場所こそ牧史郎が茫然と立ちつくしていた辺りでもあった。
 柔らかな夕暮れの陽射しがうっすらと、寺を囲む樹々から漏れてくる。
 私はしばらくそこに立ち尽くしてぼんやり庭を眺めていた。

(中略)

 ロケ地なんていうものは実際行くと大抵がっかりするものだが、今回は違った。思い切って来てみて本当によかった。

 
 数年前にこのコラムを読んで以来、私もぜひ祇王寺へ行きたいと思っているのだが、まだその夢は果たせていない。
 



これより前の5日分