ポジティブに生きていく

長い文章を書く

xonshでニコ動のランキングを見るの

(TBD) 起きたら続き書く この記事は, Xonsh Advent Calendar 2018 - Qiitaの13日目の記事です

はじめに

ばんくしとご飯食べた時にxonshの思いを語ってもらい,興味を持ったのでxonshを導入してみました.
最近はほとんどPythonしか書いてないのでPython製のシェルは私と相性が良さそう. CUI上(iTerm)だけですが, matplotlibで気軽にデータの可視化できるのはすごく便利でそういうことにはよく使っているが. 導入してから,何も設定書かずに担当日にxonshについて詳しく調査し始める🌀

ptkチュートリアルとサンプルが楽しすぎてそれ動かして理解するだけで1日溶けそう.
github.com

個人的にこの辺りのptkの機能使って何かしたかった..

f:id:watyao:20181213023054p:plain
python-prompt-toolkit/examples/full-screen/hello-world.py
f:id:watyao:20181213023156p:plain
python-prompt-toolkit/examples/dialogs/button_dialog.py

つくったもの

昨年度と今年のxonshのアドベントカレンダーとばんくしのxonshの記事を一通り読んで, 対話式で何か作りたいなーって思ったんだけどアイデアがすぐに出てこず..

今ではランキングがあまり移り変わりないですが,ニコ厨なのでついついランキングを観てしまいます. その癖をなくそうとしてAPI叩いてすぐにCUI上で見れるようにiTerm + imgcat + xonshで作成しました.
ニコ動のランキング情報をJSONで取得してみる - yutaponのブログ

うーんxonshアドベントカレンダーとはなんだったんだ...

f:id:watyao:20181213021618p:plain
つくったもの

しくみ

仕組み的は,ばんくしの画像検索の発想パクってきてる. ニコ動のランキングAPI叩く→画像サムネイルとタイトルとリンクを取得→サムネを集合化→選択

ランキングAPI: http://www.nicovideo.jp/ranking/view/monthly/{category}?rss=2.

import io
import requests
import xmltodict
import urllib
import urllib.request
from bs4 import BeautifulSoup

from PIL import Image, ImageDraw, ImageFont
def nico_ranking(args,stdin):
    DISPLAY_NUM=30
    if (len(args))==0:
      category="all"
    elif args[0] in ["game","anime","jikkyo","toho","vocaloid","g_ent2","virtual","sing"]:
      category=args[0]
    else:
      category = "all"
    font =  ImageFont.truetype("/System/Library/Fonts/ヒラギノ明朝 ProN.ttc",15)

    xml=requests.get("http://www.nicovideo.jp/ranking/fav/hourly/{}?rss=2.0".format(category)).text
    dict=xmltodict.parse(xml)
    urls = []

    for rank in range(0,DISPLAY_NUM):
        title = dict["rss"]["channel"]["item"][rank]["title"]
        description=dict["rss"]["channel"]["item"][rank]["description"]
        url=dict["rss"]["channel"]["item"][rank]["link"]
        urls.append(url)
        soup = BeautifulSoup(description, "html.parser")
        try:
            img_path = soup.findAll('img')[0]["src"]+".L"
            file =io.BytesIO(urllib.request.urlopen(img_path).read())
            img = Image.open(file)
        except:
            img_path = soup.findAll('img')[0]["src"]
            file =io.BytesIO(urllib.request.urlopen(img_path).read())
            img = Image.open(file)
            img = img.resize((360,270))
        #print(img_path)

        draw = ImageDraw.Draw(img)
        draw.text((10, 10), title, fill=(255, 255, 255), font=font)
        img.save("/tmp/{}.png".format(rank+1))
        #plt.imshow(img)
        #plt.show()

    img = Image.new('RGB', (360 * 5, 270*DISPLAY_NUM//5))
    for j in range(DISPLAY_NUM):
        im = Image.open("/tmp/{}.png".format(j+1))
        img.paste(im, ( 360*((j%5)), 270*(j//5)))
    img.save("/tmp/h.png")
    imgcat /tmp/h.png
    
    img_num = input('image number(1~{}) : '.format(DISPLAY_NUM))
    try:
      echo -n @(urls[int(img_num)-1]) | pbcopy
    except:
      print('Bad input.')

aliases["niconico"] = nico_ranking

おわり

対話式でロックマンのステージセレクトのような感じで画像選択できるかなーって思ったけど,すぐにはできなかった...

f:id:watyao:20181213211958j:plain

できたら最高だから, もう少し足掻いてみます✨
xonshというよりptkが楽しい. 紹介してくれたばんくしに感謝

さんきゅー