nemlogの新着記事のタイトルとURLを取得する方法を簡単に紹介します。
この手法はスクレイピングを使っていますので、もし、ご紹介したコードをご利用する前、にnemlog管理者の「しゅうさん」に必ず了解を得ましょう。
私は忘れてしまったので、事後報告とともに「しゅうさん」にご連絡するつもりです。
許可をいただきました!
動作確認はUbuntu 20.04LTSで行っています。
(venv) nao@330:~/naoland/advent20201220$ neofetch
.-/+oossssoo+/-. nao@330
`:+ssssssssssssssssss+:` -------
-+ssssssssssssssssssyyssss+- OS: Ubuntu 20.04.1 LTS x86_64
.ossssssssssssssssssdMMMNysssso. Host: 81D0 Lenovo ideapad 330-14IGM
/ssssssssssshdmmNNmmyNMMMMhssssss/ Kernel: 5.4.0-58-generic
+ssssssssshmydMMMMMMMNddddyssssssss+ Uptime: 1 day, 15 hours, 47 mins
/sssssssshNMMMyhhyyyyhmNMMMNhssssssss/ Packages: 1684 (dpkg), 15 (snap)
.ssssssssdMMMNhsssssssssshNMMMdssssssss. Shell: bash 5.0.17
+sssshhhyNMMNyssssssssssssyNMMMysssssss+ Resolution: 1366x768
ossyNMMMNyMMhsssssssssssssshmmmhssssssso Terminal: /dev/pts/0
ossyNMMMNyMMhsssssssssssssshmmmhssssssso CPU: Intel Celeron N4100 (4) @ 2.400GHz
+sssshhhyNMMNyssssssssssssyNMMMysssssss+ GPU: Intel UHD Graphics 605
.ssssssssdMMMNhsssssssssshNMMMdssssssss. Memory: 2427MiB / 3758MiB
/sssssssshNMMMyhhyyyyhdNMMMNhssssssss/
+sssssssssdmydMMMMMMMMddddyssssssss+
/ssssssssssshdmNNNNmyNMMMMhssssss/
.ossssssssssssssssssdMMMNysssso.
-+sssssssssssssssssyyyssss+-
`:+ssssssssssssssssss+:`
.-/+oossssoo+/-.
Python環境は導入済みであることを前提として、以降の説明をすすめていきます。
JavaScriptによって動的に生成される新着記事を取得するために、Pythonパッケージをインストールします。
pip install requests_html
pipは事前にアップデートしておいた方がよいかもしれません。 また、不足しているUbuntuのパッケージ(主に開発用)があるかもしれませんが、その場合はエラーが表示されますので、必要なパッケージをインストールしましょう。
次のPythonコードをgetnewpost.py
として任意の場所に保存してください
"""nemlogの新着記事を1件取得して`dict`型の変数に格納します"""
from requests_html import HTMLSession, AsyncHTMLSession
newpost: dict = {}
# セッション開始
session = HTMLSession()
url = "https://nemlog.nem.social/guest"
r = session.get(url)
# HTMLを生成
r.html.render(timeout=30) # デフォルトだとタイムアウトが頻発する
selector = "div.blog-card-wrapper"
items = r.html.find(selector, first=False)
for i in items:
title = i.text.splitlines()[2]
url = list(i.absolute_links)[0]
newpost = {"title": title, "url": url}
break # 1件だけ
print(f"新着ポスト: {newpost}")
このコードでは説明の便宜上、適切なエラー処理を行っていません。
次のようにコードを実行します。
python getnewpost.py
初回のプログラム実行時には、ヘッドレスchromiumがダウンロードされます。
[W:pyppeteer.chromium_downloader] start chromium download.
Download may take a few minutes.
100%|███████████████████████████████████████████████████████████████████████████████████████████| 108773488/108773488 [03:24<00:00, 531491.68it/s]
[W:pyppeteer.chromium_downloader]
chromium download done.
しかし、初回のプログラム実行時には次のようにタイムアウトエラーが発生するかもしれません。
(venv) $ python getnewpost.py
Traceback (most recent call last):
File "getnewpost.py", line 9, in <module>
r.html.render(timeout=30) # デフォルトだとタイムアウトが頻発する
File "/home/nao/naoland/advent20201220/venv/lib/python3.8/site-packages/requests_html.py", line 598, in render
content, result, page = self.session.loop.run_until_complete(self._async_render(url=self.url, script=script, sleep=sleep, wait=wait, content=self.html, reload=reload, scrolldown=scrolldown, timeout=timeout, keep_page=keep_page))
File "/usr/local/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
return future.result()
File "/home/nao/naoland/advent20201220/venv/lib/python3.8/site-packages/requests_html.py", line 512, in _async_render
await page.goto(url, options={'timeout': int(timeout * 1000)})
File "/home/nao/naoland/advent20201220/venv/lib/python3.8/site-packages/pyppeteer/page.py", line 885, in goto
raise error
pyppeteer.errors.TimeoutError: Navigation Timeout Exceeded: 30000 ms exceeded.
私もタイムアウトエラーが発生したのですが、何度実行しなおしても同じエラーが発生していました
そのため、タイムアウトを30秒に指定しましたが、たまにタイムアウトエラーが発生します。
このコードの正常な実行結果は次のようになります。
(venv) $ python getnewpost.py
新着ポスト: {'title': 'ネムツア12/19 空き時間でランと筋トレ', 'url': 'https://nemlog.nem.social/blog/53235'}
- 今回の記事では新着記事1件のみを取得していますが、お好みの件数分取得したり、前回の記事取得時から更新された分だけ取得するなど、工夫してみるとよいでしょう。
- 定期的に新着記事をチェックすると良いかもしれません。ただし、スクレイピングはnemlogに負担をかけますので、1時間未満の定期チェックは避けるべきです。
- 新着情報をLineやメールなどで通知できるようにすると便利かもしれません。
ご紹介した整理後のコードを見るととても簡単そうに見えますが、作成中はrequests_html
が返すオブジェクトの中身を逐一チェックして調整をおこなっています。
結構面倒くさかったです。
新着記事の箇所を見つけるために、
selector = "div.blog-card-wrapper"
という「CSSセレクター」を指定していますが、「XPath」という方式で指定する方法もあります。
この記事ではスクレイピングについては詳しく説明していませんが、興味のある方はスクレイピング
というキーワードでググってみてください。
いや~、こういう処理にはPython
はもってこいですね!
p.s. 本当はLINEに新着を通知するところまでやりたかったのですが今回は無理でした。おそらくこのリポジトリ内+nemlogで続きを紹介したいと思います。 ただし、「しゅうさん」の了解がとれた場合です。
許可をいただきました!