やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

ニュース取得(重複を軽減)

 RAMディスク上で同ソース別カテゴリフィードのエントリを統合する。

成果物

統合

Python 管理内容 保存場所
FeedsDb.py フィードごとの最新公開日時 RAMディスク or 永続ディスク
NewsSummaryDb.py 統合したフィードのデータ RAMディスク
NewsDb.py ニュース(抽出した本文を含む) 永続ディスク
  1. feedsのデータを用いてnews_summaryの登録を公開日時で限定する
  2. news_summaryでソースを統合する(方法は後述)
  3. news_summaryのURLから本文を抽出して、news表へ登録する(UNIQUE(url,title), insert or ignore ...

 フィードのエントリは3つのテーブルを用いて3段構えで「重複なく全ニュースを取得する」ことを実現する。

コード

 前回を基礎にする。

NewsSummaryDb.py

class NewsSummaryDb:
    ...
    def __is_exists_sql(self, published, url, title, schema_name=''): 
        return """
select exists(
  select * 
  from {schema_name}news 
  where published='{published}' 
    and url='{url}' and title='{title}') as is_exists;
""".format(schema_name=self.__schema_name(schema_name), 
            published=published, url=url, title=title)
    def is_exists(self, published, url, title):
        result = self.conn.cursor().execute(
            self.__is_exists_sql(published, url, title, self.__schema_ram), 
            ).fetchone()['is_exists']
        return True if 1 == result else False
    ...

get_news.py

...
# 概要(フィード内容)のみ取得
for feed in feeds:
    latest_published = feedsDb.get_latest(feed)
    for entry in entries:
        ...
        if latest_published is not None and published < latest_published: break
        if summaryDb.is_exists(published, url, title): continue
        ...
...

 本文の前にフィードのエントリを取得する。このとき、前回フィード取得時の最終更新日時より古いなら中断される。また、同日時でありながら異なるURLとタイトルを持つエントリに関しては登録する。ただし日時、URL、タイトルが同じエントリが既存ならスキップする。

既知のバグ

  • 「続きを読む」から本文を抽出できないことがある。なぜか同じサイト構成であっても。

 関係あるかわからんが、BeautifulSoup4.4.0以降はtext=でなくstring=らしい。

before

soup.find('a', text=self.__re_more_link)

after

soup.find('a', string=self.__re_more_link)

所感

 ほぼ完成。でもテストしてない。無駄に複雑なのが気がかり。

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux