ohmemo メモです

ohmemo

「今更な」ことを書きます

はてなブックマークの人気エントリーの情報を抽出する

この記事は CAMPHOR- Advent Calendar 2017 9日目の記事です.
こんにちは, ohmurakenです.
スクレイピングの練習も兼ねて, はてなブックマーク人気エントリーの情報を抽出してみたよという記事です.

人気エントリー

はてなブックマークでは以下のようなURLで日にち毎の人気エントリーがまとめられています.
http://b.hatena.ne.jp/hotentry/{category}/{YYYYMMDD}
例えばテクノロジーカテゴリに関する, 2017年12月5日人気エントリーの一覧ページのURLは以下のように定義されています.
http://b.hatena.ne.jp/hotentry/it/20171205

一覧ページのHTML構成

人気エントリーのページは1つのタイル内にエントリーの情報が埋め込まれています. それぞれのタイルはHTMLのliタグで区切られており, 複数のclass名が用いられています.

liタグのclass名 タイル内のコンテンツ
entry-unit category-{category} hb-entry-unit-with-favorites テキスト
entry-unit category-{category} hb-entry-unit-with-favorites has-image 画像
entry-unit category-{category} hb-entry-unit-with-favorites has-image trim-image トリミング画像

Chromeデベロッパーツールで確認するとよくわかります.

個々のエントリー情報の抽出

次にタイルの中から情報を抽出してみます. タイル内では各情報が以下のようにHTMLで記述されています.

Pythonによる実装

Pythonで実装するならBeautifulSoupというライブラリを使うと簡単にHTMLを解析する事ができ, 一覧ページのHTMLをBeautifulSoupにParseさせると, タグ名やクラス名を指定する事で要素や値を抽出する事ができます. また, pandas.DataFrameと組み合わせるとシュッと表形式で格納できます.

import requests
from collections import OrderedDict
from bs4 import BeautifulSoup as bs
from pandas import DataFrame


def get_hotentry_info(category, target_date):
    url = "http://b.hatena.ne.jp/hotentry/{}/{}".format(category, target_date)
    res = requests.get(url)
    soup = bs(res.text, 'html.parser')

    check_list = [
        "entry-unit category-{} hb-entry-unit-with-favorites has-image".format(category),
        "entry-unit category-{} hb-entry-unit-with-favorites".format(category),
        "entry-unit category-{} hb-entry-unit-with-favorites has-image trim-image".format(category)
    ]

    # HTMLからタイルのみを抽出する
    tiles = soup.find_all("li", {"class": check_list})

    # 格納する辞書とDataFrameを用意
    entry_info = OrderedDict({})
    hotentry_df = DataFrame()

    # 個々のタイルからエントリー情報を抽出する
    for tile in tiles:
        entry_info["entry"] = tile.find("a", {"data-track-click-target": "entry"})["href"]
        entry_info["entry_link"] = tile.find("a", {"class": "entry-link"})["href"]
        entry_info["entry_title"] = tile.find("a", {"class": "entry-link"})["title"]
        entry_info["entry_id"] = tile.attrs["data-eid"]
        entry_info["entry_date"] = tile.find("li", {"class": "date"}).string
        entry_info["bookmark_count"] = tile.attrs["data-bookmark-count"]
        hotentry_df = hotentry_df.append([entry_info], ignore_index=True)
    return hotentry_df


if __name__ == "__main__":
    category = "it"
    target_date = "20171205"
    print(get_hotentry_info(category, target_date))

実行すると以下のような結果が得られます. (実行結果は12月7日時点のものです.)

まとめ

はてなブックマーク人気エントリーから情報を抽出する方法をまとめてみました. エントリーに対するコメントやスターについては, はてなブックマーク REST APIはてなスター取得 APIを使用するとサクッと取得できます.

CAMPHOR- Advent Calendar 2017 明日の担当は @kasajei の『面白い本の選び方 〜ハズレ本は読み捨て、タイトルに騙されずに翻訳本を買え!』です. お楽しみに!