前回のつづき。
方法
1. 同一ソースの別カテゴリRSSを統合する。
stdinでRSSリストを渡す- 1を指定したDBへ統合する
echo -e "RSS1\nRSS2\nRSS3" | ./run.sh /任意パス/news.db
RSSの統合はSQLite3ファイルを分けることで対応する。テーブルにsource列を増やすと前回のように面倒になるため避ける。
もしRSSリストをファイルに保存しているなら、以下のようにする。
cat rss_list.txt | ./run.sh /任意パス/news.db
./run.shを./get_news.pyで動くようにしたほうが早いかもしれない。その場合はPythonでstdinを取得する方法を調べる。
echo -e "RSS1\nRSS2\nRSS3" | python3 get_news.py /任意パス/news.db cat rss_list.txt | python3 get_news.py /任意パス/news.db
2. 重複チェックとHTML取得最少化
メモリを使って高速化やフラグメンテーション回避を狙う。
:memory:→RAMディスクDB→ファイルDB
それぞれを以下のように別DBとしてattachして名付けたものとする。
attach ':memory:' as m; attach '/RAMディスク/news.db' as r; attach '/永続ディスク/news.db' as f;
2-1. インメモリDB
:memory:でインメモリDBを作り、そこで別カテゴリRSSを統合させる方法。
- 同一ソース源の別カテゴリRSSから取得したニュースを統合する:
:memory:insert or ignore m.news ... - DB内最新を取得する(統合ニュースから重複を削除):
./news.dbselect max(published) from f.news; - URLからHTML取得し本文抽出する
- DBへマージする:
:memory:update m.news set body=? where published=? and url=? - DBへマージする:
./news.dbinsert or fail into f.news(...) select ... from m.news;
2-2. RAMディスクDB
さらにRAMディスクDBファイルを作る方法。ニュース取得のプロセス終了後でも、電源ON〜OFFまでの間に得たニュースだけを見れる。場合によっては、そこから選択したニュースだけをファイルDBへ登録させても良い。
- 同一ソース源の別カテゴリRSSから取得したニュースを統合する:
:memory:insert or ignore m.news ... - DB内最新を取得する(統合ニュースから重複を削除):
RAMディスク/news.dbselect max(published) from r.news; - URLからHTML取得し本文抽出する
- DBへマージする:
:memory:update m.news set body=? where published=? and url=? - DBへマージする:
RAMディスク/news.dbinsert or fail into r.news(...) select ... from m.news; - DBへマージする:
./news.dbinsert or fail into f.news(...) select ... from m.news;
2-3. RSS用DB(RAMディスク)
上記までだと、本文抽出が完了するまでRSSが見れない。10分後かもしれない。もっと早く応答が欲しい。RSSだけ別DBにする。それをRAMディスクに配置する。
create table rss( published text not null, url text not null, title text not null, description text not null default '', UNIQUE(published,url) -- 記事の一意確認 );
2-4. 通知
本文が抽出されるには時間がかかる。完了したら通知して欲しい。
zenity --notification ...
フローを細かく
- インメモリDB
- ニュースが重複しうる複数のRSSをマージする
published,url,titleを取得する- それらが重複するものははじく
- ソートする:
order by published desc, url asc, id desc
- ニュースが重複しうる複数のRSSをマージする
- ファイルDB
- インメモリDBのうちファイルDBとの重複がないか探す
- 見つかれば、それ以前までのニュースのみ取り込む
[(published, url, title), ...]のうち重複ニュースを切り捨てる
- RSS用RAMディスクDBに挿入する
[(published, url, title), ...]
- 見つかれば、それ以前までのニュースのみ取り込む
- 本文を抽出する
[(published, url, title, body), ...]を生成する- ファイルDBに挿入する
- インメモリDBのうちファイルDBとの重複がないか探す
insertには時間がかかるためexecutemany()で一括挿入したい。だが、そのために全URLのHTML取得を完了させねばならない。そこに最も時間がかかる。
最初の1件目だけを、できるだけ早く見ることができれば嬉しい。だが、それだと挿入が遅くなる。RAMディスクに一時DBを作って、そこに1件ずつ挿入すればいいかもしれない。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13 ※
- bash 4.4.12(1)-release ※
- Python 3.5.3
- SQLite 3.29.0 ※
- MeCab 0.996ユーザ辞書
$ uname -a Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux