読者です 読者をやめる 読者になる 読者になる

アルデバラン食20170109

この日の新居浜の天気は、9日夜が曇り、10日に日付が変わった頃から晴れの予報でした。 去年の11月16日のアルデバラン食と同じような天気でしたので、 雲の切れ間からタイミングよく撮れるのを願うような感じでした。

ヒアデスの掩蔽もあったので、20時頃から準備をしていましたが、 全く月が見えないほどの雲でヒアデスの方は早々に諦めました。 23時を過ぎて、雲の切れ間が数時間前より多くなってきたような気がしました。

そして、アルデバランが月の後方に暗部から隠れていく映像が撮れました。 撮影時の書き出しデータを確かめると、潜入は23時53分48秒くらいでした。

潜入を撮り終えたあたりから、再び雲が厚くなってきて、 1時間ほど月が見えず…

その後、出現の時間になりましたが、無情にも雲が晴れることはなく、 出現の2,3分前と後に月が見えただけでした。

出現のおそらく2,3分前 f:id:uitspitss:20170110034022p:plain

出現のおそらく2,3分後 f:id:uitspitss:20170110034113p:plain

今年度の天体撮影はこれで終わりですかね。

しぶんぎ座流星群2017

1月3日の夜、愛媛の新居浜は晴れていたのでZWOのASI120MC-Sで撮ってきました。

下の動画は、1月3日23時頃から4日5時頃までのタイムラプス動画です。

今年の活動はそれほど活発ではなく、動画を見てもあまり流星が見えないので、下にいくつかピックアップしていきます。

まずは、この画像。右下に写っている薄い線が流星の飛跡です。 撮影した画像にはあまり明るく写りませんでしたが、流星の飛跡が見え始めてから1,2秒ほど目で追いかけられたくらいには経路の長い流星でした。 撮影をし始めて、30分くらいでこの流星が見られて、寒いこともあって、すごく帰りたくなりました。

f:id:uitspitss:20170108224337j:plain

2つ目は、撮影していた時間内では、一番明るく見えていたであろう流星(画像中央右)。 撮影し始めから4時間以上経過していた頃に流れていたようです。もう寒くて、音楽を聴きながら、下を向いていることも多い時間帯だったので見れなかったです。 かなり広角な画角なので、あまり長経路に見えませんが、画像中央の北斗七星と比べると経路の長さが分かるかと思います。

f:id:uitspitss:20170108224612p:plain

3つ目は、散在の流星だとは思いますが、かなり明るく流れていた流星(画像左下)です。 これはラッキーなことに見てました。

f:id:uitspitss:20170108225821p:plain

と、そんなしぶんぎ座流星群2017でした。

ASI120MC-S(ASI120MC)のCCTV LENSはおまけな感じなレンズでしたけど、おもしろく使えました。 それから、今年度はASI120MC-Sで本来の目的であるアイピースカメラとしてもいろいろ撮ることができたので、また記事を書きたいと思います。

サックスが入っているポップな曲

あけましておめでとうございます。

私は音楽のジャンルに詳しいわけでないので、 単にサックスが入っているけど、Jazzとは違うジャンルの曲ということで…

ここ1年くらい、サックスが入っている曲は自分の感性にマッチすることが多かったので、 以下にそんな曲をまとめました。

Run Away With Me - Carly Rae Jepsen

曲の始めにサックスの音がリードしていく曲。 ちょっとダンスな曲調の中にサックスの音がいいアクセントで入っている感じが好きです。

Adrift - Vök

アイスランド出身のVök。 ここ1年ほど、KEXPのYoutubeチャンネルから良い曲を見つけることが多く、VökもこのKEXPで初めて知りました。 Vök - Wikipediaを見てみると、 サックスを演奏している Andri Már についてSaxophonistと書かれているから、本業がサックスなんでしょうか。

こちらは、「Run Away With Me」とはまた違って、サックスのメロディが前面に出ている感じがします。 そして、このKEXPの動画、サックスを演奏している姿が特にかっこいいです。

あと、アイスランドbjörkやÓlafur Arnaldsなどいい曲を作る人達が多いですね。

Shaver - Porches

残念ながら、公式からはサックスが入っていないバージョン(water version)しかyoutubeに出されていなかったです…

サックスが入っているバージョン(waterなしバージョン)はbandcampなどで販売されているみたいです。 私はGoogle Play Musicで聴きました。 ともかく、サックスが入っている方を聴いた感想は、途中でサックスのソロが入ってきて、 そのあとにそこまでメロディを作っていた音が締めくくるという感じです。 Porchesは他の曲もとても聴きやすくて良いです。

2日遅れのメリークリスマス!

メリークリスマス!

f:id:uitspitss:20161227003004g:plain

  • AgIC Circuit Marker
  • Digispark
  • Adafruit LED Sequins
  • mt masking tapes

そして、工作過程の画像↓

電気回路を描く f:id:uitspitss:20161227003445p:plain f:id:uitspitss:20161227003530p:plain

電池とスイッチを付ける f:id:uitspitss:20161227003543p:plain

LEDを付ける f:id:uitspitss:20161227003624p:plain

飾り付けをする f:id:uitspitss:20161227003736p:plain

5年後の自分へ

はてなブログ5周年ありがとうキャンペーンお題第2弾「5年後の自分へ」

http://blog.hatena.ne.jp/-/campaign/hatenablog-5th-anniversary

はてなブログとはズッ友だよ!(5周年おめでとうございます)

続きを読む

tweepy(もしくはrequests-oauthlib)とsqlite3でフォロー状況を見る

だいぶ前に、遊びで使っているtwitterアカウントでリフォローをしようとしたときに、 フォロー制限のためにリフォローができなかった。 ということで、python用のtwitterライブラリtweepyを使って、 sqlite3のデータベースにフォロー状況を書き出すものを作った。 個人的にはsqlite3などのRDBの勉強としての意味合いもあった。

環境

  • python - 3.5.2
  • tweepy - 3.5.0
  • sqlite3

tweepyを使う準備

tweepyを介して、twitterAPIにアクセスするには、

  • consumer keyconsumer secret
  • access tokenaccess secret

が必要になるので、https://apps.twitter.com/でアプリケーション登録をして、トークン等を準備する。

friendsとfollowersを取得

大抵のWebAPIにはアクセス制限が付きものなので、まずはそのあたりを調べた。 なお、以下のサイトを参考にした。

api.friends_idsapi.followers_idsは、それぞれ5000ids/回を取得でき、15回/15分のリミットなので、 フォロー数が1万を超えていても安心という数を捌ける。

以下のコードで、自アカウントがフォローしているfriends、自アカウントをフォローしているfollowersを取得できる。

import tweepy

CONSUMER_KEY = "CONSUMER_KEY"
CONSUMER_SECRET = "CONSUMER_SECRET"
ACCESS_TOKEN = "ACCESS_TOKEN"
ACCESS_SECRET = "ACCESS_SECRET"

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)
api = tweepy.API(auth)

friends_ids = []
for _id in tweepy.Cursor(api.friends_ids).items():
    friends_ids.append(_id)

followers_ids = []
for _id in tweepy.Cursor(api.followers_ids).items():
    followers_ids.append(_id)

実際に使ったコードでは、この後にそれぞれのListをSetにして、set.unionをとり、相互フォローを出す処理なども入れていた。

追記:2016-10-27 ここから

今日、何気なくQiitaを見てて、tweepy がメンテナンスされなくなった という記事を見かけた。「あれっ」と思って、tweepyのgithubページを見たら、 本当に「もうメンテしない」って書いてた。 近い将来、twitterAPIの仕様変更などで動かなくなることは目に見えてるので、requests-oauthlibを使って書き直したものを以下に載せる。

from requests_oauthlib import OAuth1Session
import json

twitter = OAuth1Session(CONSUMER_KEY, client_secret = CONSUMER_SECRET,
                        resource_owner_key = ACCESS_TOKEN, resource_owner_secret = ACCESS_SECRET)

friends_ids = []
cursor = -1
while cursor:
    req = twitter.get('https://api.twitter.com/1.1/friends/ids.json?cursor={}'.format(cursor))

    if req.status_code == 200:
        data = json.loads(req.text)
        friends_ids.extend(data['ids'])
        cursor = data['next_cursor']
    else:
        print("request error : {}".format(req.status_code))
        break

followers_ids = []
cursor = -1
while cursor:
    req = twitter.get('https://api.twitter.com/1.1/followers/ids.json?cursor={}'.format(cursor))

    if req.status_code == 200:
        data = json.loads(req.text)
        followers_ids.extend(data['ids'])
        cursor = data['next_cursor']
    else:
        print("request error : {}".format(req.status_code))
        break

以下のページが参考になった。

追記:2016-10-27 ここまで

取得したfriendsとfollowersをデータベースに保存

そして、sqlite3のデータベースに保存しておく。 以下のコードは上のコードに続くような形で書いている。

import sqlite3

con = sqlite3.connect("{}.db".format("db_name"))

cur = con.cursor()
cur.execute("select * from sqlite_master where type='table'")

tables = []
for item in cur.fetchall():
    tables.append(item[1])

if "friends" not in tables:
    con.execute("create table friends(user_id integer primary key not null unique, friend integer, follower integer)")

for _id in friends_ids:
    con.execute("replace into friends(user_id, friend) values({}, {})".format(_id, 1))

for _id in followers_ids:
    con.execute("insert or ignore into friends(user_id, follower) values({}, {})".format(_id, 1))
    con.execute("update friends set follower = {} where user_id = {}".format(1, _id))

con.commit()
con.close()

followersのほうの処理で面倒なことになっているのは、sqlite3のreplaceがdelete処理を含んでしまうので、 insert or ignoreupdateを組み合わせるという方法を採っているから。 これはStack Overflowあたりで見かけたような。

データベースを見る

あとは、sqlite3の操作でフォロー状況を確認できる。

データベースを指定して開く

sqlite3 db_name.db

相互フォロー数を出す

select count(*) from friends where friend = 1 and follower = 1;

リフォローしていない数を出す

select count(*) from friends where friend = 0 and follower = 1;

最後に

いかにも業者なアカウントのフォローは避けたいものです。 ただし、idからそのような判別はできないので、tweepyのapi.lookup_users()screen_nameを引っ張てきて、リフォロー用の即席htmlページを書き出したりもしていた。 あと、この関数の説明がtweepyドキュメントになくて、 githubで確認したのを思い出した。

オンラインジャッジでの Python Tips

最近、時間があるときにオンラインジャッジの競技プログラミングもどきをやっている。 オンラインジャッジでは、入出力がCLIで行われるため、 入出力周りで何度となく同じようなコードを書く。 しかし、1ヶ月くらい別の言語をいじってたりすると、 そのようなコードを書くのに少し時間が掛かってしまう。 ということで、よく使う(使った)ものをまとめておこうと思った。

input系

単純に入力が数値のときには、input()から得られたstrをintに変換しておくと、 後で数値演算したときにエラーを吐かれることがない。

int_single = int(input())  # <= 1
print(int_single) # => 1

スペース区切りで数値が複数渡されたときは、strのsplit()で分割して、 intに変換しておく。これで、ループに使うときも変換がいらない。 多重代入もよく使う。

int_list = [int(x) for x in input().split()] # <= 1 2 3
print(int_list) # => [1, 2, 3]

a, b, c = [x for x in input().split()] # <= test1 test2 test3
print(a, b, c) # => test1 test2 test3

上と同じ1行スペース区切りだが、数値文字列だけではなく、 通常の文字列も含まれていて、そのままintに投げてしまうとエラーになる。 そんなときは、内包表記内に三項演算子で条件分岐処理を入れ込む。 strのisdigit()は結構使う。

# <= l1 10 20 30\nl2 10 20 30
labeled_list = [[int(x) if x.isdigit() else x for x in input().split()] for i in range(2)]
print(labeled_list)
# => [['l1', 10, 20, 30], ['l2', 10, 20, 30]]

複数行で文字列が入力されるときは、range()ループで必要な回数分、 ループを回せばOK!

str_list = [input() for i in range(3)] # <= 1\n2\n3
print(str_list) # => [1, 2, 3]

複数行の入力がある場合かつ終了条件がある場合、 これは諦めて、while Trueループを書いちゃってる。

input_text_list = []
while True:
    input_text = input() # <= test1\ntest2\ntest3\ntest4\ninput end.
    if input_text == "input end.":
        break
    input_text_list.append(input_text)
print(input_text_list) # => ['test1', 'test2', 'test3', 'test4']

loop系

whileループやforループのelse句はよく使う。 フラグ処理が省略できるので、楽々。

cnt = 0
while True:
    cnt += 1
    for i in range(10):
        cnt += 1
        if cnt > 100:
            break
    else:
        print(cnt)
        continue
    print("last cnt: {}".format(cnt))
    break
# => 11\n22\n33\n44\n55\n66\n77\n88\n99\nlast cnt: 101

zip()は複数のリストやタプルをまとめてループできる。 それと、内包表記の多重ループ。平面グリッド走査のような全ての組み合わせでループを回すときなどで使える。 あと、文字列のjoin()もよく使う。

upper_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
lower_str = "abcdefghijklmnopqrstuvwxyz"
upper = ["{}:{}".format(u, ord(l)-32) for u,l in zip(upper_str, lower_str)]
lower = ["{}:{}".format(u.lower(), ord(l)) for u in list(upper_str) for l in list(lower_str) if u == l.upper()]

print("\n".join(upper)) # => A:65\nB:66\nC:67\n …
print("\n".join(lower)) # => a:97\nb:98\nc:99\n …