目標とするアプリケーション

  • よく自分が訪問するWebサイトの記事一覧を取得する.
  • それを一括で表示する.
こんな感じのアプリケーションを作ってみます.

この記事のスコープ

  • 記事一覧を取得し、その一覧をJSON形式で返すFlask APIを作る

スコープ外

  • 作成したAPIを叩くようなフロントサイドアプリケーションを作る

使うもの

  • Python
  • Flask (Pythonの軽量Webフレームワーク)
  • BeautifulSoup (Webスクレイピングに用いられるライブラリ)

Python3 がインストールされていることは前提とします. また, Windowsを使うものとして説明します.

実践

実際にFlask APIを作っていきます.

環境構築

プロジェクトフォルダーの作成と venv フォルダーの作成を行います.
その後, 環境をアクティブにします.

$ mkdir contents_aggregator
$ cd contents_aggregator
$ py -3 -m venv venv
$ venv\Scripts\activate

Flask のインストール

アクティブにした環境内で以下のコマンドを実行し, Flaskをインストールします.

$ pip install Flask

Hello World

まずは`Hello, World`とだけ出力するWebアプリケーションを作ってみましょう.
app.pyをプロジェクトフォルダー内に作成しておいてください.

作成が終わったら次のとおりコードを書いて, app.pyを実行してください.

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'Hello, World!'


if __name__ == '__main__':
    app.run()
app.py (全文)
実行結果

Yeah!!!

@app.route()の部分が「どのURLが関数をトリガーするべきか」をFlaskに伝えています.今回の場合'/'なので 127.0.0.1:5000/ は hello_world()をトリガーし, Hello, World!と表示しました.

拡大

今回作るアプリケーションは対して大きくはならないのですが, 出来る限り見通しがよくなるようにapiとなる関数は別ファイルに作成しようと思います.

app.pyに次のように変更します

from flask import Flask
import api

app = Flask(__name__)

app.register_blueprint(api.bp)

if __name__ == '__main__':
    app.run()
app.py (全文)

app.register_blueprintの部分でappにBlueprintオブジェクトを追加しています.このBlueprintオブジェクトは route と関数などのコレクションです.

api.py を作成し, 次のコードを書いてください.

from flask import Blueprint

bp = Blueprint('api', __name__, url_prefix='/api')


@bp.route('/')
def hello():
    return "Hello world"
api.py

bp は Blueprintオブジェクトです. url_prefix = '/api'としたことにより, このオブジェクトにおけるroute定義は全て頭に'/api' がつくことになります.

app.py をもう一度実行し, 次は 127.0.0.1/apiにアクセスしてみましょう.

実行結果 (/api)

これで準備が整いました!実際にコンテンツを収集して返してみましょう!

コンテンツを収集してみる

準備が整ったので実際にコンテンツを収集してみます。みなさん一度は見たことがあるであろうQiitaのトップページに表示されるTrendを収集してみたいと思います.

Qiita トップページ

Qiita の Trend ですが, HTML ファイルを読んでみると, data-hyperapp-appというカスタム属性の値が'Trend'のものの, data-hyperapp-propsというカスタム属性の値が, トレンドに表示される記事一覧のjsonとなっていることがわかります.

ということで上記の部分をBeautifulSoupを使って抽出してみましょう.

from flask import Blueprint
import requests
from bs4 import BeautifulSoup

### 中略 ###

@bp.route('/get_contents/qiita')
def get_contents_qiita():

    res = requests.get('https://qiita.com/')
    soup = BeautifulSoup(res.text, 'html.parser')
    target = soup.select('div[data-hyperapp-app="Trend"]')[0]
    return target.get('data-hyperapp-props')
api.py (一部)

requestsとbs4/BeautifulSoupを用いるので pip install requestsおよび, pip install beautifulsoup4 が必要です.

ここまで出来たらapp.pyを実行してみましょう. 上記のコードを書いたのであれば '/api/get_contents/qiita'を開くことで以下のようなものが見られると思います.

実行結果

これでAPIの完成です!お疲れさまでした!

参考としてQiitaの各記事のリンクは次のようになっています:
https://qiita/{node.author.urlName}/{node.uuid}

このあと

みなさん各々見るサイトが異なると思います. そのサイトで同じようにスクレイピングAPIを作ってみましょう.

スクレイピングAPIを作ることができれば, あとは「APIを叩いていい感じに表示する画面」を作るだけです. 私は一番最初にあげたアプリケーションを作るのにJavaScript / Reactを使いましたが好きなものを使うと良いでしょう.