Iruca Log

Iruca Log

東京に住むWeb系エンジニアによる技術&雑記ブログ

SNSでフォローする!

自分が購読しているはてなブログの情報を一覧で取得するプログラム書いた [python]

こんにちは、イルカです。

このブログを購読してくださっている読者の方に何かメリットを与えたい!
という事で下記をプログラムでできないか検討を続けてます。

  • 自分を読者登録してくれた人は読者登録し返す
    • twitterのフォローバックみたいな!
  • 自分が読者登録している人の最新記事には必ずスターを付ける


実現する前段階として、「自分が読者登録しているブログとその最新記事の一覧」を抜き出す機能をまずは実装したという技術記事になります。


下記は関連記事です。
iruca21.hateblo.jp

最後まで読むのが面倒な方へ

下に書いてあるプログラムを適当なLinuxマシンで動かすと、
自分が購読しているブログの

  • 著者のはてなID
  • ブログのホスト名
  • 最新エントリのURL

を一覧で抜きだすことができます。

実行例

[root@hoge get_subscribing]# python get_subscribing_util.py
[はてなID] [ブログのホスト名] [最新エントリのURL]
masaki709 www.nubatamanon.com http://www.nubatamanon.com/entry/2017/04/18/233715
cucumberking231 www.cucumberking.com http://www.cucumberking.com/entry/nhk_e-tere_ranking5
hiro-loglog www.hiro-log.net http://www.hiro-log.net/entry/2017/04/18/222715
ponkotsu1215 chiiseka.hatenablog.com http://chiiseka.hatenablog.com/entry/2017/04/18/221454
nqumen nqumen.hatenablog.com http://nqumen.hatenablog.com/entry/2017/04/18/221251
make_usagi gwgw.hatenablog.com http://gwgw.hatenablog.com/entry/2017/04/18/220852
sakamotwin sakamotwin.hatenablog.com http://sakamotwin.hatenablog.com/entry/2017/04/18/220212
MOLOVE molove.hatenablog.com http://molove.hatenablog.com/entry/2017/04/18/214242
poco89 dokusho.hateblo.jp http://dokusho.hateblo.jp/entry/2017/04/18/212759
...(以下略)

プログラム紹介

概要

はてなにログインした状態で こういうページ にアクセスすると、自分の購読中のブログの情報が見れます。

f:id:iruca21:20170418024458j:plain

このページのソースコードから強引にHTMLをぶった切って下記の情報を抜き出しているプログラムになります。

  • 著者のはてなID
  • ブログのホスト名
  • 最新エントリのURL

尋常じゃないくらい強引なプログラムなので、ページのデザインにちょっとでも変更があったら崩壊します…(笑)

ご利用は自己責任で!
はてなのサーバや運営に迷惑をかけないように、スリープ間隔を十分にとりつつデータを取得しましょう。

必要モジュール

python モジュール requests が必要です。
以下の手順などでインストールしておいてください。

yum -y install python-setuptools
easy_install pip
pip install requests

プログラム詳細

get_subscribing_util.py

#!/usr/bin/python
#-*- coding:utf-8 -*-

import requests
from urlparse import urlparse
import time


"""
自分が購読しているはてなブログの著者とブログURLを取得する
"""

def get_rk( hatena_id, password ):
    """はてなIDとログインパスワードからrkを取得します。
    rkが何なのかはよく分からない。
    """
    target_url = "https://www.hatena.ne.jp/login"
    payload = {'name': hatena_id, 'password': password}
    response = requests.post(target_url, data=payload )

    rk = response.headers["Set-Cookie"].split("rk=")[1].split(";")[0]
    return rk

    
def get_subscribings( rk, interval=1.0 ):
    """ 自分が購読しているブログの情報を取得する。
        http://blog.hatena.ne.jp/-/antenna のページに現れる購読中のブログ情報を利用する。
    Args:
        rk: get_rk関数で得られるトークン文字列
        interval: 購読中のブログを表示する各ページを見てまわる間のスリープ間隔(秒).
                はてなのサーバに負荷をかけないようにするため。
    Returns:
        自分が購読しているブログの情報を以下の形で返却する。
        [(著者のはてなID, ブログのホスト名, 直近のエントリのURL)というタプルの配列]
    """
    subscribings = []

    page=1
    continue_flag = True

    # 次のページが存在する限り取得し続ける
    while( continue_flag ):
        target_url = "http://blog.hatena.ne.jp/-/antenna?page="+ str(page) 

        headers = {"Cookie" : "rk="+ str(rk) }
        response = requests.get( target_url, headers=headers).content

        # 返却されたHTMLから、著者のhatena idと直近のエントリのURLが含まれる部分を無理やり抜きだす.

        # http://blog.hatena.ne.jp/-/antenna ページに現れる購読中のブログごとの情報を含むHTMLを分けて考えるのにちょうどいいHTMLを使う
        author_url_contained_texts = response.split( "\" target=\"_blank\" data-track-name=\"admin-antenna-entry admin-antenna-entry-title\" data-track-once>" )

        # 購読しているユーザ数だけループを回す
        for k in range(0, len( author_url_contained_texts )-1 ):
            # delimiter_htmlの直前には直近のエントリのURLが '<a href="' の後に書いてあるのでそこから直近エントリのURLを取り出す。
            # また、そのちょっと前に
            # https://cdn1.www.st-hatena.com/users/hi/hiro-loglog/profile.gif
            # という著者のはてなIDを含む画像URLがあるのでここから強引にはてなIDを取り出す
            recent_entry_url = author_url_contained_texts[k].split('<a href="')[-1]
            author_hatena_id = author_url_contained_texts[k].split('/profile.gif')[-2].split("/")[-1]
            
            # recent_entry_url は http://www.mako0625.net/entry/2017/04/17/214151 のような文字列なので、そこからホスト名を取り出す
            blog_hostname = urlparse(recent_entry_url).hostname

            subscribings.append( (author_hatena_id, blog_hostname, recent_entry_url) )
    
        # まだ次のページがあるようなら続ける
        if "class=\"btn\">次のページ</a>" in response:
            page += 1
            # はてなサーバにDoSをかけないようにスリープを入れる
            time.sleep( interval )
            continue
        else:
            # whileループから抜け出す
            continue_flag = False

    return subscribings

if __name__ == "__main__":
    # 自分のhatena_id
    hatena_id = "XXXXX"
    # 自分のはてなログインパスワード
    login_password = "XXXXX"
    # 自分のブログのURL
    blog_url = "iruca21.hateblo.jp"

    rk = get_rk( hatena_id, login_password )

    # 取得!
    subscribings = get_subscribings( rk )
    # 取得結果を表示してみる
    print "[はてなID] [ブログのホスト名] [最新エントリのURL]"
    for subscribing in subscribings:
        print subscribing[0], subscribing[1], subscribing[2]

実行してみる

プログラム中の下記設定部分を書き変えてください。

    # 自分のhatena_id
    hatena_id = "XXXXX"
    # 自分のはてなログインパスワード
    login_password = "XXXXX"
    # 自分のブログのURL
    blog_url = "XXXXX"


では、実行してみましょう。

はてなのサーバに負荷をかけないようにスリープ時間を入れつつデータを小分けに取得するようにしているので、
購読数÷10 秒くらいの実行時間がかかります。

[root@hoge get_subscribing]# python get_subscribing_util.py
[はてなID] [ブログのホスト名] [最新エントリのURL]
masaki709 www.nubatamanon.com http://www.nubatamanon.com/entry/2017/04/18/233715
cucumberking231 www.cucumberking.com http://www.cucumberking.com/entry/nhk_e-tere_ranking5
hiro-loglog www.hiro-log.net http://www.hiro-log.net/entry/2017/04/18/222715
ponkotsu1215 chiiseka.hatenablog.com http://chiiseka.hatenablog.com/entry/2017/04/18/221454
nqumen nqumen.hatenablog.com http://nqumen.hatenablog.com/entry/2017/04/18/221251
make_usagi gwgw.hatenablog.com http://gwgw.hatenablog.com/entry/2017/04/18/220852
sakamotwin sakamotwin.hatenablog.com http://sakamotwin.hatenablog.com/entry/2017/04/18/220212
MOLOVE molove.hatenablog.com http://molove.hatenablog.com/entry/2017/04/18/214242
poco89 dokusho.hateblo.jp http://dokusho.hateblo.jp/entry/2017/04/18/212759
lightgauge www.fair-skinned-monster.com http://www.fair-skinned-monster.com/entry/2017/04/18/211430
mikofukusoba mikofukusoba.hatenablog.com http://mikofukusoba.hatenablog.com/entry/2017/04/18/204036
yuru-ppo yuru-ppo.hatenadiary.com http://yuru-ppo.hatenadiary.com/entry/2017/04/18/201836
mako0625 www.mako0625.net http://www.mako0625.net/entry/2017/04/18/200554
...(以下略)

うんうん、満足だ。

まとめ

自分の購読しているはてなブログ一覧をいっぺんに見れるページって見当たらなかったから、
意外とこのプログラムは需要があるかもしれない。
よろしければぜひご利用ください!

自分も知らず知らずのうちに65件もブログ購読してたんだなあ。


ではでは!