こんにちは!ほけきよです!
はてなブログをしている皆さんなら、当然アレ、気になりますよね??
そうはてブです。
自分の記事が拡散された時の満たされる感じは、クセになりますよね。 今回は、自分の記事のはてブがどのように増えて行くかを、APIを使って取得できるようにしてみました。
また、はてブが伸びるかどうかを左右する情報も取得できるようにしました!! 基本コピペでOKになっているはずなので、pythonを使っている方は、一回試してみると楽しいですよ!
必要なモジュール
まず、モジュールをインポートしていきましょう。デフォルト以外で入れなければ行けないのは以下の二つ
- bs4 (webスクレイピング用のモジュール)
- matplotlib (グラフ描画用のモジュール)
pipで入れちゃいましょう。 windowsでpythonを使いたい方は、関連記事へGO. Anacondaには上の二つが含まれているのでそれだけでOKですよ。
コード
#coding:utf-8 %matplotlib inline #jupyterを使う方はこれを入れておく import urllib2 from bs4 import BeautifulSoup import json import datetime import matplotlib.pyplot as plt url = "http://www.procrasist.com/entry/2017/01/07/154441"
はてブの情報を取得
はてなブックマークには、簡単に情報をGETできるように、APIが設計されています。 公式HPか、Syncerさんのページがとてもわかりやすいので参照するにはオススメです
はてブの情報をとってくるためには、自分が調べたいurlの前にhttp://b.hatena.ne.jp/entry/json/
をくっつける必要があります。ここにアクセスすることで、情報をGETできます。
ここで一つ注意です。ブックマークを非公開にしている人の情報の詳細ブックマーク情報(時間・コメント等)は取得することができません。ですので、結果的には本来のブックマーク総数より小さく表示されてしまうこともあります。
コード
def get_timestamps(url): """ はてブのタイムスタンプをget """ data = urllib2.urlopen("http://b.hatena.ne.jp/entry/json/{}".format(url)).read() info = json.loads(data.strip('(').rstrip(')')) timestamps = list() if info != None: # 公開ブックマークが存在する時に、それらの情報を抽出 bookmarks=info["bookmarks"] title = info["title"] for bookmark in bookmarks: timestamp = datetime.datetime.strptime(bookmark["timestamp"],'%Y/%m/%d %H:%M:%S') timestamps.append(timestamp) timestamps = list(reversed(timestamps)) # ブックマークされた時間を保存しておく return info, timestamps
はてブの伸びを左右する情報たち
以前もブログで少し話したことがありますが、はてブの伸びは、 エントリーに掲載されるかどうかによって左右されます。
私が伸びるかなーどうかなー。と気になるときにチェックするのは以下の5箇所です
- カテゴリ新着エントリ
- カテゴリ人気エントリ
- 総合新着エントリ
- 総合人気エントリ
- はてなブログトップ
新着エントリ < 人気エントリ < はてなブログトップ
の順で掲載期間が長くなっている気がします。これら5つについて、情報をGETできるようにしました!
コード
# ページカテゴリ取得 def get_category(url): try: html = urllib2.urlopen("http://b.hatena.ne.jp/entry/{}".format(url)) soup = BeautifulSoup(html,"lxml") return soup.find("html").get("data-category-name") except urllib2.HTTPError as e: print(e.reason) except urllib2.URLError as e: print(e.reason) #はてブのエントリリストの順位チェック def rank_checker(url,hatebu_url): try: html = urllib2.urlopen(hatebu_url) except urllib2.HTTPError as e: print(e.reason) except urllib2.URLError as e: print(e.reason) soup = BeautifulSoup(html,"lxml") a = soup.find("a",href=url) if a == None: rank = None else: rank = a.get("data-entryrank") return rank # はてなブログのトップページに乗っているか def is_hatenatop(url): try: html = urllib2.urlopen("http://hatenablog.com/") except urllib2.HTTPError as e: print(e.reason) except urllib2.URLError as e: print(e.reason) soup = BeautifulSoup(html,"lxml") a = soup.find("a",href=url) if a is None: return False return url == a.get("href") def getdata(url): category = get_category(url) # カテゴリ新着エントリ category_entrylist = "http://b.hatena.ne.jp/entrylist/"+category new_cate = rank_checker(url,category_entrylist) # カテゴリホットエントリ category_hotentry = "http://b.hatena.ne.jp/hotentry/"+category hot_cate = rank_checker(url,category_hotentry) # 総合新着エントリ entrylist = "http://b.hatena.ne.jp/entrylist" new_all = rank_checker(url,entrylist) # 総合ホットエントリ hotentry = "http://b.hatena.ne.jp/hotentry/" hot_all = rank_checker(url,hotentry) # はてなトップ hatena_top = is_hatenatop(url) # データまとめ string = "hatebu category entrylist rank : {}\nhatebu category hotentry rank : {}\nhatebu overall entrylist rank : {}\nhatebu overall hotentry rank : {}\nlisted up to hatenablog toppage : {}"\ .format(rank_checker(url,category_entrylist),rank_checker(url,category_hotentry), rank_checker(url,entrylist),rank_checker(url,hotentry),is_hatenatop(url)) print(string) return string
プロットをする
先ほどのタイムスタンプと、GETしたエントリ情報をグラフにしていきます。
visualize関数を作り、タイムスタンプで可視化。情報はannotate
関数で入力します。
記事が初めてブクマされた時から2日間のプロットとしています。
※注 :グラフの範囲やannotateは、グラフの形によって変えたほうが見栄えが良くなることもあるので、dayrange
で範囲を、plt.annotate内の
xytext=(timestamp[-1],5)`の座標を変えることで、調整してください。
コード
# プロット def visualize(info, timestamp, data, label="", dayrange=2,annotate=True): plt.xkcd() count = len(timestamp) number = range(count) submit = timestamp[0] plt.plot(timestamp,number,"-",lw=3,label=label) plt.xlim(submit,submit+datetime.timedelta(days=dayrange)) if annotate: plt.annotate(data,xy=(timestamp[-1], number[-1]), arrowprops=dict(arrowstyle='->'), xytext=(timestamp[-1],5))
実行してみる
以上が具体的な内容です。それでは、実際にはてブのリストからいくつか可視化したものをみてみましょう
- かキタローさんのバズっている記事
Udemy、いいですよね。プログラミングとかの勉強のために使ったりしています!この記事、今までのはてブの推移と、現在(2017/4/9 15:00)のステータスを見てみましょう。
コード
url = "http://www.kakitaroo.com/entry/Udemy" plt.figure(figsize=(10,7)) entry_info = getdata(url) hatebu_info, timestamps = get_timestamps(url) visualize(hatebu_info, timestamps, entry_info, label="Udemy") plt.legend() plt.show()
結果
まだまだ伸びそうですね!
比べることもできる
時系列データを見ることができるので、他のデータと重ねて比べることもできます。*1 先ほどの記事と、もう一つバズっている↓の記事を比べてみましょう
plt.figure(figsize=(10,7)) url2 = "http://www.kakitaroo.com/entry/Udemy" url1 = "http://www.sekkachi.com/entry/Heikin_HyoujunHensa_Flow" entry_info = getdata(url1) hatebu_info, timestamps = get_timestamps(url1) visualize(hatebu_info, timestamps, entry_info,label="Udemy", annotate=False) entry_info = getdata(url2) hatebu_info, timestamps = get_timestamps(url2) visualize(hatebu_info, timestamps, entry_info,label="Ave, Std", annotate=False) plt.legend() plt.show()
結果
後発記事が伸びてきていることがわかると思います! こうやって競争させるのも面白いですよね!
まとめと今後やりたいこと
今後やりたいのは、順位を使って、はてブ数を予測できないかな〜ってこと。 データを集める土台はできたので、あとは学習器に各情報と数分後のはてブ数のデータを投げてやって、伸びを予測してみたいなぁ。と思いました。
色々データを集められると、それを使って色々と考えることができるので、楽しいですね!
*1:適当に重ねているだけなので、もうちょっと出力を整えたほうがいいかもしれません。