1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

記事投稿キャンペーン 「2024年!初アウトプットをしよう」

Python3 標準モジュールだけで feed 取得

Last updated at Posted at 2024-01-12

目標

Qiita の Feed から、直近の投稿記事のタイトル、URL、日付を取得する。それを、Python 標準モジュールだけで (つまり pip を使うことなく) 実現する。

URL 例: https://qiita.com/aKuad/feed

要素技術

Feed 取得

HTTP GET リクエストして、body を受け取りたいです。そこで urllib が使えます。

from urllib.request import urlopen

feed = urlopen("https://qiita.com/aKuad/feed")
feed_text = feed.read().decode("utf-8")

print(feed_text)

ちなみに公式リファレンスでは、より高水準なインターフェースとして、pip から入れられる requests が推奨されています。ただ、ここではシンプルな HTTP GET しかしないので、これで十分です。

Feed パース & 要素取得

Feed は XML 形式で記述されています。XML ライブラリも標準にあります。

from xml.dom.minidom import parseString

feed_text = """
<feed>
  <entry>
    <title>Title1</title>
  </entry>
  <entry>
    <title>Title2</title>
  </entry>
</feed>"""

dom = parseString(feed_text)
items = dom.getElementsByTagName("entry")

for item in items:
  title = item.getElementsByTagName("title")[0].firstChild.data
  print(title)
  # Title1
  # Title2

最後の title タグの中を取得する部分がどうも不格好になってしまいましたが、これ以上キレイな手は自分には見つかりませんでした。orz

初めは xml.etree.ElementTree を試したのですが、どうも上手くいかなかったので minidom を使う方法でやりました。

公式リファレンスで、この XML パーサには脆弱性があるとされています。ただ、ここでは決まった XML しか扱わないので問題ないとしています。もし、ユーザ任意の XML を入れる形を検討している場合は注意が必要です。

ついでに dataclass

C で言う構造体的なもの。

from dataclasses import dataclass

@dataclass
class ArticleInfo:
  title: str
  url: str
  date: str

article = ArticleInfo("title text", "https://qiita.com", "2024-01-10T23:00:19+09:00")

print(article)
# ArticleInfo(title='title text', url='https://qiita.com', date='2024-01-10T23:00:19+09:00')

普通の Class と違うのは、print すると値が表示されること、初期化関数で値を代入するコードがいらないことです。

ちなみに普通の Class だと
class ArticleInfo:
  def __init__(self, title: str, url: str, date: str):
    self.title = title
    self.url   = url
    self.date  = date

article = ArticleInfo("title text", "https://qiita.com", "2024-01-10T23:00:19+09:00")

print(article)
# <__main__.ArticleInfo object at 0x7fa72fe37970>

完成品

以上を組み合わせ、関数化とかしたものがこちら。

# coding: UTF-8

from urllib.request import urlopen
from xml.dom.minidom import parseString
from dataclasses import dataclass

@dataclass
class ArticleInfo:
  title: str
  url: str
  date: str


def fetch_qiita_feed(user_id: str):
  feed = urlopen(f"https://qiita.com/{user_id}/feed")
  feed_text = feed.read().decode("utf-8")

  dom = parseString(feed_text)
  items = dom.getElementsByTagName("entry")

  articles = []
  for item in items:
    title = item.getElementsByTagName("title"    )[0].firstChild.data
    url   = item.getElementsByTagName("url"      )[0].firstChild.data
    date  = item.getElementsByTagName("published")[0].firstChild.data
    articles.append(ArticleInfo(title, url, date))

  return articles


if __name__ == "__main__":
  articles = fetch_qiita_feed("aKuad")

  for article in articles:
    print(article)
ArticleInfo(title='ユニットテストするならフレームワーク使おう (Python unittest)', url='https://qiita.com/aKuad/items/c01ef064603ac30e03fb', date='2024-01-10T23:00:19+09:00')
ArticleInfo(title='.service 自作して Python プログラムを systemd でデーモン化', url='https://qiita.com/aKuad/items/c702b508375a5d9c476b', date='2023-12-03T00:07:29+09:00')
ArticleInfo(title='Arduino Uno / atmega328p の SPI Slave ライブラリを自作する', url='https://qiita.com/aKuad/items/3d06998efc59daedd4c5', date='2023-11-12T16:02:11+09:00')
ArticleInfo(title='ESP32 マイコン を PlatformIO で動かす (on Linux Mint)', url='https://qiita.com/aKuad/items/eca015f2dcfd8bd57791', date='2023-11-08T22:47:41+09:00')

ところで何がしたかった?

本当に急な思いつきで、こんなことを考えました。

「GitHub Pages に自分の Web ページ作ったとして、そこに Qiita とか Zenn の直近の投稿を表示させられたりするかな?せや、Python で Feed 収集するのを GitHub Actions で定期実行したらできそうやん。」

まぁ、まだ Web ページ作成計画すら無いんですけど・・・。

あと Actions 上で pip 呼ぶのは何ら難しくないので、普通に拡張ライブラリ使い放題。標準モジュールにこだわる必要はほぼほぼありません。せいぜい実行時間が数秒ほど短くなるだけ。

おわり

えーっと、とりあえず、Python は標準モジュールだけでも割と色々できそうって話。

あと、Feed は古い技術ではありますが、単純で扱いやすいおかげで、こういう用途にとても適していると思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?