はじめに
ちょっと諸事情でとあるサイトを定期的に循環しデータを取得する必要がありました(いわゆるクロール)。適当にサーバ立ててスクリプト書いて、 cron で回せば終わりなんですが、それでは成長感がなさ過ぎるので色々今まで未着手だった技術やプラットフォームを使ってやってみた、という記録。
実際に必要だったクロール先をそのまま記事にするのは微妙な感じがするので、今回はこの記事用に適当なクロール先を見つけようかと探した。色々悩んだが、そういえば定期的にちょくちょく確認しているYahoo!リアルタイム検索の「トレンドキーワード」という20個の単語を定期的に取得する、というお題にすればあとからなにかに使えるのでは、と思ったので今回はこれをネタにする。
※Yahoo!リアルタイム検索 Twitter検索をヤフーが提供している。おそらくトレンドキーワードも今、Twitterでバズってるキーワードを提供していると思われる。
クローラの作成
今回はPythonを利用してクローラを作成する。 IDEはIntellJを使っているのでそのキャプチャを貼り付けるが、ここは何でも良い。雛形としてプロジェクトRootにappフォルダを作ってそこにクローラのpythonファイルを置く。

クローラ自体は、requestsを使ってHTMLを取得して、BeautifulSoupライブラリを使って必要箇所を抜き出す単純なもの。BeautifulSorpでは selectを使ってCSSセレクタで目的の場所を指定するのが便利。
以下のようにChromeの開発者機能を呼び出して、抜き出したい箇所をElement画面で選択して右クリック、Copy > Copy selector でコピペできる。例えばキャプチャの例で、トレンド1位のゲーム情報を選択してセレクタを取得すると以下のようなCSSセレクタが取得できる
#contentsBody > div.main > article.Trend_Trend__5OTRp > section > ol:nth-child(1) > li:nth-child(1) > a > article > h1

このセレクタを
soup = BeautifulSoup(res.text, 'html.parser')
for item in soup.select("CSSセレクタ...."):
print(item)
とすると 「<h1>ゲーム情報</h1>」と取得できる。今回は1位から20位まで全て欲しいので、ちょっとセレクタを削ってリストグループでとれるようにする(この辺は試行錯誤で)。最終的にとりあえず、ファイルにOutputするだけのクローラとしては以下の通り完成とする(結局左右の順位列をそれぞれ取得しているので冗長になってカッコ悪いけどまあ良しとする)
import json
TARGET_URL = "https://search.yahoo.co.jp/realtime"
def main():
keyword = wadai_crawl()
print(keyword)
f = open("wadai.json", "w")
f.write(json.dumps(keyword))
f.close()
def wadai_crawl():
keywords = []
res = requests.get(TARGET_URL)
soup = BeautifulSoup(res.text, 'html.parser')
for item in soup.select("#contentsBody > div.main > article.Trend_Trend__5OTRp > section > ol:nth-child(1) > li"):
keywords.append(item.find("h1").getText())
for item in soup.select("#contentsBody > div.main > article.Trend_Trend__5OTRp > section > ol:nth-child(2) > li"):
keywords.append(item.find("h1").getText())
return keywords
if __name__ == "__main__":
main()

実行した結果以下のようにファイル(wadai.json)がOutputされる。
Docker化
作成したクローラーをDockerで動かす。Dockerの詳細は私が以前にQiitaに書いた記事を参照。
以下のようなDockerfileおよびrequirements.txtを作成してプロジェクトルートに配置します
FROM python:slim
WORKDIR /opt/app
COPY requirements.txt .
COPY app/ .
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
ENTRYPOINT python crawler.py
requests~=2.25.1
beautifulsoup4~=4.9.3
IntellJのDockerプラグインを入れとくとIDE内でサクッとDocker imageの Build と run が行われるので便利。コマンドラインでやった場合は以下のようになる
% docker build -t wadai-crawler .
% docker run wadai-crawler
['コメダ和喫茶', 'オオタニサン', '郵便切手', '50人', '池江璃花子', 'ポケモン切手', '日本列島', '岡庭由征容疑者', '與座', 'AKI', 'デニー知事', 'おかげ庵',, 'スーパードライ 生ジョッキ缶', 'ミーグリ', '木村佳乃']
記事が長くなりそうなので、一旦、準備編として次の記事に本編を書きます。
